web3.py – Getting Transaction Status, Amounts, and Details with Web3.py

web3.py

I am having trouble interpreting transaction from web3.py w3.eth.get_transaction

Take this as example, it's a Swap transaction for example: Swapping USDT for USDC, then USDC for SINGLE
https://cronos.org/explorer/tx/0xaba4f0d9fb2606cab22328ea98297526e5ac4f98358e7fcceb098b755d8290ad/token-transfers

enter image description here

If I call web3.py w3.eth.get_transaction:

trx = w3.eth.getTransaction('0xaba4f0d9fb2606cab22328ea98297526e5ac4f98358e7fcceb098b755d8290ad')

The result is a bunch of gibberish in Bytes:
enter image description here

How can I decode the Bytes back into:

a. Type of transaction: Swap? Burn? Mint?

b. Sender and Recepient address

c. Amount in (In USDT), Amount out (In SINGLE)?

d. Status = Still pending? Or Success?

As partial solution, for "Status", we can check as follows:

from web3.exceptions import TransactionNotFound
trx_hash = '0xaba4f0d9fb2606cab22328ea98297526e5ac4f98358e7fcceb098b755d8290ad'
trx = w3.eth.getTransaction(trx_hash) # This only means you sent the transaction. It does not mean it succeeded.
status : int = -1
while True:
    '''
    https://web3py.readthedocs.io/en/stable/web3.eth.html#methods
    Returns the transaction receipt specified by transaction_hash. If the transaction has not yet been mined throws web3.exceptions.TransactionNotFound.
    If status in response equals 1 the transaction was successful. If it is equals 0 the transaction was reverted by EVM.
    ''' 
    try:
        trx_receipt = w3.eth.getTransactionReceipt(trx_hash)
        status = trx_receipt['status']
        if status == 0 or status == 1:
            break
    except TransactionNotFound:
        # Transaction not found!
        pass

Format of trx_receipt as follows, notably it contains: status and gasUsed
enter image description here

But I still need wait to find things like transaction type, amount_in, amount_out, time it took for tran, sender/receiver wallet address …etc

Related to: web3 + Liquidity Pool on CRONOS chain: How to you fetch all transactions (swap, mint, burn) of a Liquidity Pool?

https://discord.com/channels/435685690936786944/950963287141519420/970513522905739314

Best Answer

Problem solved, you'd need to parse event logs for event type "Transfer" (For the example given), not "Swap":

from typing import Dict
from web3 import Web3
from web3.exceptions import TransactionNotFound

ONE_BILLION : int = 1000000000

cronos_mainnet_rpc = "https://evm.cronos.org"
w3 = Web3(Web3.HTTPProvider(cronos_mainnet_rpc))

pool_address = Web3.toChecksumAddress("0x0fBAB8A90CAC61b481530AAd3a64fE17B322C25d")
pool_abi = '[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Burn","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"amount0","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount1","internalType":"uint256","indexed":false},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Mint","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"amount0","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount1","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Swap","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"amount0In","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount1In","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount0Out","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount1Out","internalType":"uint256","indexed":false},{"type":"address","name":"to","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Sync","inputs":[{"type":"uint112","name":"reserve0","internalType":"uint112","indexed":false},{"type":"uint112","name":"reserve1","internalType":"uint112","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DOMAIN_SEPARATOR","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MINIMUM_LIQUIDITY","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"PERMIT_TYPEHASH","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"amount0","internalType":"uint256"},{"type":"uint256","name":"amount1","internalType":"uint256"}],"name":"burn","inputs":[{"type":"address","name":"to","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factory","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint112","name":"_reserve0","internalType":"uint112"},{"type":"uint112","name":"_reserve1","internalType":"uint112"},{"type":"uint32","name":"_blockTimestampLast","internalType":"uint32"}],"name":"getReserves","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_token0","internalType":"address"},{"type":"address","name":"_token1","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"kLast","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"uint256","name":"liquidity","internalType":"uint256"}],"name":"mint","inputs":[{"type":"address","name":"to","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nonces","inputs":[{"type":"address","name":"","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"permit","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"price0CumulativeLast","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"price1CumulativeLast","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"skim","inputs":[{"type":"address","name":"to","internalType":"address"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"swap","inputs":[{"type":"uint256","name":"amount0Out","internalType":"uint256"},{"type":"uint256","name":"amount1Out","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"sync","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"token0","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"token1","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}],"constant":false}]' 
pool_contract = w3.eth.contract(address=pool_address, abi=pool_abi)

trx_hash = '0xaba4f0d9fb2606cab22328ea98297526e5ac4f98358e7fcceb098b755d8290ad'
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:
        '''
        https://web3py.readthedocs.io/en/stable/web3.eth.html#methods
        Returns the transaction receipt specified by transaction_hash. If the transaction has not yet been mined throws web3.exceptions.TransactionNotFound.
        If status in response equals 1 the transaction was successful. If it is equals 0 the transaction was reverted by EVM.
        '''
        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
            '''
            Note here, we are checking "Transfer" events! Not "Swap"! That's the confusing bit!
            '''
            logs = pool_contract.events.Transfer().processReceipt(trx_receipt, EventLogErrorFlags.Warn)
            for log in logs:
                transaction_type = log.event
                sender_address = log.args['from']
                destination_address = log.args['to']
                amount = log.args['value']

                logs_summary.append( {
                    'transaction_type' : transaction_type,
                    'sender_address' : sender_address,
                    'destination_address' : destination_address,
                    'amount' : amount
                })

            gas_used_in_units = trx_receipt['gasUsed']
            gas_price = w3.eth.gasPrice
            gas_used_in_wei = gas_used_in_units * gas_price
            gas_used_in_coin = gas_used_in_wei / (ONE_BILLION * ONE_BILLION)
            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,
    'gas' : {
        'gas_used_in_units' : gas_used_in_units,
        'gas_price' : gas_price,
        'gas_used_in_wei' : gas_used_in_wei,
        'gas_used_in_coin' : gas_used_in_coin # On CRONOS, "Coin" refers to CRO. On Ethereum, this is ETH.
    },
    'logs' : logs_summary
}

print(transaction_report)