1

I'm trying to decode the input data in a transaction... I've been stuck on this for a while, as I'm really new to using this api. I have written the below example, but I'm getting stuck when loading the ABI to contract. Can someone help me understand the issue here?

import urllib.request, json 
from web3 import Web3

provider = Web3.HTTPProvider('https://mainnet.infura.io/v3/XXXXXXXXXXXXXX')
w3 = Web3(provider)

with urllib.request.urlopen("https://api.etherscan.io/api?module=contract&action=getabi&address=0xC12D1c73eE7DC3615BA4e37E4ABFdbDDFA38907E ") as url:
    ABI = json.loads(url.read())

contract = w3.eth.contract(address='0xC12D1c73eE7DC3615BA4e37E4ABFdbDDFA38907E',abi=ABI)

transaction = w3.eth.getTransaction("0xf9d681d1e759dd56a8a110aca39b6c619234ad609afb021ddeb3f0e8a1c59fc1")
contract.decode_function_input(transaction.input)

The error I'm getting:

ValueError: Could not format value {'status': '1', ....
0

The major issue here is that the HTTP request returns a dict containing 3 keys, one of which holds the value:

{"status":"0", "message":"NOTOK", "result":"Maximum rate limit reached"}

There are two minor issues:

  1. If the "status" key in the response holds the value "0", it indicates that you have exceeded your request limit of 1 request per second (only applicable if you did not supply an API key). Additional informations here.
  2. It's a good practice to also handle HTTP response codes

Fixed code:

import urllib.request, json
from time import sleep
from web3 import Web3

provider = Web3.HTTPProvider('https://mainnet.infura.io/v3/XXXXXXXXXXXXXX')
w3 = Web3(provider)
txid = '0xf9d681d1e759dd56a8a110aca39b6c619234ad609afb021ddeb3f0e8a1c59fc1'
address = '0xC12D1c73eE7DC3615BA4e37E4ABFdbDDFA38907E'
requrl = 'http://api.etherscan.io/api?module=contract&action=getabi&address=' + address

while True:
    with urllib.request.urlopen(requrl) as url:
        if url.code != 200:
            # TODO: Error handling
            raise NotImplementedError('I don\'t know how to handle HTTP code {} :('.format(url.code))
        else:
            result = json.loads(url.read())

            if result['status'] == '1':
                abi = json.loads(result['result'])
                break

            # In this scenario status is only not 1 if you used your 1 req/sec. (25 Feb. 2020)
            sleep(1)

contract = w3.eth.contract(address=address, abi=abi)
transaction = w3.eth.getTransaction(txid)
contract.decode_function_input(transaction.input)
| improve this answer | |
  • thanks a lot for your feedback... I'll work on all your suggestions... It worked... can't believe it, it's amazing... hopefully this post will help others decode transactions with python... since I couldn't find fully usable code out there... – KALEB Feb 24 at 23:46
  • @AceCal Glad I could help. I also hope that your example can help others. Have a good time! – sea212 Feb 24 at 23:53
0

I think you need first to verify your smart contract here, then you need also to provide your API KEY

https://api.etherscan.io/api?module=contract&action=getabi&address=0xC12D1c73eE7DC3615BA4e37E4ABFdbDDFA38907E&apikey=YOUR_API_KEY_HERE

| improve this answer | |
  • thanks for your reply... Other than the missing API key, the ABI format needs to be in a string inside a list kind of format as well, while with the method above it's imported directly as a python dict – KALEB Feb 24 at 23:22

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.