2

I'd like to get the balance of a TRC20 token (in this case the WIN token) for a Tron wallet address that owns WIN tokens.

I'm using the Python module tron-api-python and based on what i've read on GitHub and the docs the code for that should look something like this:

from tronapi import Tron

# Source for ABI: https://tronscan.org/#/token20/TLa2f6VPqDgRE67v1736s7bJ8Ray5wYjU7/code
contract_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":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","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":"account","type":"address"}],"name":"isMinter","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","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"},{"inputs":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"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"}]'

tron = Tron()
contract = tron.trx.contract("TLa2f6VPqDgRE67v1736s7bJ8Ray5wYjU7", abi=contract_abi)
balance = contract.functions.balanceOf("TXRZqGMEXsGTX6AQtcSgYknos93hqw18P7")

print(balance)

But the result i get is:
eth_abi.exceptions.NoEntriesFound: No matching entries for 'address' in encoder registry

Endogen
  • 589
  • 2
  • 12
  • 24

3 Answers3

4

You can use this API:

import requests
import json

def get_balance(address, token_symbol):
  url = "https://apilist.tronscan.org/api/account"
  payload = {
      "address": address,
  }
  res = requests.get(url, params=payload)
  trc20token_balances = json.loads(res.text)["trc20token_balances"]
  token_balance = next((item for item in trc20token_balances if item["symbol"] == token_symbol), None)
  if token_balance == None:
    return 0
  else:
    return int(token_balance["balance"])

The previous response broadcasts a transaction to read a constant function; you don't need to do that if you're only going to read the balance.

carlolm
  • 277
  • 3
  • 14
  • 1
    Thanks! I found out about this too :-) Makes sense to check TRC20 balances that way. One issue is that i found out that if you don't have any TRX in your account, the TRC20 tokens balance will also not be shown which is unfortunate. – Endogen Sep 18 '20 at 12:45
1

Found it myself. This is not the code to get the balance but to send the WIN token so for this to return the balance the function_selector and the parameters would need to change but the rest should be fine since both is based on triggering a smart contract.

tron_kwargs = dict()
tron_kwargs["private_key"] = your_privkey
tron_kwargs["default_address"] = your_base58_address

tron = Tron(**tron_kwargs)

kwargs = dict()
kwargs["contract_address"] = tron.address.to_hex(wink_base58_contract_address)
kwargs["function_selector"] = "transfer(address,uint256)"
kwargs["fee_limit"] = 100000
kwargs["call_value"] = 0
kwargs["parameters"] = [
    {
        'type': 'address',
        'value': tron.address.to_hex(recipients_base58_address)
    },
    {
        'type': 'uint256',
        'value': 8000000
    }
]

raw_tx = tron.transaction_builder.trigger_smart_contract(**kwargs)
sign = tron.trx.sign(raw_tx["transaction"])
result = tron.trx.broadcast(sign)
Endogen
  • 589
  • 2
  • 12
  • 24
0

For example, if you want to get USDT-TRC20 balance:

import requests
import json

def get_balance(address, token_symbol):
    url = "https://apilist.tronscan.org/api/account"
    payload = {"address": address,}
    res = requests.get(url, headers={"TRON-FREE-API-KEY":"your-api-key"}, params=payload)
    #print(res.text)
    trc20token_balances = json.loads(res.text)["trc20token_balances"]
    token_balance = next((item for item in trc20token_balances if item["tokenAbbr"] == token_symbol), None)
    if token_balance == None:
        return 0
    else:
        return int(token_balance["balance"]) / 1000000

out = get_balance('TQiC7LJUtnagUcwzcc6ULRmXiHipf4Tbou','USDT')
print(out)
  • return values have 6 extra zero, then we need to div them to 1000000
  • api-key header, is optional. that just make the response more stable
Eyni Kave
  • 1,113
  • 13
  • 23