feat(vault): add user vault events decoding in indexer
This commit is contained in:
+39
-14
@@ -8,8 +8,42 @@ from src.core.abis import CONTROLLER_ABI, MARKET_ABI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Vault Factory & User Vault Events ABI
|
||||
VAULT_EVENTS_ABI = [
|
||||
{
|
||||
"anonymous": False,
|
||||
"inputs": [
|
||||
{"indexed": True, "name": "user", "type": "address"},
|
||||
{"indexed": True, "name": "vault", "type": "address"},
|
||||
{"indexed": False, "name": "vaultIndex", "type": "uint256"}
|
||||
],
|
||||
"name": "VaultCreated",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": False,
|
||||
"inputs": [
|
||||
{"indexed": True, "name": "token", "type": "address"},
|
||||
{"indexed": True, "name": "from", "type": "address"},
|
||||
{"indexed": False, "name": "amount", "type": "uint256"}
|
||||
],
|
||||
"name": "Deposited",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": False,
|
||||
"inputs": [
|
||||
{"indexed": True, "name": "token", "type": "address"},
|
||||
{"indexed": True, "name": "to", "type": "address"},
|
||||
{"indexed": False, "name": "amount", "type": "uint256"}
|
||||
],
|
||||
"name": "Withdrawn",
|
||||
"type": "event"
|
||||
}
|
||||
]
|
||||
|
||||
class EVMDecoder:
|
||||
"""EVM ABI 日志规范化解码器 (Layer 2: Decoding)"""
|
||||
"""EVM ABI 日志规范化解码器 (包含 Controller, Market 与 User Vault)"""
|
||||
|
||||
def __init__(self, chain_id: int):
|
||||
self.chain_id = chain_id
|
||||
@@ -19,8 +53,7 @@ class EVMDecoder:
|
||||
def _build_topic_maps(self):
|
||||
self.event_abi_map = {}
|
||||
|
||||
# 解析 Controller 与 Market ABI 中的 events
|
||||
for abi in CONTROLLER_ABI + MARKET_ABI:
|
||||
for abi in CONTROLLER_ABI + MARKET_ABI + VAULT_EVENTS_ABI:
|
||||
if abi.get("type") == "event":
|
||||
name = abi.get("name")
|
||||
inputs = abi.get("inputs", [])
|
||||
@@ -30,7 +63,6 @@ class EVMDecoder:
|
||||
self.event_abi_map[topic0] = abi
|
||||
|
||||
def decode_log(self, log: Dict[str, Any], block_timestamp: int = 0) -> Optional[NormalizedEvent]:
|
||||
"""将原始 EVM 日志解析为统一的 NormalizedEvent"""
|
||||
topics = log.get("topics", [])
|
||||
if not topics:
|
||||
return None
|
||||
@@ -46,19 +78,16 @@ class EVMDecoder:
|
||||
block_number = log.get("blockNumber", 0)
|
||||
log_index = log.get("logIndex", 0)
|
||||
|
||||
# 解码 Indexed 参数与 Non-Indexed Data
|
||||
payload: Dict[str, Any] = {}
|
||||
indexed_inputs = [i for i in abi.get("inputs", []) if i.get("indexed")]
|
||||
non_indexed_inputs = [i for i in abi.get("inputs", []) if not i.get("indexed")]
|
||||
|
||||
# 1. Indexed topics
|
||||
for idx, inp in enumerate(indexed_inputs):
|
||||
if idx + 1 < len(topics):
|
||||
raw_topic = topics[idx + 1]
|
||||
t_hex = raw_topic.hex() if isinstance(raw_topic, bytes) else raw_topic
|
||||
payload[inp["name"]] = t_hex
|
||||
|
||||
# 2. Non-indexed data
|
||||
data = log.get("data", "0x")
|
||||
if isinstance(data, str) and data.startswith("0x"):
|
||||
data_bytes = bytes.fromhex(data[2:])
|
||||
@@ -79,7 +108,6 @@ class EVMDecoder:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to decode non-indexed data for {event_name}: {e}")
|
||||
|
||||
# 标准化 Event Type
|
||||
type_mapping = {
|
||||
"DeployMarket": "MARKET_DEPLOYED",
|
||||
"SetOutcome": "OUTCOME_RESOLVED",
|
||||
@@ -87,12 +115,9 @@ class EVMDecoder:
|
||||
"Mint": "ORDER_MINT",
|
||||
"Redeem": "ORDER_REDEEM",
|
||||
"Claim": "POSITION_CLAIMED",
|
||||
"SetProtocolFeeRate": "GOV_FEE_RATE_UPDATED",
|
||||
"SetTreasury": "GOV_TREASURY_UPDATED",
|
||||
"SetCentralWallet": "GOV_CENTRAL_WALLET_UPDATED",
|
||||
"SetCreatorShare": "GOV_CREATOR_SHARE_UPDATED",
|
||||
"Paused": "PROTOCOL_PAUSED",
|
||||
"Unpaused": "PROTOCOL_UNPAUSED",
|
||||
"VaultCreated": "VAULT_CREATED",
|
||||
"Deposited": "VAULT_DEPOSITED",
|
||||
"Withdrawn": "VAULT_WITHDRAWN"
|
||||
}
|
||||
|
||||
normalized_type = type_mapping.get(event_name, f"EVM_{event_name.upper()}")
|
||||
|
||||
Reference in New Issue
Block a user