75 lines
2.7 KiB
Python
75 lines
2.7 KiB
Python
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()
|