An overview of the Token price

Token and the price of tokens

Along with the development of blockchain, the cryptocurrency field attracts a lot of attention from investors. Referring to cryptocurrency, it is impossible not to mention a concept called a token, a type of digital asset on the blockchain network. Unlike coins, tokens are created by platforms and applications that are built on an existing blockchain.

Token is a type of digital asset which is priceable and exchangeable. The price of a token is understood as the money it takes to own a unit of the token. This amount is usually expressed in USD or other currency or can also be converted to the number of coins on the underlying blockchain network. Token price represents the value of a unit of this token, not the entire token on the blockchain network. (E.g., 1 LINK = 10 USDT does not mean that ChainLink token is ten times stronger than Tether)

How to price a token?

Determining the price of a token relies on a lot of market factors. Moreover, since each exchange has a different price calculation mechanism, the token price is not the same across exchanges.

To be clear, we consider a simple mechanism of pricing using the Liquidity Pool.

A liquidity Pool combines a pair of 2 different tokens (for example, TRAVA and BNB). The Liquidity Pool allows the exchange of one type's tokens with the other's remaining tokens in the pair. For example, a liquidity pool of TRAVA and BNB allows anyone to exchange TRAVA for BNB and vice versa.

By adding a large amount of two tokens to the pool, we provide liquidity to it. That provides an initial token amount and sets the price for users to exchange. In this case, Liquidity Pool needs to be satisfied some particular requirements:

  • The total value of each token in the pool is equal

price_TRAVA * amount_TRAVA = price_BNB * amount_BNB

(1)

  • The product of the amount of two tokens is always constant (when not changing the liquidity of the pool)

amount_TRAVA * amount_BNB = const

(2)

Therefore, the price of TRAVA is calculated according to the formula:

price_TRAVA = price_BNB * amount_BNB / amount_TRAVA

(3)

When a user exchanges TRAVA for BNB (or vice versa), providing an amount of TRAVA (delta_TRAVA), based on (2), the user receives an amount of BNB:

delta_BNB = amount_BNB * delta_TRAVA / (amount_TRAVA + delta_TRAVA)

(4)

Then, the price of TRAVA decreases according to formula (3):

new_price_TRAVA = price_BNB * const / (amount_A + delta_A)^2

(5)

In this way, we can manually calculate the price of any token based on its Liquidity Pool with another token. In the next section, we look at some APIs that fetch prices from applications that provide prices for different tokens.

APIs

Many centralized and decentralized applications provide information on the price of tokens, either to the application itself, to its users, or to DApps on the blockchain. Notable ones include ChainLink Oracle, PancakeSwap, Coingecko, CoinMarketCap, Trava Token Health, etc.

In the article, we will introduce three of them: ChainLink Oracle, PancakeSwap API, and Coingecko API, focusing on their advantages, disadvantages, and usage instruction.

Oracle ChainLink is known as a Decentralized Oracle, with the function of providing data from the real world to smart contracts on the Blockchain. By using a decentralized network, the ChainLink platform ensures the trustworthiness of data provided from outside the Blockchain.

To get the price of a token, ChainLink provides a smart contract called the Data Feed, which corresponds to the limited number of tokens ChainLink allows. Each token has a corresponding Data Feed Contract address. In this contract, a function is implemented latestRoundData(), that returns some crucial information, including the price of the corresponding token and when it was updated.

In Python, Web3.py is used to retrieve feed data from the data feed contract on the blockchain. Output is the price of the corresponding token and when the price was updated.

def chain_link_price(data_feed_address, provider_uri, block_number):
   w3 = Web3(Web3.HTTPProvider(provider_uri))
   contract = w3.eth.contract(w3.toChecksumAddress(data_feed_address), abi=DATA_FEED_ABI)
   latest_data = contract.functions.latestRoundData().call(block_identifier=block_number)

   decimals = contract.functions.decimals().call()

   price = latest_data[1] / 10 ** decimals
   updated_at = latest_data[3]
   return {'price': price, 'updated_at': updated_at}

In Solidity, to use the price data, your smart contract should reference AggregatorV3Interface, which defines the external functions implemented by Data Feeds.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract PriceConsumerV3 {
   AggregatorV3Interface internal priceFeed;

   /**
    * Network: Binance Smart Chain
    * Aggregator: BNB/USD
    * Address: 0x137924D7C36816E0DcAF016eB617Cc2C92C05782
    */
   constructor() {
       priceFeed = AggregatorV3Interface(0x137924D7C36816E0DcAF016eB617Cc2C92C05782);
   }

   /**
    * Returns the latest price
    */
   function getLatestPrice() public view returns (int) {
       (
           /*uint80 roundID*/,
           int price,
           /*uint startedAt*/,
           /*uint timeStamp*/,
           /*uint80 answeredInRound*/
       ) = priceFeed.latestRoundData();
       return price;
   }
}

Advantage

  • On-chain data, easy to call from smart contract
  • Trusted data by decentralized management
  • Full historical price data has been saved to the blockchain

Disadvantage

  • Querying data from the Blockchain is time-consuming
  • Need to manually map the token with the corresponding Data Feed Contract
  • Only available for a limited number of tokens available

PancakeSwap API

PancakeSwap is a Decentralized Exchange (DEX) according to the Automated Market Makers (AMM) mechanism of the BSC network. On PancakeSwap, users can convert BEP-20 tokens to each other.

The PancakeSwap API is a set of endpoints used by market aggregators (E.g., coinmarketcap.com) to surface PancakeSwap liquidity and volume information. To get the token price data, send a GET request to the URL:

https://api.pancakeswap.info/api/v2/tokens/<token_address>

In this case, <token_address> is the address on the BSC network of the token that needs to be priced. The returned data includes price update time, name, symbol, and price of the input token.

PancakeSwap API also allows to retrieval of data of from multiple tokens simultaneously. Specifically, the following API will return information, including the price of the top 1000 tokens on PancakeSwap:

https://api.pancakeswap.info/api/v2/tokens

To get the price of some tokens interested, you can simply filter the return of the above API by the token's address.

In Python, use requests library to send GET requests and retrieve data such as the following example:

base_url = 'https://api.pancakeswap.info/api/v2/tokens/'

def get_price(token_address):
   url = base_url + token_address
   try:
       response = requests.get(url)
       if response.status_code != 200:
           raise requests.RequestException()

       data = response.json()
   except Exception as ex:
       logger.exception(ex)
       return

   price = float(data['data']['price'])
   updated_at = int(data['updated_at'] / 1000)
   return {'price': price, 'updated_at': updated_at}

Advantage

  • Simple to use. Just provide the token's address
  • Fast API with low response time
  • Provides information on a large number of tokens exchanged on PancakeSwap

Disadvantage

  • Unable to query historical data on price
  • Only tokens on the BSC network are supported
  • Less flexible when querying many tokens

Note: The API returns are cached every five minutes. The returned data may not be accurate at the current time.

Coingecko API

Coingecko is a market aggregator that provides information about the price and trading volume of tokens on centralized and decentralized exchanges. Coingecko currently tracks over 13000 tokens and over 500 exchanges.

The interface of Coingecko can be divided into 2 main components:

One is the token list dashboard, which is also the home page. Here, we have an overview of the entire cryptocurrency market, with basic information on each token, including price, market cap, trading volume, and price change in 1h, 24h, and 7d. Base on that, you can see how the market is changing.

The second is the detailed information page of each coin. In addition to the basic information, charts of this information over time are also displayed. In addition, there are statistics, changes, and trading activities of that token on exchanges.

Instead of using an interface, Coingecko provides a list of API endpoints that allow querying the data to be exposed to the interface.

Coingecko identifies each token with an identifier called coin_id, a unique identifier generated by Coingecko based on the token's name and symbol. To get the data of a token, use the corresponding coin_id. We are interested in two APIs that are used to get the token's data:

  • API to get data of one or more tokens: /coins/markets

Take as input one or more coin_ids. The returned data includes the price, market cap, trading volume, etc., of the input tokens

  • Token past data API: /coins/<coin_id>/market_chart

Take as input the coin_id of the token and the past time period to get data in days. The returned data includes information about price, trading volume, and market cap over a period of time. The granularity of the result depends on the input period. Minutely data will be used for the duration within 1 day, Hourly data will be used for the duration between 1 day and 90 days, and Daily data will be used for duration above 90 days.

GET requests can be sent directly to API endpoints or using Coingecko's built-in libraries depending on the used language, for Python, it is the pycoinecko library.

from pycoingecko import CoinGeckoAPI

class MarketService:
   def __init__(self):
       self.coingecko = CoinGeckoAPI()
       self.coingecko.request_timeout = 15
       self.currency = 'usd'

   def get_market_info(self, coin_id):
       market_info = self.coingecko.get_coins_markets(vs_currency=self.currency, ids=[coin_id])
       price = market_info[0]['current_price']
       market_cap = market_info[0]['market_cap']
       trading_volume = market_info[0]['total_volume']
       return {
           'price': price,
           'market_cap': market_cap,
           'trading_volume': trading_volume
       }

Advantage

  • Flexible API, easy to get both current and historical data
  • A large number of tokens, including lesser-known tokens
  • Data is aggregated across multiple exchanges, better representing the market

Disadvantage

  • Limit the number of requests to 50 requests per minute
  • Use uncommon identifier, only usable with coingecko, need to map token with the corresponding identifier

Conclusion

In this article, we've covered the price of tokens, including a simple way to price tokens and the token pricing APIs. For the valuation of tokens, the Liquidity Pool can be used. There are many ways to get the price of a token, each with its own pros and cons. Depending on the circumstances and requirements of the job, you can choose a suitable API.

Reference

[1] PancakeSwap documentation, docs.pancakeswap.finance, accessed 26th November 2022.

[2] Coingecko documentation, coingecko.com, accessed 26th November 2022.