Docs menu

Wallet, terminal & bot integration

This page is for anyone displaying or trading Whale.fun tokens from outside the site — a wallet, a chart terminal, a sniper, an aggregator. It covers the four things such an integration always needs: discover tokens, tell what kind of token it is, price it, and trade it. Every ABI referenced here is downloadable as JSON (see the end of the page), generated from the same definitions the site itself uses.

1 · Discover new tokens

Two launch families, two discovery paths. Fixed-price mint launches come from the launch factories, which emit an event and also expose an enumerable array. Bonding-curve launches come from the curve factories, which expose launchCount() and launches(i) — enumeration is usually more reliable than log scanning here, because free BSC log endpoints are heavily rate-limited (in our own measurements only one public endpoint allowed a 5,000-block getLogs range).

// 内盘曲线:枚举(推荐,不依赖 getLogs)
const n = await factory.read.launchCount();
for (let i = 0n; i < n; i++) {
  const token = await factory.read.launches([i]);
  const pool  = await factory.read.poolOf([token]);   // 曲线合约
}

// 固定价铸造:launches(i) 返回结构体,一次拿全
// (token, vault, taxVault, pair, creator, createdAt)
const row = await launchFactoryV2.read.launches([i]);

// ⚠️ 换过工厂 → 必须遍历「当前 + 历代」工厂,否则找不到较早那批币
//   见「已部署地址」页的完整列表与代码

2 · Tell what kind of token you are holding

The order matters, because a graduated curve token still answers on the curve factory. Resolve in this order: does any curve factory know it (poolOf ≠ 0)? If yes, read the pool's stats() — if graduated is true, the live liquidity is a normal DEX pair and you should trade there, not on the curve. Only if no curve factory knows it is it a fixed-price mint token or an unrelated ERC-20.

const s = await pool.read.stats();
// s = (token, target, raised, tokensSold, curveSupply,
//      priceX18, progressBps, graduated, pair)
if (s[7]) {
  // 已毕业:去 s[8] 这个 DEX pair 交易,曲线的 buy/sell 会 revert
} else {
  // 内盘中:progressBps/100 = 进度%,raised/target = 距毕业还差多少
}
A token can graduate while your session is open — it is exactly what heavy buying causes. Re-resolve on price refresh rather than caching the venue for the lifetime of a page, or every remaining trade will revert.

3 · Price it

In-curve tokens have exact on-chain quote views: quoteBuy(quoteIn) and quoteSell(tokenIn). Use them rather than re-implementing the curve — they mirror the fee flooring inside buy() and sell() exactly, so recomputing the maths off-chain drifts by wei. quoteSell returns 0 when the amount exceeds what the curve has actually sold; that is a real constraint, not a failure. Graduated tokens price through the DEX router as usual.

For a USD figure you also need the quote asset's price, and the quote asset is not always the native coin: it can be USDT or a tokenized stock (NVDAB, SPCXB, SPYB, QQQB). Read pool.quoteToken() — zero address means native. Treating any ERC-20 quote as $1 is a mistake we made ourselves and it puts market caps out by two orders of magnitude on stock-quoted tokens.

4 · Trade

In-curve trading does not go through a router. Buy with native quote is buy(minTokensOut) with the amount as msg.value; buy with an ERC-20 quote is buyToken(quoteIn, minTokensOut) after approving the pool. Sell is always sell(tokenIn, minQuoteOut) after approving the pool. Note the approval target: it is the curve contract itself, not a router — approving a router does nothing here, because the curve pulls the funds.

// 内盘买(原生报价)
await pool.write.buy([minOut], { value: amountIn });
// 内盘买(USDT / 股票报价)
await quote.write.approve([poolAddress, amountIn]);
await pool.write.buyToken([amountIn, minOut]);
// 内盘卖(两种报价都一样)
await token.write.approve([poolAddress, amountIn]);
await pool.write.sell([amountIn, minQuoteOut]);

// 毕业后:普通 DEX 路由。代币可能带买卖税 → 用
// swapExactTokensForTokensSupportingFeeOnTransferTokens 这一族
Always await the receipt and check status === 1. A transaction hash is not a fill — a reverted transaction has a hash too. We shipped a bug once where sells reverted on-chain while the UI reported success, purely because nothing checked the receipt status.

5 · Vaults: what a token's mechanism is

A token's tax vault is at token.taxVault(). Vaults are self-describing: vaultUISchema() returns the vault type, a description and the full list of read/write methods with their types, which is how this site renders a vault panel it has never seen. description() returns a live one-line status (for example a countdown to the next burn).

Vaults are 45-byte EIP-1167 clones, so their own bytecode contains no functions. To probe what a vault supports, resolve the implementation out of the clone and look for selectors in the implementation's runtime bytecode. This is how the site decides which aggregates to show without hardcoding a table per vault type.

// 45 字节克隆 → 实现合约
const EIP1167 = /363d3d373d3d3d363d73([0-9a-fA-F]{40})5af43d82803e903d91/;
let code = await client.getBytecode({ address: vault });
const m = code?.match(EIP1167);
if (m) code = await client.getBytecode({ address: `0x${m[1]}` });
// 之后在 code 里找选择子,例如 totalDistributed() = efca2eed
Selector probing matches function names, not meanings. The same name can mean different things across vaults — totalBurned counts NFTs sold back in the NFT vault but is an 18-decimal token amount in the floor vault. Confirm the semantics per vault type before formatting, or you will render 12 NFTs as 0.000000000000000012.

ABI downloads

Full ABIs as JSON, generated from the same definitions this site uses to talk to the chain — so they never lag behind what is deployed. GET /api/abi lists everything available; GET /api/abi/<name>.json returns one. CORS is open, so a terminal or bot can fetch them directly.

curl https://whalefun.io/api/abi                      # 清单
curl -O https://whalefun.io/api/abi/curveTaxPool.json  # 内盘池(buy/sell/quote/stats)
curl -O https://whalefun.io/api/abi/curveTaxFactory.json
curl -O https://whalefun.io/api/abi/curveTaxToken.json # 持币分红
curl -O https://whalefun.io/api/abi/launchFactoryV2.json
curl -O https://whalefun.io/api/abi/projectTokenV2.json
curl -O https://whalefun.io/api/abi/vaultSchema.json   # 任意金库的自描述接口