{
  "schemaVersion": "1.0",
  "item": {
    "slug": "nadfun",
    "name": "nadfun",
    "source": "tencent",
    "type": "skill",
    "category": "AI 智能",
    "sourceUrl": "https://clawhub.ai/portdeveloper/nadfun",
    "canonicalUrl": "https://clawhub.ai/portdeveloper/nadfun",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/nadfun",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=nadfun",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "INDEXER.md",
      "ABI.md",
      "WALLET.md",
      "TOKEN.md",
      "CREATE.md",
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/nadfun"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/nadfun",
    "agentPageUrl": "https://openagent3.xyz/skills/nadfun/agent",
    "manifestUrl": "https://openagent3.xyz/skills/nadfun/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/nadfun/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "SKILL.md - NadFun Integration Guide",
        "body": "The Monad token launchpad with bonding curves. Trade tokens, launch your own, monitor events—all with pure viem."
      },
      {
        "title": "What is NadFun?",
        "body": "NadFun is a decentralized token launchpad on the Monad blockchain. Key features:\n\nBonding Curve Trading: Tokens start on a bonding curve. Price increases as more people buy.\nGraduation: When curve reaches target reserves, token graduates to DEX (Uniswap V3).\nToken Creation: Anyone can launch a token with image, metadata, and optional initial buy.\nReal-time Events: Stream token trades, creations, and DEX swaps as they happen.\nHistorical Data: Query past events for analytics and monitoring."
      },
      {
        "title": "Skills Documentation",
        "body": "This skill guide is split into focused modules. Start with the overview, then dive into specific guides:\n\nModulePurposeAudienceSKILL.md (this file)Architecture, constants, setupEveryoneQUOTE.mdPrice quotes, curve stateTraders, analyzersTRADING.mdBuy, sell, permit signaturesTraders, botsTOKEN.mdBalances, metadata, transfersApp developersCREATE.mdToken creation, image uploadToken creatorsINDEXER.mdHistorical event queryingAnalytics, dashboardsAGENT-API.mdREST API for trading data, token infoAI agents, bots\n\nFor API download/endpoints/header usage, see AGENT-API.md.\n\nNote: 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."
      },
      {
        "title": "Skill Files",
        "body": "FileURLABI.mdhttps://nad.fun/abi.mdAGENT-API.mdhttps://nad.fun/agent-api.mdCREATE.mdhttps://nad.fun/create.mdINDEXER.mdhttps://nad.fun/indexer.mdQUOTE.mdhttps://nad.fun/quote.mdTOKEN.mdhttps://nad.fun/token.mdTRADING.mdhttps://nad.fun/trading.mdWALLET.mdhttps://nad.fun/wallet.md\n\nmkdir -p ~/.nadfun/skills\ncurl -s https://nad.fun/skill.md > ~/.nadfun/skills/SKILL.md\ncurl -s https://nad.fun/abi.md > ~/.nadfun/skills/ABI.md\ncurl -s https://nad.fun/agent-api.md > ~/.nadfun/skills/AGENT-API.md\ncurl -s https://nad.fun/create.md > ~/.nadfun/skills/CREATE.md\ncurl -s https://nad.fun/indexer.md > ~/.nadfun/skills/INDEXER.md\ncurl -s https://nad.fun/quote.md > ~/.nadfun/skills/QUOTE.md\ncurl -s https://nad.fun/token.md > ~/.nadfun/skills/TOKEN.md\ncurl -s https://nad.fun/trading.md > ~/.nadfun/skills/TRADING.md\ncurl -s https://nad.fun/wallet.md > ~/.nadfun/skills/WALLET.md"
      },
      {
        "title": "Quick Facts",
        "body": "Network: Testnet (chain 10143) or Mainnet (chain 143)\nLanguage: TypeScript/JavaScript\nPure viem: All examples use direct contract calls with viem\nFees: Check API for deploy fees via REST endpoint"
      },
      {
        "title": "Network Constants",
        "body": "All addresses and endpoints are here. Update this when network changes.\n\nconst NETWORK = \"testnet\" // 'testnet' | 'mainnet'\n\nconst CONFIG = {\n  testnet: {\n    chainId: 10143,\n    rpcUrl: \"https://monad-testnet.drpc.org\",\n    apiUrl: \"https://dev-api.nad.fun\", // For token creation\n\n    // Contract addresses\n    DEX_ROUTER: \"0x5D4a4f430cA3B1b2dB86B9cFE48a5316800F5fb2\",\n    BONDING_CURVE_ROUTER: \"0x865054F0F6A288adaAc30261731361EA7E908003\",\n    LENS: \"0xB056d79CA5257589692699a46623F901a3BB76f1\",\n    CURVE: \"0x1228b0dc9481C11D3071E7A924B794CfB038994e\",\n    WMON: \"0x5a4E0bFDeF88C9032CB4d24338C5EB3d3870BfDd\",\n    V3_FACTORY: \"0xd0a37cf728CE2902eB8d4F6f2afc76854048253b\",\n    CREATOR_TREASURY: \"0x24dFf9B68fA36f8400302e2babC3e049eA19459E\",\n  },\n  mainnet: {\n    chainId: 143,\n    rpcUrl: \"https://monad-mainnet.drpc.org\",\n    apiUrl: \"https://api.nadapp.net\",\n\n    // Contract addresses\n    DEX_ROUTER: \"0x0B79d71AE99528D1dB24A4148b5f4F865cc2b137\",\n    BONDING_CURVE_ROUTER: \"0x6F6B8F1a20703309951a5127c45B49b1CD981A22\",\n    LENS: \"0x7e78A8DE94f21804F7a17F4E8BF9EC2c872187ea\",\n    CURVE: \"0xA7283d07812a02AFB7C09B60f8896bCEA3F90aCE\",\n    WMON: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\",\n    V3_FACTORY: \"0x6B5F564339DbAD6b780249827f2198a841FEB7F3\",\n    CREATOR_TREASURY: \"0x42e75B4B96d7000E7Da1e0c729Cec8d2049B9731\",\n  },\n}[NETWORK]"
      },
      {
        "title": "Basic Setup",
        "body": "Every skill guide assumes you start with viem. Here's the foundation:\n\nimport { createPublicClient, createWalletClient, http, privateKeyToAccount } from \"viem\"\n\nconst NETWORK = \"testnet\"\nconst CONFIG = {\n  /* from above */\n}[NETWORK]\n\n// Create clients\nconst publicClient = createPublicClient({\n  chain: {\n    id: CONFIG.chainId,\n    name: \"Monad\",\n    nativeCurrency: { name: \"MON\", symbol: \"MON\", decimals: 18 },\n    rpcUrls: { default: { http: [CONFIG.rpcUrl] } },\n  },\n  transport: http(CONFIG.rpcUrl),\n})\n\nconst account = privateKeyToAccount(\"0x...\")\nconst walletClient = createWalletClient({\n  account,\n  chain: publicClient.chain,\n  transport: http(CONFIG.rpcUrl),\n})\n\nThis is your foundation. All other modules build on top of this."
      },
      {
        "title": "Authentication (Login Flow)",
        "body": "To access session-protected endpoints (API key management, account settings, etc.), you need to authenticate via wallet signature."
      },
      {
        "title": "Login Flow",
        "body": "import { createWalletClient, http, privateKeyToAccount } from \"viem\"\n\nconst account = privateKeyToAccount(\"0x...\")\nconst walletClient = createWalletClient({\n  account,\n  chain: {\n    id: CONFIG.chainId,\n    name: \"Monad\",\n    nativeCurrency: { name: \"MON\", symbol: \"MON\", decimals: 18 },\n    rpcUrls: { default: { http: [CONFIG.rpcUrl] } },\n  },\n  transport: http(CONFIG.rpcUrl),\n})\n\n// Step 1: Request nonce\nconst nonceRes = await fetch(`${CONFIG.apiUrl}/auth/nonce`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ address: account.address }),\n})\nconst { nonce } = await nonceRes.json()\n\n// Step 2: Sign the nonce\nconst signature = await walletClient.signMessage({ message: nonce })\n\n// Step 3: Create session\nconst sessionRes = await fetch(`${CONFIG.apiUrl}/auth/session`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({\n    signature,\n    nonce,\n    chain_id: CONFIG.chainId,\n  }),\n})\n\n// Extract session cookie from response headers\nconst sessionCookie = sessionRes.headers.get(\"set-cookie\")\nconst { account_info } = await sessionRes.json()\n\nconsole.log(\"Logged in as:\", account_info.account_id)"
      },
      {
        "title": "Using Session Cookie",
        "body": "// Use session cookie for authenticated requests\nconst headers = { Cookie: sessionCookie }\n\n// Example: Create API Key (requires session)\nconst apiKeyRes = await fetch(`${CONFIG.apiUrl}/api-key`, {\n  method: \"POST\",\n  headers: { ...headers, \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ name: \"My Bot\", expires_in_days: 365 }),\n})\nconst { api_key } = await apiKeyRes.json()\nconsole.log(\"API Key:\", api_key) // Store this securely!"
      },
      {
        "title": "Logout",
        "body": "await fetch(`${CONFIG.apiUrl}/auth/delete_session`, {\n  method: \"DELETE\",\n  headers: { Cookie: sessionCookie },\n})"
      },
      {
        "title": "TypeScript Interfaces",
        "body": "interface AuthNonceRequest {\n  address: string\n}\n\ninterface AuthNonceResponse {\n  nonce: string\n}\n\ninterface AuthSessionRequest {\n  signature: string\n  nonce: string\n  chain_id: number\n  wallet_address?: string // Optional\n}\n\ninterface AuthSessionResponse {\n  account_info: {\n    account_id: string\n    nickname: string\n    bio: string\n    image_uri: string\n  }\n}"
      },
      {
        "title": "Bonding Curve",
        "body": "Tokens on NadFun start on a bonding curve. The curve defines price and availability:\n\nReal reserves: Actual MON and tokens in the pool\nVirtual reserves: Initial pseudo-reserves for curve math\nK constant: Maintains x*y=k formula for price\nTarget: How many tokens must be sold to graduate\n\nGet curve state with getCurveState(token) → see QUOTE.md"
      },
      {
        "title": "Graduation",
        "body": "When enough tokens are bought:\n\nCurve reaches target reserve\nLiquidity moves to Uniswap V3 pool\nToken transitions from bonding curve to DEX\nisGraduated(token) returns true\n\nCheck progress with getProgress(token) (0-10000 = 0-100%)"
      },
      {
        "title": "Action IDs",
        "body": "The actionId parameter in token creation identifies the type of action:\n\nactionIdDescription1Token Creation\n\nAlways use actionId: 1 when calling the create function."
      },
      {
        "title": "Permit Signatures",
        "body": "EIP-2612 lets wallets sign approval transactions instead of sending separate approve() calls:\n\nGenerate signature: generatePermitSignature(token, spender, amount, deadline)\nUse in trade: sellPermit({ ...params, ...signature })\nNo separate approve needed—saves gas\n\nSee TRADING.md for details."
      },
      {
        "title": "Pattern 1: Simple Trade",
        "body": "// Get quote (3 args: token, amountIn, isBuy)\nconst [router, amountOut] = await publicClient.readContract({\n  address: LENS,\n  abi: lensAbi,\n  functionName: \"getAmountOut\",\n  args: [token, amountIn, true], // true = buy\n})\n\n// Buy with slippage protection (1 tuple arg)\nconst minOut = (amountOut * BigInt(995)) / BigInt(1000) // 0.5% slippage\nconst deadline = BigInt(Math.floor(Date.now() / 1000) + 300)\nconst tx = await walletClient.writeContract({\n  address: router, // Use router returned from getAmountOut\n  abi: bondingCurveRouterAbi,\n  functionName: \"buy\",\n  args: [\n    {\n      amountOutMin: minOut,\n      token: token,\n      to: account.address,\n      deadline: deadline,\n    },\n  ],\n  value: amountIn,\n})\n\nSee TRADING.md for full examples."
      },
      {
        "title": "Pattern 2: Launch Token",
        "body": "import { bondingCurveRouterAbi } from \"./abis/router\"\n\n// Requires API_KEY and deployFeeAmount (see CREATE.md for feeConfig())\n\n// 1. Upload image to Agent API (raw binary, NOT formData)\nconst imageRes = await fetch(`${CONFIG.apiUrl}/agent/token/image`, {\n  method: \"POST\",\n  headers: {\n    \"X-API-Key\": API_KEY,\n    \"Content-Type\": \"image/png\", // or 'image/jpeg', 'image/webp', 'image/svg+xml'\n  },\n  body: imageBuffer, // raw binary data (Buffer, Blob, or ArrayBuffer)\n})\nconst { image_uri: imageUri } = await imageRes.json()\n\n// 2. Upload metadata to Agent API\nconst metadataRes = await fetch(`${CONFIG.apiUrl}/agent/token/metadata`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\", \"X-API-Key\": API_KEY },\n  body: JSON.stringify({\n    name: \"My Token\",\n    symbol: \"MTK\",\n    description: \"My awesome token\",\n    image_uri: imageUri,\n  }),\n})\nconst { metadata_uri: metadataUri } = await metadataRes.json()\n\n// 3. Mine salt via Agent API\nconst saltRes = await fetch(`${CONFIG.apiUrl}/agent/salt`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\", \"X-API-Key\": API_KEY },\n  body: JSON.stringify({\n    creator: account.address,\n    name: \"My Token\",\n    symbol: \"MTK\",\n    metadata_uri: metadataUri,\n  }),\n})\nconst { salt } = await saltRes.json()\n\n// 4. Create token on-chain\nconst tx = await walletClient.writeContract({\n  address: BONDING_CURVE_ROUTER,\n  abi: bondingCurveRouterAbi,\n  functionName: \"create\",\n  args: [\n    {\n      name: \"My Token\",\n      symbol: \"MTK\",\n      tokenURI: metadataUri,\n      amountOut: 0n, // Set > 0n for initial buy amount (in tokens)\n      salt: salt,\n      actionId: 1, // Token creation action identifier (always 1 for create)\n    },\n  ],\n  value: deployFeeAmount, // plus optional initial buy MON if amountOut > 0\n  gas, // Use estimated gas (see below)\n})\n\nconsole.log(\"Transaction:\", tx)\n\n// Gas estimation (recommended over hardcoded values)\nconst gasEstimate = await publicClient.estimateContractGas({\n  address: CONFIG.BONDING_CURVE_ROUTER,\n  abi: bondingCurveRouterAbi,\n  functionName: \"create\",\n  args: [\n    { name: \"My Token\", symbol: \"MTK\", tokenURI: metadataUri, amountOut: 0n, salt, actionId: 1 },\n  ],\n  value: deployFeeAmount,\n  account: account.address,\n})\nconst gas = (gasEstimate * 120n) / 100n // 20% buffer for safety\n\nSee CREATE.md for step-by-step."
      },
      {
        "title": "Prompts for AI Agents",
        "body": "Use these prompts to guide your work:"
      },
      {
        "title": "Trading",
        "body": "\"Get a price quote for token X with 0.1 MON\"\n\"Buy 0.1 MON of token X with 1% slippage\"\n\"Sell all tokens with permit signature\"\n\"Check if token has graduated\""
      },
      {
        "title": "Token Info",
        "body": "\"Get metadata for token address X\"\n\"Check my MON balance\"\n\"Get available tokens to buy before graduation\""
      },
      {
        "title": "Creation",
        "body": "\"Launch a token called MyToken (MTK) with this image\"\n\"Mine a vanity address for my token\"\n\"Check token creation fees\""
      },
      {
        "title": "Analysis",
        "body": "\"Calculate graduation progress for token X\"\n\"Get the bonding curve state for token X\"\n\"Track all swaps on the graduated token\"\n\"Analyze token creation rate\""
      },
      {
        "title": "Required Files",
        "body": "For integration, you'll need:\n\nabis/\n├── curve.ts              # Bonding curve contract ABI\n├── lens.ts               # Price quote ABI\n├── router.ts             # DEX router ABI\n├── token.ts              # ERC20 token ABI\n└── v3*.ts                # Uniswap V3 ABIs\n\nconstants.ts              # Network configs, contract addresses\n\nAll ABIs are documented in ABI.md."
      },
      {
        "title": "ABI Import Guide",
        "body": "Each ABI can be copied from ABI.md. Reference the correct section:\n\nABIABI.md SectionPurposebondingCurveRouterAbiBondingCurveRouter ABIToken creation, buy/selllensAbiLens ABIPrice quotes, getAmountOutcurveAbiCurve ABICurve state, graduation checktokenAbiToken ABIERC20 operations, permit signing\n\nExample import pattern:\n\n// Copy the ABI from ABI.md into your project\nimport { bondingCurveRouterAbi } from \"./abis/router\"\nimport { lensAbi } from \"./abis/lens\""
      },
      {
        "title": "Installation",
        "body": "npm install viem\n# or\npnpm add viem\n# or\nyarn add viem"
      },
      {
        "title": "Dependencies",
        "body": "{\n  \"viem\": \"^2.0.0\"\n}\n\nPure viem. No other blockchain libraries needed."
      },
      {
        "title": "\"No such contract\"",
        "body": "You're on the wrong network. Check NETWORK constant matches your setup."
      },
      {
        "title": "\"Token not graduated yet\"",
        "body": "Query getProgress() via Lens contract. Returns 0-10000. Need 10000 (100%) to graduate."
      },
      {
        "title": "\"Transaction reverted\"",
        "body": "Check amountOutMin—slippage might be too high or curve moved\nVerify deadline—transaction took too long\nCheck allowance—approve token before sell"
      },
      {
        "title": "Next Steps",
        "body": "Pick a guide based on what you need:\n\nBuilding a dex bot? → TRADING.md\nCreating a dashboard? → INDEXER.md + QUOTE.md\nLaunching tokens? → CREATE.md\nToken info queries? → TOKEN.md\n\nEach guide has complete examples ready to copy."
      },
      {
        "title": "Type Safety Tips",
        "body": "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:\n\n// Types are automatically narrowed\nconst result = await contract.read.getAmountOut([...])\n// result type is precisely bigint (not bigint | undefined)\n\nUse viem type helpers for type-safe conversions:\n\nimport { Address, Hex } from \"viem\"\nimport { parseEther, formatEther } from \"viem\"\n\n// Amounts\nconst wei = parseEther(\"1\") // string -> bigint\nconst eth = formatEther(1000000000000000000n) // bigint -> string\n\n// Addresses\nconst addr: Address = \"0x...\" // Validated address type\n\n// Signatures\nconst sig: Hex = \"0x...\" // Hex string type"
      },
      {
        "title": "Common ABI Errors",
        "body": "When interacting with smart contracts, you might encounter specific errors. Here's a table of common ABI-related errors and how to approach them:\n\nErrorMeaningInsufficientAmountOutput less than amountOutMinInsufficientAmountOutInsufficient output amountDeadlineExpiredDeadline has passedUnauthorizedCaller not authorizedAlreadyGraduatedToken already graduated to DEXBondingCurveLockedCurve locked during graduationInvalidProofMerkle proof verification failed (specific to claims)AlreadyClaimedAmount already claimed for this proof (specific to claims)NotClaimableToken not eligible for claims yet (specific to claims)InsufficientBalanceTreasury has insufficient MON balance (specific to claims)\n\nCheck error types in viem with:\n\nimport { ContractFunctionExecutionError } from 'viem'\n\ntry {\n  await contract.write.buy([...]) // or any contract interaction\n} catch (error) {\n  if (error instanceof ContractFunctionExecutionError) {\n    console.log(error.shortMessage) // \"InsufficientAmount\", etc.\n  }\n}"
      }
    ],
    "body": "SKILL.md - NadFun Integration Guide\n\nThe Monad token launchpad with bonding curves. Trade tokens, launch your own, monitor events—all with pure viem.\n\nWhat is NadFun?\n\nNadFun is a decentralized token launchpad on the Monad blockchain. Key features:\n\nBonding Curve Trading: Tokens start on a bonding curve. Price increases as more people buy.\nGraduation: When curve reaches target reserves, token graduates to DEX (Uniswap V3).\nToken Creation: Anyone can launch a token with image, metadata, and optional initial buy.\nReal-time Events: Stream token trades, creations, and DEX swaps as they happen.\nHistorical Data: Query past events for analytics and monitoring.\nSkills Documentation\n\nThis skill guide is split into focused modules. Start with the overview, then dive into specific guides:\n\nModule\tPurpose\tAudience\nSKILL.md (this file)\tArchitecture, constants, setup\tEveryone\nQUOTE.md\tPrice quotes, curve state\tTraders, analyzers\nTRADING.md\tBuy, sell, permit signatures\tTraders, bots\nTOKEN.md\tBalances, metadata, transfers\tApp developers\nCREATE.md\tToken creation, image upload\tToken creators\nINDEXER.md\tHistorical event querying\tAnalytics, dashboards\nAGENT-API.md\tREST API for trading data, token info\tAI agents, bots\n\nFor API download/endpoints/header usage, see AGENT-API.md.\n\nNote: 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.\n\nSkill Files\nFile\tURL\nABI.md\thttps://nad.fun/abi.md\nAGENT-API.md\thttps://nad.fun/agent-api.md\nCREATE.md\thttps://nad.fun/create.md\nINDEXER.md\thttps://nad.fun/indexer.md\nQUOTE.md\thttps://nad.fun/quote.md\nTOKEN.md\thttps://nad.fun/token.md\nTRADING.md\thttps://nad.fun/trading.md\nWALLET.md\thttps://nad.fun/wallet.md\n\nmkdir -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\n\nQuick Facts\nNetwork: Testnet (chain 10143) or Mainnet (chain 143)\nLanguage: TypeScript/JavaScript\nPure viem: All examples use direct contract calls with viem\nFees: Check API for deploy fees via REST endpoint\nNetwork Constants\n\nAll addresses and endpoints are here. Update this when network changes.\n\nconst NETWORK = \"testnet\" // 'testnet' | 'mainnet'\n\nconst CONFIG = {\n  testnet: {\n    chainId: 10143,\n    rpcUrl: \"https://monad-testnet.drpc.org\",\n    apiUrl: \"https://dev-api.nad.fun\", // For token creation\n\n    // Contract addresses\n    DEX_ROUTER: \"0x5D4a4f430cA3B1b2dB86B9cFE48a5316800F5fb2\",\n    BONDING_CURVE_ROUTER: \"0x865054F0F6A288adaAc30261731361EA7E908003\",\n    LENS: \"0xB056d79CA5257589692699a46623F901a3BB76f1\",\n    CURVE: \"0x1228b0dc9481C11D3071E7A924B794CfB038994e\",\n    WMON: \"0x5a4E0bFDeF88C9032CB4d24338C5EB3d3870BfDd\",\n    V3_FACTORY: \"0xd0a37cf728CE2902eB8d4F6f2afc76854048253b\",\n    CREATOR_TREASURY: \"0x24dFf9B68fA36f8400302e2babC3e049eA19459E\",\n  },\n  mainnet: {\n    chainId: 143,\n    rpcUrl: \"https://monad-mainnet.drpc.org\",\n    apiUrl: \"https://api.nadapp.net\",\n\n    // Contract addresses\n    DEX_ROUTER: \"0x0B79d71AE99528D1dB24A4148b5f4F865cc2b137\",\n    BONDING_CURVE_ROUTER: \"0x6F6B8F1a20703309951a5127c45B49b1CD981A22\",\n    LENS: \"0x7e78A8DE94f21804F7a17F4E8BF9EC2c872187ea\",\n    CURVE: \"0xA7283d07812a02AFB7C09B60f8896bCEA3F90aCE\",\n    WMON: \"0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A\",\n    V3_FACTORY: \"0x6B5F564339DbAD6b780249827f2198a841FEB7F3\",\n    CREATOR_TREASURY: \"0x42e75B4B96d7000E7Da1e0c729Cec8d2049B9731\",\n  },\n}[NETWORK]\n\nBasic Setup\n\nEvery skill guide assumes you start with viem. Here's the foundation:\n\nimport { createPublicClient, createWalletClient, http, privateKeyToAccount } from \"viem\"\n\nconst NETWORK = \"testnet\"\nconst CONFIG = {\n  /* from above */\n}[NETWORK]\n\n// Create clients\nconst publicClient = createPublicClient({\n  chain: {\n    id: CONFIG.chainId,\n    name: \"Monad\",\n    nativeCurrency: { name: \"MON\", symbol: \"MON\", decimals: 18 },\n    rpcUrls: { default: { http: [CONFIG.rpcUrl] } },\n  },\n  transport: http(CONFIG.rpcUrl),\n})\n\nconst account = privateKeyToAccount(\"0x...\")\nconst walletClient = createWalletClient({\n  account,\n  chain: publicClient.chain,\n  transport: http(CONFIG.rpcUrl),\n})\n\n\nThis is your foundation. All other modules build on top of this.\n\nAuthentication (Login Flow)\n\nTo access session-protected endpoints (API key management, account settings, etc.), you need to authenticate via wallet signature.\n\nLogin Flow\nimport { createWalletClient, http, privateKeyToAccount } from \"viem\"\n\nconst account = privateKeyToAccount(\"0x...\")\nconst walletClient = createWalletClient({\n  account,\n  chain: {\n    id: CONFIG.chainId,\n    name: \"Monad\",\n    nativeCurrency: { name: \"MON\", symbol: \"MON\", decimals: 18 },\n    rpcUrls: { default: { http: [CONFIG.rpcUrl] } },\n  },\n  transport: http(CONFIG.rpcUrl),\n})\n\n// Step 1: Request nonce\nconst nonceRes = await fetch(`${CONFIG.apiUrl}/auth/nonce`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ address: account.address }),\n})\nconst { nonce } = await nonceRes.json()\n\n// Step 2: Sign the nonce\nconst signature = await walletClient.signMessage({ message: nonce })\n\n// Step 3: Create session\nconst sessionRes = await fetch(`${CONFIG.apiUrl}/auth/session`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({\n    signature,\n    nonce,\n    chain_id: CONFIG.chainId,\n  }),\n})\n\n// Extract session cookie from response headers\nconst sessionCookie = sessionRes.headers.get(\"set-cookie\")\nconst { account_info } = await sessionRes.json()\n\nconsole.log(\"Logged in as:\", account_info.account_id)\n\nUsing Session Cookie\n// Use session cookie for authenticated requests\nconst headers = { Cookie: sessionCookie }\n\n// Example: Create API Key (requires session)\nconst apiKeyRes = await fetch(`${CONFIG.apiUrl}/api-key`, {\n  method: \"POST\",\n  headers: { ...headers, \"Content-Type\": \"application/json\" },\n  body: JSON.stringify({ name: \"My Bot\", expires_in_days: 365 }),\n})\nconst { api_key } = await apiKeyRes.json()\nconsole.log(\"API Key:\", api_key) // Store this securely!\n\nLogout\nawait fetch(`${CONFIG.apiUrl}/auth/delete_session`, {\n  method: \"DELETE\",\n  headers: { Cookie: sessionCookie },\n})\n\nTypeScript Interfaces\ninterface AuthNonceRequest {\n  address: string\n}\n\ninterface AuthNonceResponse {\n  nonce: string\n}\n\ninterface AuthSessionRequest {\n  signature: string\n  nonce: string\n  chain_id: number\n  wallet_address?: string // Optional\n}\n\ninterface AuthSessionResponse {\n  account_info: {\n    account_id: string\n    nickname: string\n    bio: string\n    image_uri: string\n  }\n}\n\nCore Concepts\nBonding Curve\n\nTokens on NadFun start on a bonding curve. The curve defines price and availability:\n\nReal reserves: Actual MON and tokens in the pool\nVirtual reserves: Initial pseudo-reserves for curve math\nK constant: Maintains x*y=k formula for price\nTarget: How many tokens must be sold to graduate\n\nGet curve state with getCurveState(token) → see QUOTE.md\n\nGraduation\n\nWhen enough tokens are bought:\n\nCurve reaches target reserve\nLiquidity moves to Uniswap V3 pool\nToken transitions from bonding curve to DEX\nisGraduated(token) returns true\n\nCheck progress with getProgress(token) (0-10000 = 0-100%)\n\nAction IDs\n\nThe actionId parameter in token creation identifies the type of action:\n\nactionId\tDescription\n1\tToken Creation\n\nAlways use actionId: 1 when calling the create function.\n\nPermit Signatures\n\nEIP-2612 lets wallets sign approval transactions instead of sending separate approve() calls:\n\nGenerate signature: generatePermitSignature(token, spender, amount, deadline)\nUse in trade: sellPermit({ ...params, ...signature })\nNo separate approve needed—saves gas\n\nSee TRADING.md for details.\n\nCommon Patterns\nPattern 1: Simple Trade\n// Get quote (3 args: token, amountIn, isBuy)\nconst [router, amountOut] = await publicClient.readContract({\n  address: LENS,\n  abi: lensAbi,\n  functionName: \"getAmountOut\",\n  args: [token, amountIn, true], // true = buy\n})\n\n// Buy with slippage protection (1 tuple arg)\nconst minOut = (amountOut * BigInt(995)) / BigInt(1000) // 0.5% slippage\nconst deadline = BigInt(Math.floor(Date.now() / 1000) + 300)\nconst tx = await walletClient.writeContract({\n  address: router, // Use router returned from getAmountOut\n  abi: bondingCurveRouterAbi,\n  functionName: \"buy\",\n  args: [\n    {\n      amountOutMin: minOut,\n      token: token,\n      to: account.address,\n      deadline: deadline,\n    },\n  ],\n  value: amountIn,\n})\n\n\nSee TRADING.md for full examples.\n\nPattern 2: Launch Token\nimport { bondingCurveRouterAbi } from \"./abis/router\"\n\n// Requires API_KEY and deployFeeAmount (see CREATE.md for feeConfig())\n\n// 1. Upload image to Agent API (raw binary, NOT formData)\nconst imageRes = await fetch(`${CONFIG.apiUrl}/agent/token/image`, {\n  method: \"POST\",\n  headers: {\n    \"X-API-Key\": API_KEY,\n    \"Content-Type\": \"image/png\", // or 'image/jpeg', 'image/webp', 'image/svg+xml'\n  },\n  body: imageBuffer, // raw binary data (Buffer, Blob, or ArrayBuffer)\n})\nconst { image_uri: imageUri } = await imageRes.json()\n\n// 2. Upload metadata to Agent API\nconst metadataRes = await fetch(`${CONFIG.apiUrl}/agent/token/metadata`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\", \"X-API-Key\": API_KEY },\n  body: JSON.stringify({\n    name: \"My Token\",\n    symbol: \"MTK\",\n    description: \"My awesome token\",\n    image_uri: imageUri,\n  }),\n})\nconst { metadata_uri: metadataUri } = await metadataRes.json()\n\n// 3. Mine salt via Agent API\nconst saltRes = await fetch(`${CONFIG.apiUrl}/agent/salt`, {\n  method: \"POST\",\n  headers: { \"Content-Type\": \"application/json\", \"X-API-Key\": API_KEY },\n  body: JSON.stringify({\n    creator: account.address,\n    name: \"My Token\",\n    symbol: \"MTK\",\n    metadata_uri: metadataUri,\n  }),\n})\nconst { salt } = await saltRes.json()\n\n// 4. Create token on-chain\nconst tx = await walletClient.writeContract({\n  address: BONDING_CURVE_ROUTER,\n  abi: bondingCurveRouterAbi,\n  functionName: \"create\",\n  args: [\n    {\n      name: \"My Token\",\n      symbol: \"MTK\",\n      tokenURI: metadataUri,\n      amountOut: 0n, // Set > 0n for initial buy amount (in tokens)\n      salt: salt,\n      actionId: 1, // Token creation action identifier (always 1 for create)\n    },\n  ],\n  value: deployFeeAmount, // plus optional initial buy MON if amountOut > 0\n  gas, // Use estimated gas (see below)\n})\n\nconsole.log(\"Transaction:\", tx)\n\n// Gas estimation (recommended over hardcoded values)\nconst gasEstimate = await publicClient.estimateContractGas({\n  address: CONFIG.BONDING_CURVE_ROUTER,\n  abi: bondingCurveRouterAbi,\n  functionName: \"create\",\n  args: [\n    { name: \"My Token\", symbol: \"MTK\", tokenURI: metadataUri, amountOut: 0n, salt, actionId: 1 },\n  ],\n  value: deployFeeAmount,\n  account: account.address,\n})\nconst gas = (gasEstimate * 120n) / 100n // 20% buffer for safety\n\n\nSee CREATE.md for step-by-step.\n\nPrompts for AI Agents\n\nUse these prompts to guide your work:\n\nTrading\n\"Get a price quote for token X with 0.1 MON\"\n\"Buy 0.1 MON of token X with 1% slippage\"\n\"Sell all tokens with permit signature\"\n\"Check if token has graduated\"\nToken Info\n\"Get metadata for token address X\"\n\"Check my MON balance\"\n\"Get available tokens to buy before graduation\"\nCreation\n\"Launch a token called MyToken (MTK) with this image\"\n\"Mine a vanity address for my token\"\n\"Check token creation fees\"\nAnalysis\n\"Calculate graduation progress for token X\"\n\"Get the bonding curve state for token X\"\n\"Track all swaps on the graduated token\"\n\"Analyze token creation rate\"\nRequired Files\n\nFor integration, you'll need:\n\nabis/\n├── curve.ts              # Bonding curve contract ABI\n├── lens.ts               # Price quote ABI\n├── router.ts             # DEX router ABI\n├── token.ts              # ERC20 token ABI\n└── v3*.ts                # Uniswap V3 ABIs\n\nconstants.ts              # Network configs, contract addresses\n\n\nAll ABIs are documented in ABI.md.\n\nABI Import Guide\n\nEach ABI can be copied from ABI.md. Reference the correct section:\n\nABI\tABI.md Section\tPurpose\nbondingCurveRouterAbi\tBondingCurveRouter ABI\tToken creation, buy/sell\nlensAbi\tLens ABI\tPrice quotes, getAmountOut\ncurveAbi\tCurve ABI\tCurve state, graduation check\ntokenAbi\tToken ABI\tERC20 operations, permit signing\n\nExample import pattern:\n\n// Copy the ABI from ABI.md into your project\nimport { bondingCurveRouterAbi } from \"./abis/router\"\nimport { lensAbi } from \"./abis/lens\"\n\nInstallation\nnpm install viem\n# or\npnpm add viem\n# or\nyarn add viem\n\nDependencies\n{\n  \"viem\": \"^2.0.0\"\n}\n\n\nPure viem. No other blockchain libraries needed.\n\nTroubleshooting\n\"No such contract\"\n\nYou're on the wrong network. Check NETWORK constant matches your setup.\n\n\"Token not graduated yet\"\n\nQuery getProgress() via Lens contract. Returns 0-10000. Need 10000 (100%) to graduate.\n\n\"Transaction reverted\"\nCheck amountOutMin—slippage might be too high or curve moved\nVerify deadline—transaction took too long\nCheck allowance—approve token before sell\nNext Steps\n\nPick a guide based on what you need:\n\nBuilding a dex bot? → TRADING.md\nCreating a dashboard? → INDEXER.md + QUOTE.md\nLaunching tokens? → CREATE.md\nToken info queries? → TOKEN.md\n\nEach guide has complete examples ready to copy.\n\nGeneral Development Practices & Troubleshooting\nType Safety Tips\n\nAlways 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:\n\n// Types are automatically narrowed\nconst result = await contract.read.getAmountOut([...])\n// result type is precisely bigint (not bigint | undefined)\n\n\nUse viem type helpers for type-safe conversions:\n\nimport { Address, Hex } from \"viem\"\nimport { parseEther, formatEther } from \"viem\"\n\n// Amounts\nconst wei = parseEther(\"1\") // string -> bigint\nconst eth = formatEther(1000000000000000000n) // bigint -> string\n\n// Addresses\nconst addr: Address = \"0x...\" // Validated address type\n\n// Signatures\nconst sig: Hex = \"0x...\" // Hex string type\n\nCommon ABI Errors\n\nWhen interacting with smart contracts, you might encounter specific errors. Here's a table of common ABI-related errors and how to approach them:\n\nError\tMeaning\nInsufficientAmount\tOutput less than amountOutMin\nInsufficientAmountOut\tInsufficient output amount\nDeadlineExpired\tDeadline has passed\nUnauthorized\tCaller not authorized\nAlreadyGraduated\tToken already graduated to DEX\nBondingCurveLocked\tCurve locked during graduation\nInvalidProof\tMerkle proof verification failed (specific to claims)\nAlreadyClaimed\tAmount already claimed for this proof (specific to claims)\nNotClaimable\tToken not eligible for claims yet (specific to claims)\nInsufficientBalance\tTreasury has insufficient MON balance (specific to claims)\n\nCheck error types in viem with:\n\nimport { ContractFunctionExecutionError } from 'viem'\n\ntry {\n  await contract.write.buy([...]) // or any contract interaction\n} catch (error) {\n  if (error instanceof ContractFunctionExecutionError) {\n    console.log(error.shortMessage) // \"InsufficientAmount\", etc.\n  }\n}"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/portdeveloper/nadfun",
    "publisherUrl": "https://clawhub.ai/portdeveloper/nadfun",
    "owner": "portdeveloper",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/nadfun",
    "downloadUrl": "https://openagent3.xyz/downloads/nadfun",
    "agentUrl": "https://openagent3.xyz/skills/nadfun/agent",
    "manifestUrl": "https://openagent3.xyz/skills/nadfun/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/nadfun/agent.md"
  }
}