Skip to content

Commit 716b941

Browse files
committed
Added ERC20 UIDF
1 parent 0137814 commit 716b941

File tree

5 files changed

+327
-0
lines changed

5 files changed

+327
-0
lines changed

indexer/modules/custom/erc20_token_transfer/__init__.py

Whitespace-only changes.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from dataclasses import dataclass
2+
from datetime import datetime
3+
from indexer.domain import Domain, FilterData
4+
5+
@dataclass
6+
class ERC20Transfer(FilterData):
7+
token_address: str
8+
from_address: str
9+
to_address: str
10+
value: int
11+
block_number: int
12+
block_timestamp: datetime
13+
transaction_hash: str
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import logging
2+
from typing import List
3+
4+
from common.utils.web3_utils import ZERO_ADDRESS
5+
from indexer.domain.log import Log
6+
from indexer.domain.token_transfer import TokenTransfer, extract_transfer_from_log
7+
from indexer.jobs.base_job import FilterTransactionDataJob
8+
from indexer.modules.custom.erc20_token_transfer.domain.erc20_transfer_time import ERC20Transfer
9+
from indexer.specification.specification import TopicSpecification, TransactionFilterByLogs
10+
from indexer.utils.abi_setting import ERC20_TRANSFER_EVENT
11+
12+
logger = logging.getLogger(__name__)
13+
14+
def _filter_erc20_transfers(logs: List[Log]) -> List[TokenTransfer]:
15+
token_transfers = []
16+
for log in logs:
17+
transfers = extract_transfer_from_log(log)
18+
token_transfers.extend([
19+
transfer for transfer in transfers
20+
if transfer.token_type == "ERC20"
21+
])
22+
return token_transfers
23+
24+
class ERC20TransferJob(FilterTransactionDataJob):
25+
dependency_types = [Log]
26+
output_types = [ERC20Transfer]
27+
able_to_reorg = True
28+
29+
def __init__(self, **kwargs):
30+
super().__init__(**kwargs)
31+
self._contract_list = self.user_defined_config.get("contract_address")
32+
self.logger.info("ERC20 contracts to process %s", self._contract_list)
33+
34+
def get_filter(self):
35+
topic_filter_list = [
36+
TopicSpecification(
37+
addresses=self._contract_list,
38+
topics=[ERC20_TRANSFER_EVENT.get_signature()]
39+
)
40+
]
41+
return TransactionFilterByLogs(topic_filter_list)
42+
43+
def _collect(self, **kwargs):
44+
logs = self._data_buff[Log.type()]
45+
46+
# Filter and process ERC20 transfers
47+
erc20_transfers = _filter_erc20_transfers(logs)
48+
49+
# Convert to our domain model
50+
transfer_records = [
51+
ERC20Transfer(
52+
token_address=transfer.token_address,
53+
from_address=transfer.from_address,
54+
to_address=transfer.to_address,
55+
value=transfer.value,
56+
block_timestamp=transfer.block_timestamp,
57+
block_number=transfer.block_number,
58+
transaction_hash=transfer.transaction_hash,
59+
)
60+
for transfer in erc20_transfers
61+
]
62+
63+
# Collect the transfers
64+
self._collect_domains(transfer_records)
65+
66+
def _process(self, **kwargs):
67+
pass
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from datetime import datetime
2+
from sqlalchemy import Column, Index, PrimaryKeyConstraint, desc, func
3+
from sqlalchemy.dialects.postgresql import BIGINT, BOOLEAN, BYTEA, NUMERIC, TIMESTAMP
4+
5+
from common.models import HemeraModel, general_converter
6+
7+
class ERC20TransferTime(HemeraModel):
8+
__tablename__ = "erc20_transfer_time"
9+
10+
transaction_hash = Column(BYTEA, primary_key=True)
11+
from_address = Column(BYTEA)
12+
to_address = Column(BYTEA)
13+
token_address = Column(BYTEA)
14+
value = Column(NUMERIC(100))
15+
block_timestamp = Column(TIMESTAMP)
16+
block_number = Column(BIGINT)
17+
18+
create_time = Column(TIMESTAMP, server_default=func.now())
19+
update_time = Column(TIMESTAMP, server_default=func.now())
20+
reorg = Column(BOOLEAN, default=False)
21+
22+
@staticmethod
23+
def model_domain_mapping():
24+
return [{
25+
"domain": "ERC20Transfer",
26+
"conflict_do_update": False,
27+
"update_strategy": None,
28+
"converter": general_converter,
29+
}]
30+
31+
# Add useful indexes
32+
Index(
33+
"erc20_transfer_time_block_timestamp_idx",
34+
desc(ERC20TransferTime.block_timestamp)
35+
)
36+
37+
Index(
38+
"erc20_transfer_time_from_address_idx",
39+
ERC20TransferTime.from_address
40+
)
41+
42+
Index(
43+
"erc20_transfer_time_to_address_idx",
44+
ERC20TransferTime.to_address
45+
)

indexer/utils/abi_setting.py

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
"""
4+
Time : 2024/10/12 下午2:10
5+
Author : xuzh
6+
Project : hemera_indexer
7+
"""
8+
from common.utils.abi_code_utils import Event, Function
9+
10+
# log event
11+
WETH_DEPOSIT_EVENT = Event(
12+
{
13+
"anonymous": False,
14+
"inputs": [
15+
{"indexed": True, "name": "dst", "type": "address"},
16+
{"indexed": False, "name": "wad", "type": "uint256"},
17+
],
18+
"name": "Deposit",
19+
"type": "event",
20+
}
21+
)
22+
23+
WETH_WITHDRAW_EVENT = Event(
24+
{
25+
"anonymous": False,
26+
"inputs": [
27+
{"indexed": True, "name": "src", "type": "address"},
28+
{"indexed": False, "name": "wad", "type": "uint256"},
29+
],
30+
"name": "Withdrawal",
31+
"type": "event",
32+
}
33+
)
34+
35+
ERC20_TRANSFER_EVENT = Event(
36+
{
37+
"anonymous": False,
38+
"inputs": [
39+
{"indexed": True, "name": "from", "type": "address"},
40+
{"indexed": True, "name": "to", "type": "address"},
41+
{"indexed": False, "name": "value", "type": "uint256"},
42+
],
43+
"name": "Transfer",
44+
"type": "event",
45+
}
46+
)
47+
48+
ERC721_TRANSFER_EVENT = ERC20_TRANSFER_EVENT
49+
50+
ERC1155_SINGLE_TRANSFER_EVENT = Event(
51+
{
52+
"anonymous": False,
53+
"inputs": [
54+
{"indexed": True, "name": "operator", "type": "address"},
55+
{"indexed": True, "name": "from", "type": "address"},
56+
{"indexed": True, "name": "to", "type": "address"},
57+
{"indexed": False, "name": "id", "type": "uint256"},
58+
{"indexed": False, "name": "value", "type": "uint256"},
59+
],
60+
"name": "TransferSingle",
61+
"type": "event",
62+
}
63+
)
64+
65+
ERC1155_BATCH_TRANSFER_EVENT = Event(
66+
{
67+
"anonymous": False,
68+
"inputs": [
69+
{"indexed": True, "name": "operator", "type": "address"},
70+
{"indexed": True, "name": "from", "type": "address"},
71+
{"indexed": True, "name": "to", "type": "address"},
72+
{"indexed": False, "name": "ids", "type": "uint256[]"},
73+
{"indexed": False, "name": "values", "type": "uint256[]"},
74+
],
75+
"name": "TransferBatch",
76+
"type": "event",
77+
}
78+
)
79+
80+
# ABI function
81+
TOKEN_NAME_FUNCTION = Function(
82+
{
83+
"constant": True,
84+
"inputs": [],
85+
"name": "name",
86+
"outputs": [{"name": "", "type": "string"}],
87+
"payable": False,
88+
"stateMutability": "view",
89+
"type": "function",
90+
}
91+
)
92+
93+
TOKEN_SYMBOL_FUNCTION = Function(
94+
{
95+
"constant": True,
96+
"inputs": [],
97+
"name": "symbol",
98+
"outputs": [{"name": "", "type": "string"}],
99+
"payable": False,
100+
"stateMutability": "view",
101+
"type": "function",
102+
}
103+
)
104+
105+
TOKEN_DECIMALS_FUNCTION = Function(
106+
{
107+
"constant": True,
108+
"inputs": [],
109+
"name": "decimals",
110+
"outputs": [{"name": "", "type": "uint8"}],
111+
"payable": False,
112+
"stateMutability": "view",
113+
"type": "function",
114+
}
115+
)
116+
117+
TOKEN_TOTAL_SUPPLY_FUNCTION = Function(
118+
{
119+
"constant": True,
120+
"inputs": [],
121+
"name": "totalSupply",
122+
"outputs": [{"name": "", "type": "uint256"}],
123+
"payable": False,
124+
"stateMutability": "view",
125+
"type": "function",
126+
}
127+
)
128+
129+
TOKEN_TOTAL_SUPPLY_WITH_ID_FUNCTION = Function(
130+
{
131+
"constant": True,
132+
"inputs": [{"name": "id", "type": "uint256"}],
133+
"name": "totalSupply",
134+
"outputs": [{"name": "", "type": "uint256"}],
135+
"payable": False,
136+
"stateMutability": "view",
137+
"type": "function",
138+
}
139+
)
140+
141+
ERC721_OWNER_OF_FUNCTION = Function(
142+
{
143+
"constant": True,
144+
"inputs": [{"name": "tokenId", "type": "uint256"}],
145+
"name": "ownerOf",
146+
"outputs": [{"name": "owner", "type": "address"}],
147+
"payable": False,
148+
"stateMutability": "view",
149+
"type": "function",
150+
}
151+
)
152+
153+
ERC721_TOKEN_URI_FUNCTION = Function(
154+
{
155+
"constant": True,
156+
"inputs": [{"name": "tokenId", "type": "uint256"}],
157+
"name": "tokenURI",
158+
"outputs": [{"name": "uri", "type": "address"}],
159+
"payable": False,
160+
"stateMutability": "view",
161+
"type": "function",
162+
}
163+
)
164+
165+
ERC1155_MULTIPLE_TOKEN_URI_FUNCTION = Function(
166+
{
167+
"constant": True,
168+
"inputs": [{"name": "tokenId", "type": "uint256"}],
169+
"name": "uri",
170+
"outputs": [{"name": "uri", "type": "address"}],
171+
"payable": False,
172+
"stateMutability": "view",
173+
"type": "function",
174+
}
175+
)
176+
177+
ERC20_BALANCE_OF_FUNCTION = Function(
178+
{
179+
"constant": True,
180+
"inputs": [{"name": "_owner", "type": "address"}],
181+
"name": "balanceOf",
182+
"outputs": [{"name": "balance", "type": "uint256"}],
183+
"payable": False,
184+
"stateMutability": "view",
185+
"type": "function",
186+
}
187+
)
188+
189+
ERC1155_TOKEN_ID_BALANCE_OF_FUNCTION = Function(
190+
{
191+
"constant": True,
192+
"inputs": [
193+
{"name": "account", "type": "address"},
194+
{"name": "id", "type": "uint256"},
195+
],
196+
"name": "balanceOf",
197+
"outputs": [{"name": "balance", "type": "uint256"}],
198+
"payable": False,
199+
"stateMutability": "view",
200+
"type": "function",
201+
}
202+
)

0 commit comments

Comments
 (0)