1

I can filter my events (please see), but instead of that if I know only the transaction hash and if its already deployed, is it possible to obtain and parse the transaction's log data using Web3.py? Please see the solution for web3.js.

=> Is there any web3.eth.abi.decodeLog function under Web3.py?


For example, from receipt we can obtain the logs.data.

> tx = '0x5c7e74a21419a6ff825aca9b54df1a86599b4b1ee82e60e6410e8d54cbb58b2c'    
> web3.eth.getTransactionReceipt(tx).logs
    [{
        address: "0x611dc53934550684825f3477ecb68029b1b908f3",
        blockHash: "0x356829b068046b6d44147663f8bd6c187e9507c578d9ec9d69e65d7a248ff368",
        blockNumber: 1180103,
        data: "0x0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000002e516d52736142454763717851634a6242784369314c4e39697a3562444147445752364878375a76577167716d64520000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007536369656e636500000000000000000000000000000000000000000000000000",
        logIndex: 0,
        removed: false,
        topics: ["0x711007a4be830d68a6d2a7b6546227b676bf9e7d7a0e3c248552ed72cfec2441", "0x0000000000000000000000004e4a0750350796164d8defc442a712b7557bf282"],
        transactionHash: "0x5c7e74a21419a6ff825aca9b54df1a86599b4b1ee82e60e6410e8d54cbb58b2c",
        transactionIndex: 0
    }]

Example log I have is, where string has a dynamic size. If possible, I want to decode web3.eth.getTransactionReceipt(tx).logs[<index>]['data] and web3.eth.getTransactionReceipt(tx).logs[<index>]['topics].

event LogJob(address indexed clusterAddress,
             string indexed key,
             uint index,
             uint8 fileID,
             string desc,
             string hash
             );
  • The transaction exists on my private chain, hence it does not exist on the public ethereum chain that's why. – alper Nov 29 '18 at 21:23
1

From Web3.py documentation:

myContract = web3.eth.contract(address=contract_address, abi=contract_abi)
tx_hash = myContract.functions.myFunction().transact()
receipt = web3.eth.getTransactionReceipt(tx_hash)
logs = myContract.events.myEvent().processReceipt(receipt)

ContractEvent provides methods to interact with contract events. Positional and keyword arguments supplied to the contract event subclass will be used to find the contract event by signature.

-1

Try this function:

def decode(hash,index,params):
    event = {}
    index1 = 1
    index2 = 2
    log = eth.getTransactionReceipt(hash)['logs'][index]
    for param in params:
        if param['indexed']:
            event[param['name']] = int(log['topics'][index1],16)
            index1 += 1
        else:
            size = param['size']//4
            event[param['name']] = int(log['data'][index2:index2+size],16)
            index2 += size
    return event

The structure of the params argument depends on the structure of your event.

For example, if your event is:

event Event(address indexed user, uint256 input, uint256 output)

Then you should use:

params = [
    {'name':'user'  ,'size':160,'indexed':True },
    {'name':'input' ,'size':256,'indexed':False},
    {'name':'output','size':256,'indexed':False},
]

The function assumes a global variable:

eth = Web3(HTTPProvider(ETH_NODE_ADDRESS)).eth
  • Does index stands for transactionIndex and how did you decide integer value for the index, index1 and index2 ? @goodvibration – alper Sep 17 '18 at 14:54
  • @alper: Yes. The first indexed argument in the event is at topics[1], so I initialize index1 = 1. The first two characters in the data are 0x, hence the actual data starts at the third character (whose zero-based index is 2), so I set index2 = 2. – goodvibration Sep 17 '18 at 14:57
  • For the address indexed user I get following output b"q\x10\x07\xa4\xbe\x83\rh\xa6\xd2\xa7\xb6Tb'\xb6v\xbf\x9e}z\x0e<$\x85R\xedr\xcf\xec$A" for web3.eth.getTransactionReceipt(tx).logs[0]['topics'][0]. I cannot do int(.... , 16) which gives following error: invalid literal for int() with base 16 – alper Sep 17 '18 at 15:00
  • Looks like you've got everything encoded in utf-8 or something like that. Or maybe it's web3.py v4 which contains some additional information like event-name and so forth. – goodvibration Sep 17 '18 at 15:06
  • 1
    Please not that, I have to emit string which has a dynamic size. so its a difficult to obtain its size. that will lead me to fail on parse the arguments on your solution. – alper Sep 17 '18 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.