Skill: therealharpaljadeja/nadfun-token-creation (version 1.0.0)

--- name: create-token description: Guide for creating a token on Nad.fun. Covers the full 4-step flow - uploading an image, uploading metadata, mining a salt for a vanity address, and deploying the token on-chain via the BondingCurveRouter contract. user-invocable: true argument-hint: [name] [symbol] --- # Nad.fun Token Creation Flow ## Prerequisite: monad-development Skill Before proceeding, check if the `monad-development` skill is installed. If it is not available, install it using ClawHub: ```bash clawhub search "monad" ``` Find and install the `monad-development` skill from the results. This skill is required for wallet management and on-chain actions in Step 3 and Step 4. --- Help the user create a token on Nad.fun by following the 4-step sequential process below. Each step depends on the output of the previous step. ## API Base URL **Production:** `https://api.nadapp.net` ## Contract Addresses ``` BondingCurveRouter = [REDACTED_SECRET] Lens = [REDACTED_SECRET] ``` --- ## Step 1: Upload Image **POST** `/agent/token/image` - **Content-Type:** `image/png`, `image/jpeg`, `image/webp`, or `image/svg+xml` - **Body:** Raw binary image data (max 5MB) - **Returns:** `image_uri` (CDN URL) and `is_nsfw` (boolean) ```js const imageResponse = await fetch("https://api.nadapp.net/agent/token/image", { method: "POST", headers: { "Content-Type": imageFile.type }, body: imageFile, }); const { image_uri, is_nsfw } = await imageResponse.json(); ``` ### Error Codes | Status | Description | |--------|-------------| | 400 | Invalid image format or missing image | | 413 | Image exceeds 5MB limit | | 500 | NSFW check failed or upload failed | --- ## Step 2: Upload Metadata **POST** `/agent/token/metadata` - **Content-Type:** `application/json` - **Requires:** `image_uri` from Step 1 ### Request Body **Required fields:** | Field | Type | Constraints | |-------|------|-------------| | `image_uri` | string | Must be from `https://storage.nadapp.net/` | | `name` | string | 1-32 characters | | `symbol` | string | 1-10 characters, alphanumeric only (`/^[a-zA-Z0-9]+$/`) | **Optional fields:** | Field | Type | Constraints | |-------|------|-------------| | `description` | string or null | Max 500 characters | | `website` | string or null | Must start with `https://` | | `twitter` | string or null | Must contain `x.com` and start with `https://` | | `telegram` | string or null | Must contain `t.me` and start with `https://` | ```js const metadataResponse = await fetch("https://api.nadapp.net/agent/token/metadata", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ image_uri, name: "My Token", symbol: "MTK", description: "An awesome token for the Nad.fun", website: "https://mytoken.com", twitter: "https://x.com/mytoken", telegram: "https://t.me/mytoken", }), }); const { metadata_uri } = await metadataResponse.json(); ``` ### Error Codes | Status | Description | |--------|-------------| | 400 | NSFW status unknown, invalid data, or validation failed | | 500 | Upload to storage or database failed | --- ## Step 3: Mine Salt **POST** `/agent/salt` - **Content-Type:** `application/json` - **Requires:** `metadata_uri` from Step 2 - Produces a vanity token address ending in `7777` ### Request Body | Field | Type | Description | |-------|------|-------------| | `creator` | string | Creator's wallet address (EVM format) | | `name` | string | Token name (must match metadata) | | `symbol` | string | Token symbol (must match metadata) | | `metadata_uri` | string | Metadata URI from Step 2 | ```js const saltResponse = await fetch("https://api.nadapp.net/agent/salt", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ creator: walletAddress, name: "My Token", symbol: "MTK", metadata_uri: metadataUri, }), }); const { salt, address } = await saltResponse.json(); ``` - **Returns:** `salt` (bytes32 hex) and `address` (token address with `7777` suffix) ### Error Codes | Status | Description | |--------|-------------| | 400 | Invalid parameters | | 408 | Timeout - max iterations reached | | 500 | Internal server error | --- ## Step 4: Create Token On-Chain Call `BondingCurveRouter.create()` with the data from previous steps. ### TokenCreationParams ```solidity struct TokenCreationParams { string name; string symbol; string tokenURI; // metadata_uri from Step 2 uint256 amountOut; // 0 for no initial buy, or use Lens.getInitialBuyAmountOut(amountIn) bytes32 salt; // salt from Step 3 uint8 actionId; // always 1 (graduate to Capricorn V3) } ``` ```solidity function create(TokenCreationParams calldata params) external payable returns (address token, address pool); ``` ### Option A: Create Without Initial Buy Send only the deploy fee as `msg.value`. ```js const curve = new ethers.Contract(BONDING_CURVE_ADDRESS, BONDING_CURVE_ABI, signer); const [deployFee,,] = await curve.feeConfig(); const params = { name, symbol, tokenURI: metadata_uri, amountOut: 0, salt, actionId: 1, }; const tx = await router.create(params, { value: deployFee }); await tx.wait(); ``` ### Option B: Create With Initial Buy Send `deployFee + amountIn` as `msg.value`. Use `Lens.getInitialBuyAmountOut(amountIn)` for `amountOut`. ```js const lens = new ethers.Contract(LENS_ADDRESS, LENS_ABI, signer); const expectedAmountOut = await lens.getInitialBuyAmountOut(amountIn); const [deployFee,,] = await curve.feeConfig(); const params = { name, symbol, tokenURI: metadata_uri, amountOut: expectedAmountOut, salt, actionId: 1, }; const tx = await router.create(params, { value: deployFee + amountIn }); await tx.wait(); ``` --- ## Wallet for On-Chain Actions For Step 3 (salt mining) and Step 4 (on-chain deployment), use the wallet from the `monad-development` skill. That skill handles all wallet configuration, private key management, and RPC setup. Use the signer and wallet address it provides when calling the salt API (`creator` field) and when sending the `BondingCurveRouter.create()` transaction. --- ## Important Rules 1. **Sequential process** - Each step depends on the previous step's output. 2. **NSFW validation** - Images are auto-checked in Step 1; the flag carries into metadata. 3. **URL validation** - All URLs must use HTTPS. Twitter must use `x.com`, Telegram must use `t.me`. 4. **Image domain restriction** - Only `https://storage.nadapp.net/` image URIs are accepted in metadata. 5. **Salt mining** - May timeout if the vanity address pattern can't be found within iteration limits. 6. **actionId** - Always use `1` (graduate to Capricorn V3). ## When Generating Code - Use `ethers` v6 syntax by default unless the user specifies otherwise. - Always handle errors for each API call before proceeding to the next step. - The `salt` from Step 3 and `metadata_uri` from Step 2 are both needed for Step 4. - For initial buy, always query `Lens.getInitialBuyAmountOut()` to get the correct `amountOut`.


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)