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 explainnativeToQuoteSwapEnabled
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, ifnativeToQuoteSwapEnabled
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