feat(vault): add user vault events decoding in indexer

This commit is contained in:
Bot
2026-08-31 01:42:38 +08:00
parent b309448293
commit 8e5df08f3a
+39 -14
View File
@@ -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()}")