import logging from decimal import Decimal from typing import Optional, Dict, Any from web3 import AsyncWeb3, AsyncHTTPProvider from eth_account import Account from app.config import settings logger = logging.getLogger(__name__) class RelayerService: """ 【WTFX Relayer 链上代付撮合服务】 代表持有 Session Key 授权的用户,将其交易免 Gas 费提交至链上执行 """ def __init__(self): self.w3 = AsyncWeb3(AsyncHTTPProvider(settings.ROBINHOOD_TESTNET_RPC)) # 管理员/Relayer 私钥 self.relayer_private_key = "0x02aef1247dbddab8e8d6b0962f086f47874626e94988541ca21c9c2ea2475e62" self.relayer_account = Account.from_key(self.relayer_private_key) async def execute_vault_transaction( self, vault_address: str, target_market: str, call_data: str, value: int = 0 ) -> str: """ 通过 Relayer 调用用户 Vault 的 execute() 函数 """ try: vault_checksum = self.w3.to_checksum_address(vault_address) target_checksum = self.w3.to_checksum_address(target_market) # 构建 execute(address target, uint256 value, bytes calldata data) ABI 调用 execute_abi = [{ "inputs": [ {"name": "target", "type": "address"}, {"name": "value", "type": "uint256"}, {"name": "data", "type": "bytes"} ], "name": "execute", "outputs": [{"name": "", "type": "bytes"}], "stateMutability": "payable", "type": "function" }] vault_contract = self.w3.eth.contract(address=vault_checksum, abi=execute_abi) nonce = await self.w3.eth.get_transaction_count(self.relayer_account.address) gas_price = await self.w3.eth.gas_price data_bytes = bytes.fromhex(call_data[2:]) if call_data.startswith("0x") else bytes.fromhex(call_data) tx = await vault_contract.functions.execute( target_checksum, value, data_bytes ).build_transaction({ "from": self.relayer_account.address, "nonce": nonce, "gasPrice": gas_price, "chainId": 46630 }) signed_tx = self.relayer_account.sign_transaction(tx) tx_hash = await self.w3.eth.send_raw_transaction(signed_tx.rawTransaction) logger.info(f"Relayer tx submitted: {tx_hash.hex()} for Vault {vault_address}") return tx_hash.hex() except Exception as e: logger.error(f"Failed to execute relayer tx: {e}") raise e relayer_service = RelayerService()