nadfunDecentralized Monad token launchpad with bonding curve trading, token creation, real-time event streaming, and historical data querying via pure viem calls.
Install via ClawdBot CLI:
clawdbot install portdeveloper/nadfunThe Monad token launchpad with bonding curves. Trade tokens, launch your own, monitor events—all with pure viem.
NadFun is a decentralized token launchpad on the Monad blockchain. Key features:
This skill guide is split into focused modules. Start with the overview, then dive into specific guides:
| Module | Purpose | Audience |
| ------------------------ | ------------------------------------- | --------------------- |
| SKILL.md (this file) | Architecture, constants, setup | Everyone |
| QUOTE.md | Price quotes, curve state | Traders, analyzers |
| TRADING.md | Buy, sell, permit signatures | Traders, bots |
| TOKEN.md | Balances, metadata, transfers | App developers |
| CREATE.md | Token creation, image upload | Token creators |
| INDEXER.md | Historical event querying | Analytics, dashboards |
| AGENT-API.md | REST API for trading data, token info | AI agents, bots |
For API download/endpoints/header usage, see AGENT-API.md.
Note: To obtain an API key, you must first login to nad.fun via wallet signature. See the Authentication section below for the login flow, then use the session cookie to create an API key via POST /api-key.
| File | URL |
| ------------ | ---------------------------- |
| ABI.md | https://nad.fun/abi.md |
| AGENT-API.md | https://nad.fun/agent-api.md |
| CREATE.md | https://nad.fun/create.md |
| INDEXER.md | https://nad.fun/indexer.md |
| QUOTE.md | https://nad.fun/quote.md |
| TOKEN.md | https://nad.fun/token.md |
| TRADING.md | https://nad.fun/trading.md |
| WALLET.md | https://nad.fun/wallet.md |
mkdir -p ~/.nadfun/skills
curl -s https://nad.fun/skill.md > ~/.nadfun/skills/SKILL.md
curl -s https://nad.fun/abi.md > ~/.nadfun/skills/ABI.md
curl -s https://nad.fun/agent-api.md > ~/.nadfun/skills/AGENT-API.md
curl -s https://nad.fun/create.md > ~/.nadfun/skills/CREATE.md
curl -s https://nad.fun/indexer.md > ~/.nadfun/skills/INDEXER.md
curl -s https://nad.fun/quote.md > ~/.nadfun/skills/QUOTE.md
curl -s https://nad.fun/token.md > ~/.nadfun/skills/TOKEN.md
curl -s https://nad.fun/trading.md > ~/.nadfun/skills/TRADING.md
curl -s https://nad.fun/wallet.md > ~/.nadfun/skills/WALLET.md
All addresses and endpoints are here. Update this when network changes.
const NETWORK = "testnet" // 'testnet' | 'mainnet'
const CONFIG = {
testnet: {
chainId: 10143,
rpcUrl: "https://monad-testnet.drpc.org",
apiUrl: "https://dev-api.nad.fun", // For token creation
// Contract addresses
DEX_ROUTER: "0x5D4a4f430cA3B1b2dB86B9cFE48a5316800F5fb2",
BONDING_CURVE_ROUTER: "0x865054F0F6A288adaAc30261731361EA7E908003",
LENS: "0xB056d79CA5257589692699a46623F901a3BB76f1",
CURVE: "0x1228b0dc9481C11D3071E7A924B794CfB038994e",
WMON: "0x5a4E0bFDeF88C9032CB4d24338C5EB3d3870BfDd",
V3_FACTORY: "0xd0a37cf728CE2902eB8d4F6f2afc76854048253b",
CREATOR_TREASURY: "0x24dFf9B68fA36f8400302e2babC3e049eA19459E",
},
mainnet: {
chainId: 143,
rpcUrl: "https://monad-mainnet.drpc.org",
apiUrl: "https://api.nadapp.net",
// Contract addresses
DEX_ROUTER: "0x0B79d71AE99528D1dB24A4148b5f4F865cc2b137",
BONDING_CURVE_ROUTER: "0x6F6B8F1a20703309951a5127c45B49b1CD981A22",
LENS: "0x7e78A8DE94f21804F7a17F4E8BF9EC2c872187ea",
CURVE: "0xA7283d07812a02AFB7C09B60f8896bCEA3F90aCE",
WMON: "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
V3_FACTORY: "0x6B5F564339DbAD6b780249827f2198a841FEB7F3",
CREATOR_TREASURY: "0x42e75B4B96d7000E7Da1e0c729Cec8d2049B9731",
},
}[NETWORK]
Every skill guide assumes you start with viem. Here's the foundation:
import { createPublicClient, createWalletClient, http, privateKeyToAccount } from "viem"
const NETWORK = "testnet"
const CONFIG = {
/* from above */
}[NETWORK]
// Create clients
const publicClient = createPublicClient({
chain: {
id: CONFIG.chainId,
name: "Monad",
nativeCurrency: { name: "MON", symbol: "MON", decimals: 18 },
rpcUrls: { default: { http: [CONFIG.rpcUrl] } },
},
transport: http(CONFIG.rpcUrl),
})
const account = privateKeyToAccount("0x...")
const walletClient = createWalletClient({
account,
chain: publicClient.chain,
transport: http(CONFIG.rpcUrl),
})
This is your foundation. All other modules build on top of this.
To access session-protected endpoints (API key management, account settings, etc.), you need to authenticate via wallet signature.
import { createWalletClient, http, privateKeyToAccount } from "viem"
const account = privateKeyToAccount("0x...")
const walletClient = createWalletClient({
account,
chain: {
id: CONFIG.chainId,
name: "Monad",
nativeCurrency: { name: "MON", symbol: "MON", decimals: 18 },
rpcUrls: { default: { http: [CONFIG.rpcUrl] } },
},
transport: http(CONFIG.rpcUrl),
})
// Step 1: Request nonce
const nonceRes = await fetch(`${CONFIG.apiUrl}/auth/nonce`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ address: account.address }),
})
const { nonce } = await nonceRes.json()
// Step 2: Sign the nonce
const signature = await walletClient.signMessage({ message: nonce })
// Step 3: Create session
const sessionRes = await fetch(`${CONFIG.apiUrl}/auth/session`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
signature,
nonce,
chain_id: CONFIG.chainId,
}),
})
// Extract session cookie from response headers
const sessionCookie = sessionRes.headers.get("set-cookie")
const { account_info } = await sessionRes.json()
console.log("Logged in as:", account_info.account_id)
// Use session cookie for authenticated requests
const headers = { Cookie: sessionCookie }
// Example: Create API Key (requires session)
const apiKeyRes = await fetch(`${CONFIG.apiUrl}/api-key`, {
method: "POST",
headers: { ...headers, "Content-Type": "application/json" },
body: JSON.stringify({ name: "My Bot", expires_in_days: 365 }),
})
const { api_key } = await apiKeyRes.json()
console.log("API Key:", api_key) // Store this securely!
await fetch(`${CONFIG.apiUrl}/auth/delete_session`, {
method: "DELETE",
headers: { Cookie: sessionCookie },
})
interface AuthNonceRequest {
address: string
}
interface AuthNonceResponse {
nonce: string
}
interface AuthSessionRequest {
signature: string
nonce: string
chain_id: number
wallet_address?: string // Optional
}
interface AuthSessionResponse {
account_info: {
account_id: string
nickname: string
bio: string
image_uri: string
}
}
Tokens on NadFun start on a bonding curve. The curve defines price and availability:
Get curve state with getCurveState(token) → see QUOTE.md
When enough tokens are bought:
isGraduated(token) returns trueCheck progress with getProgress(token) (0-10000 = 0-100%)
The actionId parameter in token creation identifies the type of action:
| actionId | Description |
| -------- | -------------- |
| 1 | Token Creation |
Always use actionId: 1 when calling the create function.
EIP-2612 lets wallets sign approval transactions instead of sending separate approve() calls:
generatePermitSignature(token, spender, amount, deadline)sellPermit({ ...params, ...signature })See TRADING.md for details.
// Get quote (3 args: token, amountIn, isBuy)
const [router, amountOut] = await publicClient.readContract({
address: LENS,
abi: lensAbi,
functionName: "getAmountOut",
args: [token, amountIn, true], // true = buy
})
// Buy with slippage protection (1 tuple arg)
const minOut = (amountOut * BigInt(995)) / BigInt(1000) // 0.5% slippage
const deadline = BigInt(Math.floor(Date.now() / 1000) + 300)
const tx = await walletClient.writeContract({
address: router, // Use router returned from getAmountOut
abi: bondingCurveRouterAbi,
functionName: "buy",
args: [
{
amountOutMin: minOut,
token: token,
to: account.address,
deadline: deadline,
},
],
value: amountIn,
})
See TRADING.md for full examples.
import { bondingCurveRouterAbi } from "./abis/router"
// Requires API_KEY and deployFeeAmount (see CREATE.md for feeConfig())
// 1. Upload image to Agent API (raw binary, NOT formData)
const imageRes = await fetch(`${CONFIG.apiUrl}/agent/token/image`, {
method: "POST",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "image/png", // or 'image/jpeg', 'image/webp', 'image/svg+xml'
},
body: imageBuffer, // raw binary data (Buffer, Blob, or ArrayBuffer)
})
const { image_uri: imageUri } = await imageRes.json()
// 2. Upload metadata to Agent API
const metadataRes = await fetch(`${CONFIG.apiUrl}/agent/token/metadata`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": API_KEY },
body: JSON.stringify({
name: "My Token",
symbol: "MTK",
description: "My awesome token",
image_uri: imageUri,
}),
})
const { metadata_uri: metadataUri } = await metadataRes.json()
// 3. Mine salt via Agent API
const saltRes = await fetch(`${CONFIG.apiUrl}/agent/salt`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": API_KEY },
body: JSON.stringify({
creator: account.address,
name: "My Token",
symbol: "MTK",
metadata_uri: metadataUri,
}),
})
const { salt } = await saltRes.json()
// 4. Create token on-chain
const tx = await walletClient.writeContract({
address: BONDING_CURVE_ROUTER,
abi: bondingCurveRouterAbi,
functionName: "create",
args: [
{
name: "My Token",
symbol: "MTK",
tokenURI: metadataUri,
amountOut: 0n, // Set > 0n for initial buy amount (in tokens)
salt: salt,
actionId: 1, // Token creation action identifier (always 1 for create)
},
],
value: deployFeeAmount, // plus optional initial buy MON if amountOut > 0
gas, // Use estimated gas (see below)
})
console.log("Transaction:", tx)
// Gas estimation (recommended over hardcoded values)
const gasEstimate = await publicClient.estimateContractGas({
address: CONFIG.BONDING_CURVE_ROUTER,
abi: bondingCurveRouterAbi,
functionName: "create",
args: [
{ name: "My Token", symbol: "MTK", tokenURI: metadataUri, amountOut: 0n, salt, actionId: 1 },
],
value: deployFeeAmount,
account: account.address,
})
const gas = (gasEstimate * 120n) / 100n // 20% buffer for safety
See CREATE.md for step-by-step.
Use these prompts to guide your work:
For integration, you'll need:
abis/
├── curve.ts # Bonding curve contract ABI
├── lens.ts # Price quote ABI
├── router.ts # DEX router ABI
├── token.ts # ERC20 token ABI
└── v3*.ts # Uniswap V3 ABIs
constants.ts # Network configs, contract addresses
All ABIs are documented in ABI.md.
Each ABI can be copied from ABI.md. Reference the correct section:
| ABI | ABI.md Section | Purpose |
| ----------------------- | ------------------------------------------------- | -------------------------------- |
| bondingCurveRouterAbi | BondingCurveRouter ABI | Token creation, buy/sell |
| lensAbi | Lens ABI | Price quotes, getAmountOut |
| curveAbi | Curve ABI | Curve state, graduation check |
| tokenAbi | Token ABI | ERC20 operations, permit signing |
Example import pattern:
// Copy the ABI from ABI.md into your project
import { bondingCurveRouterAbi } from "./abis/router"
import { lensAbi } from "./abis/lens"
npm install viem
# or
pnpm add viem
# or
yarn add viem
{
"viem": "^2.0.0"
}
Pure viem. No other blockchain libraries needed.
You're on the wrong network. Check NETWORK constant matches your setup.
Query getProgress() via Lens contract. Returns 0-10000. Need 10000 (100%) to graduate.
Pick a guide based on what you need:
Each guide has complete examples ready to copy.
Always use the as const assertion when working with ABIs in viem. All ABIs in this module are pre-declared with as const for full type inference:
// Types are automatically narrowed
const result = await contract.read.getAmountOut([...])
// result type is precisely bigint (not bigint | undefined)
Use viem type helpers for type-safe conversions:
import { Address, Hex } from "viem"
import { parseEther, formatEther } from "viem"
// Amounts
const wei = parseEther("1") // string -> bigint
const eth = formatEther(1000000000000000000n) // bigint -> string
// Addresses
const addr: Address = "0x..." // Validated address type
// Signatures
const sig: Hex = "0x..." // Hex string type
When interacting with smart contracts, you might encounter specific errors. Here's a table of common ABI-related errors and how to approach them:
| Error | Meaning |
| ----------------------- | ---------------------------------------------------------- |
| InsufficientAmount | Output less than amountOutMin |
| InsufficientAmountOut | Insufficient output amount |
| DeadlineExpired | Deadline has passed |
| Unauthorized | Caller not authorized |
| AlreadyGraduated | Token already graduated to DEX |
| BondingCurveLocked | Curve locked during graduation |
| InvalidProof | Merkle proof verification failed (specific to claims) |
| AlreadyClaimed | Amount already claimed for this proof (specific to claims) |
| NotClaimable | Token not eligible for claims yet (specific to claims) |
| InsufficientBalance | Treasury has insufficient MON balance (specific to claims) |
Check error types in viem with:
import { ContractFunctionExecutionError } from 'viem'
try {
await contract.write.buy([...]) // or any contract interaction
} catch (error) {
if (error instanceof ContractFunctionExecutionError) {
console.log(error.shortMessage) // "InsufficientAmount", etc.
}
}
Generated Mar 1, 2026
A startup wants to launch a new token on the Monad blockchain to raise funds and build community. They use NadFun to create the token with custom metadata and an initial bonding curve, allowing early supporters to buy at increasing prices before it graduates to a DEX for broader trading.
A trading firm develops bots to monitor and trade tokens on NadFun's bonding curves. The bots use real-time event streaming and historical data from the INDEXER module to execute buy/sell orders based on price trends and graduation events, optimizing profits from early-stage token movements.
A data analytics company builds a dashboard that queries NadFun's historical events and token metadata to provide insights into token launches, trading volumes, and graduation rates. This helps investors and creators track performance and make informed decisions on the Monad ecosystem.
A DeFi app integrates NadFun's token creation and trading features to allow users to launch and trade tokens directly within their platform. Using the AGENT-API and viem-based contracts, the app offers seamless token management without requiring users to navigate external interfaces.
An online learning platform uses NadFun as a case study to teach developers about bonding curves, token launches, and smart contract interactions on Monad. Students follow the skill modules to practice creating tokens, trading, and analyzing events in a testnet environment.
Offer a service where you help clients launch tokens on NadFun, handling setup, metadata, and initial bonding curve configuration for a fee. Revenue comes from service charges and a percentage of token sales, leveraging the CREATE and TRADING modules for streamlined operations.
Develop and sell subscription-based access to enhanced analytics tools that use NadFun's INDEXER and AGENT-API to provide real-time insights, custom reports, and predictive models on token performance. Revenue is generated through monthly or annual subscription plans for traders and analysts.
Create a platform that allows users to deploy automated trading strategies on NadFun, using bots that execute trades based on predefined rules. Charge users a subscription fee or take a small percentage of profits, utilizing the TRADING and QUOTE modules for efficient trading operations.
đź’¬ Integration Tip
Start by setting up the viem foundation with the provided network constants, then explore the AGENT-API for REST endpoints to simplify data access and trading without direct contract calls.
Connect Claude to Clawdbot instantly and keep it connected 24/7. Run after setup to link your subscription, then auto-refreshes tokens forever.
ERC-8004 Trustless Agents - Register, discover, and build reputation for AI agents on Ethereum. Use when registering agents on-chain, querying agent registries, giving/receiving reputation feedback, or interacting with the AI agent trust layer.
Autonomous crypto trading on Base via Bankr. Use for trading tokens, monitoring launches, executing strategies, or managing a trading portfolio. Triggers on "trade", "buy", "sell", "launch", "snipe", "profit", "PnL", "portfolio balance", or any crypto trading task on Base.
Deploy ERC20 tokens on Base using Clanker SDK. Create tokens with built-in Uniswap V4 liquidity pools. Supports Base mainnet and Sepolia testnet. Requires PRIVATE_KEY in config.
Query DeFi portfolio data across 50+ chains via Zapper's GraphQL API. Use when the user wants to check wallet balances, DeFi positions, NFT holdings, token prices, or transaction history. Supports Base, Ethereum, Polygon, Arbitrum, Optimism, and more. Requires ZAPPER_API_KEY.
Interact with Solana blockchain via Helius APIs. Create/manage wallets, check balances (SOL + tokens), send transactions, swap tokens via Jupiter, and monitor addresses. Use for any Solana blockchain operation, crypto wallet management, token transfers, DeFi swaps, or portfolio tracking.