web3.py:contract.events.Transfer().processReceipt - 買還是賣?
讓我們在這裡舉兩個例子,它們是在VVS SINGLE/USDC 流動性池上完成的交換:
**範例 1:**用 SINGLE 購買 USDC(即 SELL SINGLE) https://cronoscan.com/tx/0xbd958b205291355d681cf01fa01f2064078d7be3b1ba63be8a9d2dff72bcce48
**範例 2:**使用 USDC 購買 SINGLE(即 BUY SINGLE) https://cronoscan.com/tx/0x4f8898c244bd7bc7f77d6d8aec7af670ff6d86f252d9d231860dc1528dacf91c
如果您按照步驟使用 contract.events.Transfer().processReceipt 解碼交易,
from typing import Dict from web3 import Web3 from web3.exceptions import TransactionNotFound cronos_mainnet_rpc = "https://evm.cronos.org" w3 = Web3(Web3.HTTPProvider(cronos_mainnet_rpc)) pool_address = Web3.toChecksumAddress("0x0fBAB8A90CAC61b481530AAd3a64fE17B322C25d") pool_abi = '... very long ...' pool_contract = w3.eth.contract(address=pool_address, abi=pool_abi) trx_hash = '0xbd958b205291355d681cf01fa01f2064078d7be3b1ba63be8a9d2dff72bcce48' trx = w3.eth.getTransaction(trx_hash) # This only means you sent the transaction. It does not mean it succeeded. trx_block_number = trx.blockNumber trx_unix_ts = w3.eth.getBlock(trx_block_number).timestamp status : int = -1 while True: try: trx_receipt = w3.eth.getTransactionReceipt(trx_hash) status = trx_receipt['status'] if status == 0 or status == 1: logs_summary = [] from web3._utils.events import EventLogErrorFlags logs = pool_contract.events.Transfer().processReceipt(trx_receipt, EventLogErrorFlags.Warn) for log in logs: transaction_type = log.event log_index = log.logIndex # Each 'log' has different log_index, you can use it to determine which is first and which comes after. transaction_index = log.transactionIndex # But they have same transaction_index! sender_address = log.args['from'] destination_address = log.args['to'] amount = log.args['value'] logs_summary.append( { 'log_index' : log_index, 'transaction_index' : transaction_index, 'transaction_type' : transaction_type, 'sender_address' : sender_address, 'destination_address' : destination_address, 'amount' : amount }) break except TransactionNotFound: # Transaction not found! pass trx_status : str = "Pending" if status==1: trx_status = "Confirmmed" elif status==0: trx_status = "Reverted" transaction_report : Dict = { 'trx_hash' : trx_hash, 'trx_block_number' : trx.blockNumber, 'status' : trx_status, 'trx_unix_ts' : trx_unix_ts, 'logs' : logs_summary }
筆記
- 0x0fBAB8A90CAC61b481530AAd3a64fE17B322C25d 是 VVS/Cronos 鏈上的 SINGLE/USDC 流動性池。
- 0x88D669588b50F3cAa21507Ee5A867f132F9db97C為錢包地址
問題是,從“日誌”(log.args下肯定沒有任何內容),我找不到任何可以告訴我交易是否為買入交易的資訊?或賣出交易。
logs = pool_contract.events.Transfer().processReceipt(trx_receipt, EventLogErrorFlags.Warn)
這一點很重要,因為除了第一個目標,即能夠判斷是買入還是賣出,這些資訊還將幫助我使用 USDC 的小數或 SINGLE 的小數調整“金額”。那將是第二個目標。
web3.py get_transaction 狀態、進出金額、發送方/接收方地址、transaction_type(Swap? Mint? Burn?)、gasUsed 等
交易層面沒有買賣的概念。下面兩個是等價的:
- 使用 USDC 購買 SIMPLE
- 為 SIMPLE 出售 USDC
對於人類可讀的買賣標籤,您需要根據自己的條件來定義買賣。一種這樣的條件可能是“掉期會增加還是減少 USDC 頭寸”。
這些資訊可用於
Swap
事件輸入amount0_out
和amount1_out
參數。
這破案了:
from web3 import Web3 from web3.logs import DISCARD EIP20_ABI = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]' # noqa w3_cro = Web3(Web3.HTTPProvider("https://evm.cronos.org")) generic_token_contract = w3_cro.eth.contract(abi=EIP20_ABI) def get_swap_details(trx_hash): receipt = w3_cro.eth.get_transaction_receipt(trx_hash) sender = receipt["from"] print("##### Swap Trx Hash:", trx_hash, "#####") print("wallet:", sender) events = generic_token_contract.events transfers = events.Transfer().processReceipt(receipt, errors=DISCARD) for t in transfers: args = t["args"] if args['_from'] == sender: direction = "SELLS" elif args['_to'] == sender: direction = "BUYS" else: continue token_address = t["address"] value = args["_value"] token_contract = w3_cro.eth.contract(address=token_address, abi=EIP20_ABI) token_symbol = token_contract.functions.symbol().call() token_decimals = token_contract.functions.decimals().call() print(direction, value / 10**token_decimals, token_symbol) print() if __name__ == "__main__": # Example 1. Single-hop. Buy USDC with SINGLE https://cronoscan.com/tx/0xbd958b205291355d681cf01fa01f2064078d7be3b1ba63be8a9d2dff72bcce48 swap_trx_hash = "0xbd958b205291355d681cf01fa01f2064078d7be3b1ba63be8a9d2dff72bcce48" get_swap_details(swap_trx_hash) # Example 2. Single-hop. Buy SINGLE with USDC https://cronoscan.com/tx/0x4f8898c244bd7bc7f77d6d8aec7af670ff6d86f252d9d231860dc1528dacf91c swap_trx_hash = "0x4f8898c244bd7bc7f77d6d8aec7af670ff6d86f252d9d231860dc1528dacf91c" get_swap_details(swap_trx_hash) # Example 3. Two hops. Buy USDT with SINGLE https://cronoscan.com/tx/0x1b09a08c87a2015a34fa05883cf1005715ff64d90772c044b02f80e646a69951 swap_trx_hash = "0x1b09a08c87a2015a34fa05883cf1005715ff64d90772c044b02f80e646a69951" get_swap_details(swap_trx_hash) # Example 4. Two hops. Buy SINGLE with USDT https://cronoscan.com/tx/0x4eff6d10c7310d272dc999d8c0acffcf18ff43b6802411a069570c43564d5579 swap_trx_hash = "0x4eff6d10c7310d272dc999d8c0acffcf18ff43b6802411a069570c43564d5579" get_swap_details(swap_trx_hash)
輸出 - 它看起來與您在 crono explorer 上看到的相同:
##### Swap Trx Hash: 0xbd958b205291355d681cf01fa01f2064078d7be3b1ba63be8a9d2dff72bcce48 ##### wallet: 0x88D669588b50F3cAa21507Ee5A867f132F9db97C SELLS 8399.685204763235 SINGLE BUYS 107.62197 USDC ##### Swap Trx Hash: 0x4f8898c244bd7bc7f77d6d8aec7af670ff6d86f252d9d231860dc1528dacf91c ##### wallet: 0x88D669588b50F3cAa21507Ee5A867f132F9db97C SELLS 250.0 USDC BUYS 19425.008235644043 SINGLE ##### Swap Trx Hash: 0x1b09a08c87a2015a34fa05883cf1005715ff64d90772c044b02f80e646a69951 ##### wallet: 0x88D669588b50F3cAa21507Ee5A867f132F9db97C SELLS 500.0 SINGLE BUYS 6.393829 USDT ##### Swap Trx Hash: 0x4eff6d10c7310d272dc999d8c0acffcf18ff43b6802411a069570c43564d5579 ##### wallet: 0x88D669588b50F3cAa21507Ee5A867f132F9db97C SELLS 6.393829 USDT BUYS 495.0314116207821 SINGLE