Inspect A Token

Previously, you can get a token’s info by calling the getTokenV2 method. We have added a new function called getTokenV3. This new method returns a TokenStateV3 struct, which has two extra fields: quoteTokenAddress and nativeToQuoteSwapEnabled .

  • quoteTokenAddress is the payment token used for trading this token on the bonding curve. If it is zero address, it is the native gas token (i.e BNB on BSC or ETH on ETH L2s). On BSC, we support USD1 and lisUSD as the alternative payment token.

  • nativeToQuoteSwapEnabled : To explain nativeToQuoteSwapEnabled we start from an example. Let's say you create a token with USD1 as the payment token. If you want to trade the token you need to pay USD1 and when you sell the token on the bonding curve, you will receive USD1. However, if nativeToQuoteSwapEnabled is true for this token, you can trade with BNB (i.e, the native gas token). Our smart contract will perform an intermediate swap between BNB and the quote token.


/// @notice the state of a token (with dex related fields)
struct TokenStateV2 {
    TokenStatus status; // the status of the token
    uint256 reserve; // the reserve of the token
    uint256 circulatingSupply; // the circulatingSupply of the token
    uint256 price; // the price of the token
    TokenVersion tokenVersion; // the version of the token implementation this token is using
    uint256 r; // the r of the curve of the token
    uint256 dexSupplyThresh; // the cirtulating supply threshold for adding the token to the DEX
}

/// @notice the state of a token (with all V2 fields plus quoteTokenAddress and nativeToQuoteSwapEnabled)
struct TokenStateV3 {
    /// The status of the token (see TokenStatus enum)
    TokenStatus status;
    /// The reserve amount of the quote token held by the bonding curve
    uint256 reserve;
    /// The circulating supply of the token
    uint256 circulatingSupply;
    /// The current price of the token (in quote token units, 18 decimals)
    uint256 price;
    /// The version of the token implementation (see TokenVersion enum)
    TokenVersion tokenVersion;
    /// The curve parameter 'r' used for the bonding curve
    uint256 r;
    /// The circulating supply threshold for adding the token to the DEX
    uint256 dexSupplyThresh;
    /// The address of the quote token (address(0) if native gas token)
    address quoteTokenAddress;
    /// Whether native-to-quote swap is enabled for this token
    bool nativeToQuoteSwapEnabled;
}    

/// @notice Get token state
/// @param token  The address of the token
/// @return state  The state of the token
function getTokenV2(address token) external view returns (TokenStateV2 memory state);
/// @notice Get token state (V3)
/// @param token  The address of the token
/// @return state  The state of the token (V3)
function getTokenV3(address token) external view returns (TokenStateV3 memory state);

Here is an typescript example for inspecting a token

import { createPublicClient, http, formatEther, Address, zeroAddress } from "viem";
import { bsc as targetChain } from "viem/chains";
import { PORTAL_ABI } from "./abi";
import { Curve } from "./curve";
import Decimal from "decimal.js";
import {FlapConfig} from "./flap-config";



// TokenStatus and TokenVersion enums for display
enum TokenStatus {
    Invalid = 0,
    Tradable = 1,
    InDuel = 2,
    Killed = 3,
    DEX = 4
}
enum TokenVersion {
    TOKEN_LEGACY_MINT_NO_PERMIT = 0,
    TOKEN_LEGACY_MINT_NO_PERMIT_DUPLICATE = 1,
    TOKEN_V2_PERMIT = 2,
    TOKEN_GOPLUS = 3
}

async function inspectToken(tokenAddress: Address) {
    const client = createPublicClient({
        chain: targetChain,
        transport: http(),
    });

    const state = await client.readContract({
        address: FlapConfig.portal,
        abi: PORTAL_ABI,
        functionName: "getTokenV3",
        args: [tokenAddress],
    }) as {
        status: number;
        reserve: bigint;
        circulatingSupply: bigint;
        price: bigint;
        tokenVersion: number;
        r: bigint;
        dexSupplyThresh: bigint;
        quoteTokenAddress: Address;
        nativeToQuoteSwapEnabled: boolean;
    };

    console.log(`\n=== Token: ${tokenAddress} ===`);
    console.log("TokenStateV3:");
    console.log(`  status: ${TokenStatus[state.status] ?? state.status}`);
    console.log(`  reserve: ${formatEther(state.reserve)} QUOTE TOKEN`);
    console.log(`  circulatingSupply: ${formatEther(state.circulatingSupply)}`);
    console.log(`  price: ${formatEther(state.price)}`);
    console.log(`  tokenVersion: ${TokenVersion[state.tokenVersion] ?? state.tokenVersion}`);
    console.log(`  r: ${formatEther(state.r)}`);
    console.log(`  dexSupplyThresh: ${formatEther(state.dexSupplyThresh)}`);
    console.log(`  quoteTokenAddress: ${state.quoteTokenAddress == zeroAddress ? "BNB" : state.quoteTokenAddress}`);
    console.log(`  nativeToQuoteSwapEnabled: ${state.nativeToQuoteSwapEnabled}`);

    // Progress calculation (only if Tradable)
    if (state.status === TokenStatus.Tradable) {
        const r = Number(formatEther(state.r));
        const circulatingSupply = formatEther(state.circulatingSupply);
        const dexSupplyThresh = formatEther(state.dexSupplyThresh);
        const reserve = formatEther(state.reserve);

        const curve = new Curve(r);

        console.log(`The current circulating supply of the token is ${circulatingSupply}`);
        console.log(`The token will be migrated to DEX when the circulating supply reaches ${dexSupplyThresh} or more`);
        console.log(`The current reserve of the token is ${reserve}`);
        console.log(`The token will be migrated to DEX when the reserve reaches ${curve.totalReserve(dexSupplyThresh)} QUOTE TOKEN or more`);

        const reserveProgress = new Decimal(reserve).div(curve.totalReserve(dexSupplyThresh)).mul(100);
        const supplyProgress = new Decimal(circulatingSupply).div(dexSupplyThresh).mul(100);
        const marketCapProgress = curve.mc(reserve).div(curve.fdv(dexSupplyThresh)).mul(100);

        console.log(`The progress in reserve is ${reserveProgress.toFixed(2)}%`);
        console.log(`The progress in circulating supply is ${supplyProgress.toFixed(2)}%`);
        console.log(`The progress in market cap is ${marketCapProgress.toFixed(2)}%`);
    } else if (state.status === TokenStatus.DEX) {
        console.log("The token is already listed on DEX.");
    }
}

async function main() {
    const promies = [
        "0xfb0cea2f88ba45881dce0d90d409f185fd908888",
        "0x800596a37b03688e86285fbd9c33f9cf33082628"
    ].map(async (token) => {
        await inspectToken(token as Address);
    });

    await Promise.all(promies);
}

main().catch(console.error);

Last updated