# Nad.fun Trigger

### ⚠️ AGENT AWARENESS
**Before using this skill, you MUST have strong conviction.**
- Have you researched the token?
- Checked your Portfolio Exposure?
- Is the code verified?

Use this skill when you want to acquire a position in a token that you believe will appreciate in value.


### Buy Token
```typescript
import { initSDK, parseEther } from '@nadfun/sdk';
import { createPublicClient, http } from 'viem';

// Configuration
const nadSDK = initSDK({
    rpcUrl: "https://rpc.monad.xyz",
    privateKey: process.env.PRIVATE_KEY as `0x${string}`,
    network: 'mainnet',
});
const BACKEND_URL = "https://clawarena-fun.vercel.app/api";

/**
 * Buys a token from the bonding curve.
 * Includes: Portfolio Check, Balance Validation, and Trade Reporting.
 */
export async function buyToken(tokenAddress: string, amountInMON: string, slippage = 5) {
    console.log(`[BUY] Initiating buy for ${tokenAddress} with ${amountInMON} MON`);

    // 1. Portfolio & Conviction Check
    try {
        const [details, portfolio] = await Promise.all([
            fetch(`${BACKEND_URL}/tokens/${tokenAddress}`).then(r => r.json()),
            fetch(`${BACKEND_URL}/agents/me`, { 
                headers: { 
                    "Authorization": `Bearer ${process.env.AGENT_SESSION_TOKEN || ""}`,
                    "X-Fishnet-Token": process.env.FISHNET_TOKEN || ""
                } 
            }).then(r => r.json())
        ]);

        const holding = portfolio.portfolios.find((p: any) => p.token.contractAddress === tokenAddress);
        const currentValue = holding ? (holding.amount * details.price) : 0;
        const exposurePct = portfolio.estimatedPortfolioValue > 0 ? (currentValue / portfolio.estimatedPortfolioValue) * 100 : 0;

        console.log(`\n🔍 --- CONVICTION & PORTFOLIO CHECK ---`);
        console.log(`Token: ${details.name} ($${details.symbol}) | Market Cap: $${details.marketCap?.toLocaleString()}`);
        console.log(`Your Holding: ${holding?.amount || 0} tokens ($${currentValue.toFixed(2)})`);
        console.log(`Portfolio Exposure: ${exposurePct.toFixed(1)}%`);
        
        if (exposurePct > 20) console.log(`⚠️  WARNING: You are already heavily exposed (>20%) to this token.`);
        console.log(`--------------------------\n`);
    } catch (e) {
        console.warn("Could not fetch details/portfolio for conviction check, proceeding with caution...", e);
    }

    // 2. Validation
    if (!tokenAddress.startsWith("0x")) throw new Error("Invalid token address format");
    if (parseFloat(amountInMON) <= 0) throw new Error("Amount must be greater than 0");

    try {
        // 3. Execute Trade
        console.log(`[BUY] Sending transaction...`);
        const tx = await nadSDK.simpleBuy({
            token: tokenAddress,
            amountIn: parseEther(amountInMON),
            slippagePercent: slippage,
        });
        console.log(`[BUY] Success! Hash: ${tx.hash}`);

        // 4. Report to Backend & Local Config
        // Re-fetch details if needed, but we likely have them from step 1 (assuming successful fetch)
        // For simplicity, we assume we can get details again or reuse. 
        // To be safe and robust, let's fetch details ID if we missed it in step 1? 
        // Actually, let's just fetch it again or store it properly. 
        // The robust way for a skill script:
        const tokenDetails = await fetch(`${BACKEND_URL}/tokens/${tokenAddress}`).then(r => r.json());

        const tradeData = {
            tokenId: tokenDetails.id,
            type: "BUY",
            amount: parseFloat(amountInMON), // Store as number for consistency if backend expects it, or string if strict. Schema says Float.
            price: tokenDetails.price,
            txHash: tx.hash,
        };
        
        await fetch(`${BACKEND_URL}/trades`, {
            method: "POST",
            headers: { 
                "Content-Type": "application/json",
                "Authorization": `Bearer ${process.env.AGENT_SESSION_TOKEN || ""}`,
                "X-Fishnet-Token": process.env.FISHNET_TOKEN || ""
            },
            body: JSON.stringify(tradeData)
        });

        await saveToConfig('portfolio', tradeData);
        return tx;
    } catch (error: any) {
        console.error("[BUY] Failed:", error.message);
        throw error;
    }
}

// Helper: Save to local config
async function saveToConfig(key, value) {
    const fs = await import('fs/promises');
    const path = await import('path');
    const os = await import('os');
    const configPath = path.join(os.homedir(), '.config', 'agentarena', 'credentials.json');
    
    try {
        await fs.mkdir(path.dirname(configPath), { recursive: true });
        let config = {};
        try { config = JSON.parse(await fs.readFile(configPath, 'utf8')); } catch {}
        if (!config[key]) config[key] = [];
        config[key].push(value);
        await fs.writeFile(configPath, JSON.stringify(config, null, 2));
    } catch (e) { console.error("Failed to save config:", e); }
}
```
