3

How can I track tokens transactions of a list of wallets in the bsc network?

I think about using websocket and filter function. I think it's possible to use the topics as a part of the filter parameters and reflect only the Transfer event to/from watched address, so that my app doesn't have to handle unnecessary data.

But I'm doing something wrong and don't know how to correctly give list of wallets (or at least only one wallet) as a parameter to my filter function. How to do that?

And I have problems with getting data from Transfer event as I don't know how to decode a HexBytes type. I saw web3.js functions for it but nothing with web3.py.

address_list = ['0x67fdE6D04a82689a59E5188f9B572CBeF53D4763', '...', '...']

web3 = Web3(Web3.WebsocketProvider('wss://bsc.getblock.io/mainnet/?api_key=your_api_key'))
web3_filter = web3.eth.filter({'topics': address_list}) 
while True:
    for event in web3_filter.get_new_entries():
        print(web3.toJSON(web3.eth.wait_for_transaction_receipt(event).logs))
TylerH
  • 20,799
  • 66
  • 75
  • 101
R0ixy
  • 91
  • 1
  • 1
  • 5

4 Answers4

6

At last I found the solution. At first I wrote the same code using node.js, because web3.js makes it much simplier for me to understand how it actually works. It has better methods naming, better docs, etc

So back to web.py:

For getting Transfer event signature I used this code transferEventSignature = web3.toHex(Web3.sha3(text='Transfer(address,address,uint256)'))

For encoding/decoding you can use eth_abi library

from web3 import Web3
from eth_abi import encode_abi, decode_abi
from hexbytes import HexBytes

encoded_wallet = (web3.toHex(encode_abi(['address'], [wallet])) # encoding

web3 = Web3(Web3.WebsocketProvider('wss://speedy-nodes-nyc.moralis.io/api-key/bsc/mainnet/ws'))
event_filter = web3.eth.filter({'topics': [transferEventSignature, None, encoded_wallet]}) # setting up a filter with correct parametrs
        while True:
            for event in event_filter.get_new_entries():
                decoded_address = decode_abi(['address'], HexBytes(event.topics[2])) # decoding wallet 
                value = decode_abi(['uint256'], HexBytes(event.data)) # decoding event.data

                tokenContractAddress = event.address

                contractInstance = web3.eth.contract(address=tokenContractAddress, abi=jsonAbi) # jsonAbi is standart erc-20 token abi 
                # I used simplified JSON abi that is only able to read decimals, name and symbol

                name = contractInstance.functions.name().call() 
                decimals = contractInstance.functions.decimals().call()
                symbol = contractInstance.functions.symbol().call()
                # getting any token information

                # doing some useful stuff

GetBlock.io worked for me, but would sometimes get out of sync with the network. I have had better success with this service: https://moralis.io/

I hope somebody will find this usefull.

R0ixy
  • 91
  • 1
  • 1
  • 5
  • Hi ! Thanks for you snippet but I search to do the same in web3js . Can you explain how did you does that please ? I don't find the "logic" behind the hood... thx – Jo Le Belge Sep 30 '21 at 12:20
3

Here is my code to track BEP20 token transactions:

def log_new(event_filter):
    for event in event_filter.get_new_entries():
        handle_event(event)

def handle_event(event):
    receipt =  web3.eth.waitForTransactionReceipt(event['transactionHash'])
    logs = contract.events.Transfer().processReceipt(receipt)

    args = logs[0]['args']

    print ("EVENT", event)
    hashstr = binascii.b2a_hex(event['transactionHash'])
    name = contract.functions.name().call() 
    decimals = contract.functions.decimals().call()
    symbol = contract.functions.symbol().call()

    item = {
        "from": args["from"],
        "to": args.to,
        "value": args.value,
        "blockNumber":event['blockNumber'],
        "transhash":  "0x" + hashstr.decode("ascii"),
        "timeStamp" : get_block_timestamp(event['blockNumber']),
        "tokenSymbol" : symbol, #"KAMPAY"
        "decimals" : decimals,
        "name" : name
    }
    print(item)


block_filter = web3.eth.filter({'fromBlock':'latest','address':MYTOKENADDRESS})
while 1:
    log_new(block_filter)
    time.sleep(1)
Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
Oliver
  • 31
  • 2
0

Bscscan offers apis with free basic usage (5 req/sec)

So for having the list of transactions (there are different types of transactions including normal, internal, bep-20 etc) you could use this.

Sample usage would be this.

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
Abbas Mdemin
  • 1
  • 1
  • 1
0

The bscscan api is not reliable. The problem is that the API is behind a cloudfare DDoS protection and a captcha is asked sometimes. With Python code, there is no way to bypass this captcha check, unfortunately.

Alex Waygood
  • 6,304
  • 3
  • 24
  • 46
Oliver
  • 31
  • 2