How to query a HRC-20 token and its data?

How is it possible to query a HRC-20 token, get its name and associated data, and query it’s current price?

Is this possible using the harmony SDK or API? I have ot been able to find any references to this, the documentation is focused on interacting with wallets - making transactions etc, i don’t need to do that. Simply need to read data from a token.

You can interact with any function that the contract allows via web3 but things such as price are not stored in the contract itself but on 3rd party dexes / cexes.

Ok that makes sense regarding the price, i’ll see if i can pull that from one of the DEXs APIs.

Regarding querying the contract though - can you point me to where that is in the SDK or API documentation, i can’t seem to find anything that demonstrates how to query a HRC-20 token contract address…

Which language?

I can give a very basic example of calling functions using Web3 in Python. Web3 is available in pretty much all mainstream languages and method names are consistent in each.

I suggest you simply do the tutorial in whatever language are comfortable in and get connected with sending a transaction but the basic gist is

  1. make a connection to the chain
  2. create a contract object with the address and abi
  3. interact.
# example calling a normal (call) read function (decimals) that has no cost and
# a write (transaction) function (approve) that charges a fee so requires wallet 
# credentials and a transaction to be built, signed and sent.

from web3 import Web3

# connect to harmony
wss_url = "wss://ws.s0.t.hmny.io"
w3 = Web3(Web3.WebsocketProvider(wss_url))

# ABI with 2 functions `decimals` and `approve` used for the demo
abi = [
    {
        "constant": True,
        "inputs": [],
        "name": "decimals",
        "outputs": [{"internalType": "uint8", "name": "", "type": "uint8"}],
        "payable": False,
        "stateMutability": "view",
        "type": "function",
    },
    {
        "constant": False,
        "inputs": [
            {"internalType": "address", "name": "spender", "type": "address"},
            {"internalType": "uint256", "name": "amount", "type": "uint256"},
        ],
        "name": "approve",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
        "payable": False,
        "stateMutability": "nonpayable",
        "type": "function",
    },
]

# Setup wallet to use
p_key = "WALLET PRIVATE KEY"
wallet = w3.eth.account.privateKeyToAccount(p_key).address
print(wallet)

# Setup token address and create a contract object
token_address = "token contract address 0x..."
contract = w3.eth.contract(address=token_address, abi=abi)

# call decimals function
decimals = contract.functions.decimals().call()
print(decimals) # i.e. 18

def approve(
    amount: int,
    contract: str,
    wallet_address: str,
    private_key: str,
) -> str:

    # Convret to Wei and get nonce
    max_amount = w3.toWei(amount, "ether")
    nonce = w3.eth.getTransactionCount(wallet_address)

    # Build transaction using the function and arguments prior
    tx = contract.functions.approve(wallet_address, max_amount).buildTransaction(
        {
            "from": wallet_address,
            "nonce": nonce,
            "chainId": 1666600000,
            "gasPrice": 1000000000,
            "gas": 25000,
            "value": 0,
        }
    )

    # Sign Tx and send
    signed_tx = w3.eth.account.signTransaction(tx, private_key)
    tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)

    return w3.toHex(tx_hash)

approved_tx_hash = approve(1000000000, contract, wallet, p_key)
print(approved_tx_hash)
# 0x8cda1fa7e08278dca299230c13a5146e4a13393fba235fe1a28d0d828a6c2daf

Thanks - appreciated.

I may be confused, but essentially i want to create a dashboard for our hrc-20 token - which will include the price and price history (in the form of a graph), and stats that include (for example) number of holders, largest purchase today, market cap, total number of tokens, etc.

What is the best way forward to achieve this? I am regular web/web2 programmer that’s pretty new to blockchain coding see and i’m trying to find out where to start.
Interestingly other chains (algo, bsc, etc) have sdk’s that allow me to query the data i’m after (tokens based on their chain), but not harmony? (again i could be misunderstanding this)

The information has to be stored somewhere to access it.

Depending on the composition of your contract, certain information can be obtained from it.

For example, totalSupply is a normal function to return that information. A contract can also store number of holders, amounts etc (or anything you declare) but if it is not in the contract, then of course you cannot grab that information.

If you have not released the contract, maybe it will be useful to include functions and mappings to collate this information.

For trading information / things not stored in the contract., you either need to poll and store information from the chain relating to that contract into your own database (aggregate), create an explorer node that holds the entire chain or make use of 3rd party API’s that may contain such data like Viperswap for example.

Yes that makes sense - data has to be somewhere of course to be able to query, i understand this.

The part i don’t get yet, is that it’s not obvious to me looking at the Harmony SDK / API how i can query our tokens contract? It seems to only cater for wallets, creating a wallet, creating transactions on a wallet etc. Do i have to use a wallet just to query data about a specific hrc-20 token on the harmony chain? (apologies for seemingly sily questions here), and even then, i can’t see anything about where i specify a token contract address to query it.

Again i could be confused. I’m itching to get started on this but there’s something i am not quite understanding.

It depends on the function in the contract.

If it is a view function that is not payable then you are just reading data and that is public and free to access.

If you wish to interact with any writing of information to the contract or it is a payable function (transfer token for example), then gas is required and a transaction has to be created, hence why you need a wallet and actual ONE in that wallet to complete the interaction.

You can see this in the example I posted above… Calling decimals is free and requires no transaction. To call the approve function, requires some writing of data to the blockchain and thus requires a wallet and a transaction + Gas.

For example, in your contract for decimals you will have this. a view (read) that is publically available and returns the decimals. This is free and requires no gas / tx

    uint8 private _decimals = 18;

    function decimals() public view returns (uint8) {
        return _decimals;
    }

For the approve function it is different…

It calls the private method _approve with the method _msgSender() which returns (address payable) this means it requires gas because it is payable :stuck_out_tongue:

    function approve(address spender, uint256 amount) public override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

I won’t be doing any writing, just reading - can you point me to any documentation that describes how to read a hrc-20 token contract? again i can’t see anything in the sdk or api tat allows this.

The only way to read the contract is to have the source code and ABI. then you can access the functions as described above. There is no source code on the blockchain, only ByteCode.

Saying that, most tokens have the same functions as standard… so a normal ERC20 ABI / contract can help with most things…

I tink i’ll need to go back to square one and learn this from the very beginning by the sound of it.

It’s a million miles away from what i’m used to - say, designing a database, writing an API, and building out a front end.

Not really, in all honesty it is very similar! just different syntax …

I view the Contract as the code, Blockchain as the DB and Web3 / RPC as API connections

View is reading (GET) and transactions are writing (POST)

If you copy and paste the example above or do a simple tutorial on WEB3 in the language of your choice, you will soon pick it up from a user perspective.

Writing contracts in Solidity IS a large beast but interacting, especially
with Web3 should not be beyond a normal dev skills

Yes i suppose that’s a good comparison! However, i have used the harmony sdk and api to learn and practice by creating wallets, sending transactions etc - that is all good, and am quite comfortable with that.

The bit i got confused on was (and i say simply, but seemingly not!) simplyto look up a harmony token and get information about it (forget price as i know i can get that elsewhere now) - its name, its holders etc etc.

I am missing something silly here i know it!

There is no on-chain information available… It has to be stored elsewhere.

This is not unique to Harmony of course.

You can get some info from the contract if you have the address and the ABI but you cannot just say, ‘give me a list of tokens’ or give me the abi for a token named ‘MAF’

Anything like that requires a 3rd party or own database and often, contract owners will have to provide the contract source code and ABI.

I would suggest you write a list of what exactly you require and then go through it 1 by 1 and see what is and is not possible… If it is not, it can probably be done somewhere!

I have not had a chance to look at this but maybe you can derive some information from here… that serves explorer.harmony.one

https://ws.explorer-v2-api.hmny.io/