kiwi.rich
Arc mainnetNo API keyOnchain source of truth

Build on kiwi.rich

Everything needed to list, index, quote, and trade kiwi.rich markets in terminals, bots, scanners, and analytics products.

Start here

Two sources, one canonical market

Watch the contracts for immediate launch, trade, and graduation events. Use the public API to enrich those events with images, socials, normalized prices, holders, candles, and historical activity. Never delay new-pair discovery on an API request.

Onchain events

Canonical and lowest latency. Use for New Pairs, live trades, Final Stretch, and migration alerts.

Read API

Indexed and normalized. Use for rendering market cards, charts, token pages, holders, and metadata.

All read endpoints are public and CORS-enabled. Integrations never need a kiwi.rich API key or user private key.

Contracts

Arc mainnet deployments

Index both factories. V2 is the current launch version; V1 markets remain live and must continue to be discoverable and tradeable.

V2 factory

Primary · block 11,202,050

V1 factory

Legacy · block 11,075,665

System USDC

ERC-20 interface · 6 decimals

Permit router

Optional atomic USDC permit

Sponsored router

Zero-buy creator authorization

Chain ID

5042

Launch token

18 decimals

Address suffix

0000

New pairs

Discover every launch

Subscribe to LaunchCreated on both factories. The event contains the token, curve, creator, display metadata URI, and the complete immutable economics for that factory version.

viem · launch discovery
import { createPublicClient, http, parseAbiItem } from "viem";

const FACTORIES = [
  "0x8Ac834b6A56278f4cf4a6D2E66F332a5348e12Dc", // V2
  "0x74B79eA7C8c8621979c5aB9710f27B70aBB543E5", // V1
] as const;

const launchCreated = parseAbiItem(
  "event LaunchCreated(address indexed token, address indexed curve, address indexed creator, string name, string symbol, string metadataURI, (uint256 totalSupply, uint256 curveSupply, uint256 virtualUsdc, uint256 graduationTarget, uint16 curveFeeBps, uint16 poolFeeBps, uint16 creatorFeeShareBps, bool burnSurplusTokens, address usdc, address protocolTreasury) config"
);

const logs = await client.getLogs({
  address: FACTORIES,
  event: launchCreated,
  fromBlock: 11075665n,
  toBlock: "latest",
});

Canonical validation

A token is a kiwi.rich launch only when at least one published factory returns a non-zero curve fromcurveForToken(token).

Ordering

Order New Pairs by block number and log index. Persist the last finalized cursor and rewind on a chain reorganization instead of relying on timestamps alone.

canonical token check
import { zeroAddress } from "viem";

async function resolveKiwiMarket(token) {
  for (const factory of FACTORIES) {
    const curve = await client.readContract({
      address: factory,
      abi: factoryAbi,
      functionName: "curveForToken",
      args: [token],
    });

    if (curve !== zeroAddress) {
      const pool = await client.readContract({
        address: factory,
        abi: factoryAbi,
        functionName: "poolForToken",
        args: [token],
      });
      return { factory, curve, pool };
    }
  }
  return null;
}

State machine

Curve to permanent liquidity

A market has exactly two phases. Graduation happens atomically inside the final curve buy, creates one permanent constant-product pool, and closes curve trading permanently.

0 · Bonding curve

New / Final Stretch

Venue is curveForToken(token). Progress equals the real curve USDC reserve divided by that launch's graduation target.

1 · Permanent pool

Migrated

Venue is poolForToken(token). Liquidity has no withdrawal, transfer, decrease, or LP-owner path.

EventTerminal action
LaunchCreatedInsert the token into New Pairs immediately.
Buy / SellUpdate price, volume, transactions, reserves, and progress.
LaunchGraduatedMove the token to Migrated and switch execution to the emitted pool.

HTTP API

Normalized market data

The API is read-only, versioned, and CORS-enabled. Cache it for presentation, but use contract events for latency-sensitive alerts and transaction decisions.

GET/api/v1/launchpad

Factories, policy, event signatures, and resource links.

GET/api/v1/markets

Newest-first market snapshot and latest trades.

GET/api/v1/token/{address}

Phase, venue, price, FDV, liquidity, holders, candles, and metadata.

GET/api/v1/abis

Catalog of stable JSON ABI resources.

GET/api/v1/openapi

OpenAPI 3.1 machine-readable API description.

GET/llms.txt

Compact integration context for coding agents.

curl
# Launchpad configuration and event signatures
curl https://kiwi.rich/api/v1/launchpad

# Bounded newest-first market snapshot
curl "https://kiwi.rich/api/v1/markets?limit=24"

# Complete normalized data for one canonical token
curl https://kiwi.rich/api/v1/token/0x6d1b30b0795ee3745d9648d286caebf905390000

# Machine-readable interfaces
curl https://kiwi.rich/api/v1/abis
curl https://kiwi.rich/api/v1/openapi

Execution

Quote and trade the active venue

Read the phase immediately before quoting. Curve and pool venues expose the same buy and sell entrypoint names, while their quote return shapes differ. Integrators sign and submit transactions from their own wallets; kiwi.rich never receives private keys.

Buy quotequoteBuy(usdcIn)USDC input uses 6 decimals
Buybuy(usdcIn, minTokensOut)Approve system USDC to the active venue
Sell quotequoteSell(tokensIn)Token input uses 18 decimals
Sellsell(tokensIn, minUsdcOut)Approve the launch token to the active venue
viem · buy with approval
import { erc20Abi, parseUnits } from "viem";

const usdcIn = parseUnits("100", 6);
const tokenData = await fetch(
  `https://kiwi.rich/api/v1/token/${token}`
).then((response) => response.json());

const venue = tokenData.market.venue;
const onCurve = tokenData.market.phase === "bonding_curve";
const venueAbi = onCurve ? bondingCurveAbi : graduatedPoolAbi;
const quote = await publicClient.readContract({
  address: venue,
  abi: venueAbi,
  functionName: "quoteBuy",
  args: [usdcIn],
});

const tokensOut = quote[0];
const minTokensOut = (tokensOut * 9_900n) / 10_000n; // 1% slippage

await walletClient.writeContract({
  address: "0x3600000000000000000000000000000000000000",
  abi: erc20Abi,
  functionName: "approve",
  args: [venue, usdcIn],
});

await walletClient.writeContract({
  address: venue,
  abi: venueAbi,
  functionName: "buy",
  args: [usdcIn, minTokensOut],
  value: 0n,
});

Graduation edge case

A final curve buy may consume less USDC than the supplied maximum. Use the curve's fullquoteBuy result when accounting for exact spend. After every confirmed trade, reread phase and pool before constructing the next order.

Token presentation

Images, links, and descriptions

Read metadataURI() from the token or use the normalized token endpoint. Metadata is offchain presentation data; the token address, creator, economics, and market venues must always come from the contracts.

metadata JSON
{
  "name": "Kiwi Cat",
  "symbol": "kcat",
  "description": "A token launched on Arc.",
  "image": "https://.../logo.png",
  "x": "https://x.com/...",
  "telegram": "https://t.me/...",
  "website": "https://..."
}

Image, description, and social URLs may be absent on legacy launches. Treat unknown fields as optional and never infer canonical status from the metadata host or address suffix alone.

Production checklist

Rules that keep integrations correct

These constraints matter for every terminal, bot, and scanner integration.

  • Index V2 and V1 from their exact deployment blocks.
  • Validate tokens through factory storage, not the 0000 suffix.
  • Use 6 decimals for ERC-20 USDC and 18 decimals for native gas USDC.
  • Send zero native value to buy and sell contract calls.
  • Read each launch's emitted economics instead of hardcoding V2 values.
  • Handle reorgs and deduplicate events by transaction hash plus log index.
  • Switch venue only after the canonical graduation event confirms.
  • Do not label the permanent pool as Uniswap or expose LP withdrawal controls.

Built an integration?

Show us on X