Web3.py

web3.py:contract.events.Transfer().processReceipt - 買還是賣?

  • July 26, 2022

讓我們在這裡舉兩個例子,它們是在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_outamount1_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

引用自:https://ethereum.stackexchange.com/questions/132422