Skill: lvcidpsyche/solpaw-launcher (version 3.0.2)

--- name: solpaw description: Launch Solana tokens on Pump.fun via the SolPaw platform. 0.1 SOL one-time fee. Your wallet is the onchain creator. homepage: https://solpaw.fun user-invocable: true disable-model-invocation: true command-dispatch: tool command-tool: exec command-arg-mode: raw metadata: {"openclaw": {"emoji": "🐾", "requires": {"bins": ["curl"], "env": ["SOLPAW_API_KEY", "SOLPAW_CREATOR_WALLET", "SOLANA_PRIVATE_KEY", "SOLPAW_API_URL"], "config": []}, "primaryEnv": "SOLPAW_API_KEY", "install": []}} --- # SolPaw — Launch Tokens on Solana via Pump.fun ## When to use Use this skill when the user explicitly asks to: - Launch a new memecoin / token on Solana via Pump.fun - Deploy a token with a name, symbol, description, and image - Create a Pump.fun token listing for a community, project, or meme **This skill MUST only be invoked by the user.** Do not autonomously launch tokens. ## Overview SolPaw is the first Solana token-launch platform for autonomous agents. It handles IPFS metadata uploads, transaction building, and Pump.fun deployment. - **Cost**: 0.1 SOL one-time platform fee + ~0.02 SOL Pump.fun creation fee per launch - **Creator**: Your agent's wallet is the real onchain creator on Pump.fun - **Limit**: 1 launch per agent per 24 hours - **Platform wallet**: [REDACTED_SECRET] - **Docs**: https://solpaw.fun ## Security - **Ephemeral wallets recommended**: Use a dedicated launch wallet with only the SOL needed (~0.15 SOL). Never use your main wallet's private key. - **SOLANA_PRIVATE_KEY** is used exclusively for local transaction signing. It is never transmitted to the SolPaw API server — signing happens client-side. - **API key** (`SOLPAW_API_KEY`) authenticates requests but cannot sign transactions or move funds. - **CSRF tokens** are single-use and expire after 30 minutes, preventing replay attacks. - **Fee signatures** are verified onchain and cannot be reused for multiple launches. - **Daily limit**: 1 launch per agent per 24 hours, enforced server-side. - **All secrets** (`SOLPAW_API_KEY`, `SOLANA_PRIVATE_KEY`) must be stored in environment variables, never in code or chat. ## Prerequisites 1. A Solana wallet with at least 0.15 SOL (0.1 platform fee + ~0.02 Pump.fun fee + gas) 2. A SolPaw API key (register at the API) 3. Environment variables set: - `SOLPAW_API_KEY` — your SolPaw API key - `SOLPAW_CREATOR_WALLET` — your Solana wallet public key - `SOLANA_PRIVATE_KEY` — your wallet private key (base58 encoded, for local signing only — never sent to server) - `SOLPAW_API_URL` — API base URL (default: `https://api.solpaw.fun/api/v1`) ## Steps ### Step 1: Register (one-time) ```bash curl -s -X POST https://api.solpaw.fun/api/v1/agents/register \ -H "Content-Type: application/json" \ -d '{"agent_name":"MyAgent","default_fee_wallet":"YOUR_WALLET_ADDRESS"}' | jq . ``` Save the `api_key` from the response. It will NOT be shown again. ### Step 2: Get a CSRF token ```bash CSRF=$(curl -s -H "Authorization: Bearer $SOLPAW_API_KEY" \ https://api.solpaw.fun/api/v1/agents/csrf | jq -r '.data.csrf_token') ``` ### Step 3: Send 0.1 SOL launch fee Send 0.1 SOL (100,000,000 lamports) to the platform wallet: [REDACTED_SECRET] Save the transaction signature. ### Step 4: Upload token image (optional but recommended) ```bash IMAGE_ID=$(curl -s -X POST https://api.solpaw.fun/api/v1/tokens/upload-image \ -H "Authorization: Bearer $SOLPAW_API_KEY" \ -F "file=@token-logo.png" | jq -r '.data.image_id') ``` ### Step 5: Launch token (Local Mode — your wallet is the creator) ```bash # Build unsigned transaction TX_DATA=$(curl -s -X POST https://api.solpaw.fun/api/v1/tokens/launch-local \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SOLPAW_API_KEY" \ -d '{ "name": "MyCoolToken", "symbol": "MCT", "description": "An awesome token launched by an AI agent on SolPaw", "creator_wallet": "'$SOLPAW_CREATOR_WALLET'", "signer_public_key": "'$SOLPAW_CREATOR_WALLET'", "launch_fee_signature": "YOUR_FEE_TX_SIGNATURE", "image_id": "'$IMAGE_ID'", "initial_buy_sol": 0, "slippage": 10, "priority_fee": 0.0005, "csrf_token": "'$CSRF'" }') # Sign the transaction with your private key, then submit SIGNED_TX="..." # sign the base64 transaction from TX_DATA curl -s -X POST https://api.solpaw.fun/api/v1/tokens/submit \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $SOLPAW_API_KEY" \ -d '{"signed_transaction": "'$SIGNED_TX'", "mint": "MINT_FROM_TX_DATA"}' ``` ### Using the TypeScript SDK (Easier) ```typescript import SolPawSkill from './solpaw-skill'; import { Keypair } from '@solana/web3.js'; const solpaw = new SolPawSkill({ apiEndpoint: 'https://api.solpaw.fun/api/v1', [REDACTED_SECRET], defaultCreatorWallet: process.env.SOLPAW_CREATOR_WALLET, }); const keypair = Keypair.fromSecretKey(bs58.decode(process.env.SOLANA_PRIVATE_KEY)); // One-call launch: pays fee + uploads + signs + submits const result = await solpaw.payAndLaunch({ name: 'MyCoolToken', symbol: 'MCT', description: 'Launched by an AI agent on SolPaw', image_url: 'https://example.com/logo.png', initial_buy_sol: 0.5, }, keypair); console.log(result.pumpfun_url); // https://pump.fun/coin/... ``` ## Constraints - **DO NOT launch tokens without explicit user approval** — always confirm name, symbol, and description first - DO NOT launch more than 1 token per 24 hours (enforced server-side) - DO NOT include offensive or misleading token names/descriptions - ALWAYS include a token image — tokens without images perform poorly on Pump.fun - ALWAYS use Local Mode (pass `signer_keypair`) so the agent's wallet is the onchain creator - The 0.1 SOL platform fee is non-refundable once the launch succeeds - CSRF tokens expire after 30 minutes and are single-use - Image uploads expire after 30 minutes - NEVER log, display, or transmit `SOLANA_PRIVATE_KEY` — it is used for local signing only ## Examples ### Successful launch ``` Agent: I'll launch the DOGE2 token on Pump.fun for you. > Uploading token image... > Paying 0.1 SOL launch fee... > Building transaction... > Signing and submitting... > Token launched successfully! > Pump.fun: https://pump.fun/coin/So1... > Mint: So1... > Your wallet is the onchain creator. ``` ### Error: insufficient balance ``` Agent: Your wallet only has 0.05 SOL. You need at least 0.15 SOL to launch: - 0.1 SOL platform fee - ~0.02 SOL Pump.fun creation fee - ~0.01 SOL for gas ```

path: README.md
content: # SolPaw Skill for OpenClaw

**Launch tokens on Solana via Pump.fun — directly from your OpenClaw agent.**

[![Version](https://img.shields.io/badge/version-1.0.0-blue.svg)](https://github.com/LvcidPsyche/solpaw-skill)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
[![Website](https://img.shields.io/badge/Website-solpaw.fun-orange)](https://solpaw.fun)
[![API Docs](https://img.shields.io/badge/API-Docs-blue)](https://solpaw.fun/docs)
[![ClawHub](https://img.shields.io/badge/ClawHub-Install-purple)](https://clawhub.ai/LvcidPsyche/solpaw-skill-final)

---

## Overview

SolPaw Skill enables OpenClaw agents to autonomously launch memecoins on Solana through Pump.fun. Perfect for:

- AI agents creating community tokens
- Automated trading bot launches
- Agent identity/reputation tokens
- Experimental DeFi projects

**Pricing:**
- **0.1 SOL** one-time launch fee
- **No ongoing fees ever**
- Creator wallet receives 100% of Pump.fun trading fees

---

## Quick Start

### 1. Install the Skill

```bash
openclaw skills install solpaw-launcher
```

Or manually clone to your skills directory:

```bash
cd ~/.openclaw/skills
git clone https://github.com/LvcidPsyche/solpaw-skill.git solpaw-launcher
```

### 2. Configure

Add to your `agent-config.yml`:

```yaml
skills:
  - name: solpaw-launcher
    config:
      api_endpoint: https://api.solpaw.fun/api/v1
      [REDACTED_SECRET]
      default_creator_wallet: ${CREATOR_WALLET}
```

Set environment variables:

```bash
export SOLPAW_API_KEY="sk-solpaw-your-api-key"
export CREATOR_WALLET="YourSolanaWalletAddress"
```

### 3. Register Your Agent

```bash
curl -X POST https://api.solpaw.fun/api/v1/agents/register \
  -H "Content-Type: application/json" \
  -d '{
    "agent_name": "MyCoolAgent",
    "default_fee_wallet": "'${CREATOR_WALLET}'"
  }'
```

Save the returned `api_key` — it's shown only once.

### 4. Launch a Token

```typescript
import SolPawSkill from './solpaw-skill';

const solpaw = new SolPawSkill({
  apiEndpoint: 'https://api.solpaw.fun/api/v1',
  [REDACTED_SECRET],
  defaultCreatorWallet: process.env.CREATOR_WALLET,
});

// Launch!
const result = await solpaw.launchToken({
  name: 'AgentCoin',
  symbol: 'AGENT',
  description: 'Launched autonomously by an AI agent on Solana',
  launch_fee_signature: 'your-0.1-sol-payment-signature',
  initial_buy_sol: 0.5,
});

if (result.success) {
  console.log(`🚀 Token launched: ${result.pumpfun_url}`);
  console.log(`💰 Mint: ${result.mint}`);
} else {
  console.error(`❌ Launch failed: ${result.error}`);
}
```

---

## API Reference

### Constructor

```typescript
new SolPawSkill(config: SolPawConfig)
```

**Config:**
- `apiEndpoint` (string, required): SolPaw API URL
- `apiKey` (string, required): Your agent API key
- `defaultCreatorWallet` (string, required): Default Solana wallet for fees

### Methods

#### `getPlatformInfo()`

Get platform configuration — wallet address, launch fee, and daily limits.

```typescript
const info = await solpaw.getPlatformInfo();
// {
//   platform_wallet: [REDACTED_SECRET],
//   launch_fee_sol: 0.1,
//   daily_limit: 1
// }
```

#### `launchToken(params)`

Launch a token on Pump.fun.

**Parameters:**
- `name` (string, required): Token name (min 2 chars)
- `symbol` (string, required): Token symbol (min 2 chars)
- `description` (string, required): Token description (min 10 chars)
- `launch_fee_signature` (string, required): Transaction signature of 0.1 SOL payment
- `image_url` (string, optional): Token image URL
- `creator_wallet` (string, optional): Override default creator wallet
- `twitter` (string, optional): Twitter/X URL
- `telegram` (string, optional): Telegram URL
- `website` (string, optional): Website URL
- `initial_buy_sol` (number, optional): Initial SOL to buy (default: 0)
- `slippage` (number, optional): Slippage % (default: 10)
- `priority_fee` (number, optional): Priority fee in SOL (default: 0.0005)

**Returns:**
```typescript
{
  success: boolean;
  mint?: string;              // Token mint address
  signature?: string;         // Transaction signature
  pumpfun_url?: string;       // Pump.fun page URL
  solscan_url?: string;       // Solscan explorer URL
  launch_fee?: {
    amount_sol: number;
    platform_wallet: string;
    payment_signature: string;
  };
  error?: string;             // Error message if failed
}
```

#### `getMyTokens(page?, limit?)`

List tokens launched by this agent.

```typescript
const { tokens, total } = await solpaw.getMyTokens(1, 20);
```

#### `getFeeSummary()`

Get fee earnings summary.

```typescript
const fees = await solpaw.getFeeSummary();
// {
//   total_fees_sol: 1.5,
//   platform_share_sol: 0.15,
//   token_count: 3
// }
```

#### `getPlatformStats()`

Get public platform statistics.

```typescript
const stats = await solpaw.getPlatformStats();
```

---

## Launch Flow

```
┌─────────────┐     ┌──────────────┐     ┌─────────────────┐
│   Agent     │────▶│  SolPaw API  │────▶│  PumpPortal API │
│  (You)      │     │ (This Skill) │     │   (pump.fun)    │
└──────┬──────┘     └──────────────┘     └─────────────────┘
       │                                         │
       │ 1. Send 0.1 SOL to platform wallet      │
       │◄────────────────────────────────────────┘
       │
       │ 2. Call launchToken() with tx signature
       │─────────────────────────────────────────▶
       │
       │ 3. Server verifies payment on-chain
       │    Uploads metadata to IPFS
       │    Calls PumpPortal API
       │
       │◄─────────────────────────────────────────
       │ 4. Return mint, signature, URLs
```

---

## Security

- **Private keys never touch the server** — You sign the 0.1 SOL payment locally
- **CSRF protection** — Single-use tokens for state-changing operations
- **Rate limiting** — 3 launches per minute, 1 per day per agent
- **Payment verification** — Each 0.1 SOL transaction verified on-chain
- **Signature deduplication** — Each payment can only be used once

---

## Self-Hosting (Optional)

Want to run your own SolPaw instance?

```bash
git clone https://github.com/LvcidPsyche/solpaw.git
cd solpaw
cp .env.example .env
# Edit .env with your values
docker compose up -d
```

See the [main repo](https://github.com/LvcidPsyche/solpaw) for full deployment docs.

---

## Requirements

- OpenClaw agent with skills support
- Node.js 20+ (for TypeScript skill)
- Solana wallet with 0.1 SOL + transaction fees
- PumpPortal API key (if self-hosting)

---

## License

MIT © 2026 SolPaw

---

## Links

- **Main Repo:** https://github.com/LvcidPsyche/solpaw
- **API Docs:** https://api.solpaw.fun/api/v1/info
- **Pump.fun:** https://pump.fun
- **OpenClaw:** https://openclaw.ai


path: package.json
content: {
  "name": "solpaw-skill",
  "version": "1.0.0",
  "description": "OpenClaw skill for launching tokens on Solana via Pump.fun",
  "main": "solpaw-skill.ts",
  "types": "solpaw-skill.ts",
  "keywords": [
    "openclaw",
    "skill",
    "solana",
    "pumpfun",
    "token",
    "launchpad",
    "crypto",
    "memecoin"
  ],
  "author": "Redclay",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/LvcidPsyche/solpaw-skill.git"
  },
  "peerDependencies": {
    "@solana/web3.js": "^1.95.0"
  },
  "engines": {
    "node": ">=20.0.0"
  }
}


path: references/api-docs.md
content: # SolPaw API Reference

Base URL: `https://api.solpaw.fun/api/v1`

## Authentication

All authenticated endpoints require:
```
[REDACTED_SECRET]
```

State-changing endpoints also require a CSRF token (from `/agents/csrf`), passed as `csrf_token` in the request body or `X-CSRF-Token` header.

## Endpoints

### POST /agents/register
Register a new agent and receive an API key.

**Body:**
```json
{
  "agent_name": "string (3-50 chars)",
  "default_fee_wallet": "Solana address"
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "agent_id": "agent_...",
    "api_key": "sk-solpaw-...",
    "message": "Store this API key securely. It will NOT be shown again."
  }
}
```

### GET /agents/csrf (Auth required)
Get a single-use CSRF token. Expires in 30 minutes.

### POST /tokens/upload-image (Auth required)
Upload a token image (multipart form data).

**Form field:** `file` — PNG, JPEG, GIF, or WebP (max 5MB)

**Response:**
```json
{
  "success": true,
  "data": {
    "image_id": "uuid",
    "mime_type": "image/png",
    "size_bytes": 12345,
    "expires_in": 1800
  }
}
```

### POST /tokens/launch-local (Auth required) — Recommended
Build an unsigned transaction. Agent signs locally and submits.
Agent's wallet is the onchain creator on Pump.fun.

**Body:**
```json
{
  "name": "string (2-32 chars)",
  "symbol": "string (2-10, alphanumeric)",
  "description": "string (10-500 chars)",
  "creator_wallet": "Solana address",
  "signer_public_key": "Solana address (same as creator_wallet)",
  "launch_fee_signature": "Solana tx signature of 0.1 SOL payment",
  "image_id": "UUID from /tokens/upload-image (optional)",
  "image_url": "HTTPS URL (optional, if no image_id)",
  "image_base64": "base64 string (optional)",
  "image_mime_type": "image/png (required with image_base64)",
  "initial_buy_sol": 0,
  "slippage": 10,
  "priority_fee": 0.0005,
  "csrf_token": "from /agents/csrf",
  "twitter": "HTTPS URL (optional)",
  "telegram": "HTTPS URL (optional)",
  "website": "HTTPS URL (optional)"
}
```

**Response:**
```json
{
  "success": true,
  "data": {
    "transaction": "base64-encoded unsigned transaction",
    "mint_public_key": "So1...",
    "token": { "name": "...", "symbol": "..." },
    "launch_fee": {
      "amount_sol": 0.1,
      "platform_wallet": "6SoPUBp...",
      "payment_signature": "..."
    }
  }
}
```

### POST /tokens/submit (Auth required)
Submit a signed transaction to Solana.

**Body:**
```json
{
  "signed_transaction": "base64-encoded signed transaction",
  "mint": "mint public key",
  "name": "token name",
  "symbol": "token symbol",
  "creator_wallet": "Solana address"
}
```

### POST /tokens/launch (Auth required) — Fallback
Lightning mode: server signs the transaction. Platform wallet is the onchain creator (not recommended).

Same body as `/tokens/launch-local` but without `signer_public_key`.

### GET /tokens (Auth required)
List your launched tokens.

### GET /tokens/stats/platform (Public)
Get platform statistics.

### GET /health (Public)
Server health check.

## Rate Limits

| Endpoint | Limit |
|----------|-------|
| Token launch | 3/min |
| General API | 30/min |
| Daily per agent | 1 per 24h |

## Error Codes

| Code | Status | Meaning |
|------|--------|---------|
| VALIDATION_ERROR | 400 | Invalid request |
| AUTH_MISSING | 401 | No API key |
| AUTH_INVALID | 401 | Bad API key |
| CSRF_INVALID | 403 | Missing/expired CSRF |
| PAYMENT_NOT_FOUND | 400 | Fee tx not found |
| PAYMENT_INSUFFICIENT | 400 | Less than 0.1 SOL |
| PAYMENT_ALREADY_USED | 400 | Signature reused |
| IMAGE_TOO_LARGE | 400 | Image > 5MB |
| DAILY_LAUNCH_LIMIT | 429 | 1 per 24h exceeded |
| LAUNCH_FAILED | 500 | Deployment failed |

## Platform Wallet

Send 0.1 SOL launch fee to: [REDACTED_SECRET]


path: skill.json
content: {
  "name": "solpaw",
  "description": "Launch Solana tokens on Pump.fun via SolPaw. 0.1 SOL one-time fee. Your wallet is the onchain creator.",
  "env": {
    "SOLPAW_API_KEY": "",
    "SOLPAW_CREATOR_WALLET": "",
    "SOLANA_PRIVATE_KEY": "",
    "SOLPAW_API_URL": "https://api.solpaw.fun/api/v1"
  },
  "dependencies": ["curl"],
  "install": {
    "darwin": {
      "command": "echo SolPaw skill ready — set SOLPAW_API_KEY, SOLPAW_CREATOR_WALLET, and SOLANA_PRIVATE_KEY"
    },
    "linux": {
      "command": "echo SolPaw skill ready — set SOLPAW_API_KEY, SOLPAW_CREATOR_WALLET, and SOLANA_PRIVATE_KEY"
    },
    "win32": {
      "command": "echo SolPaw skill ready — set SOLPAW_API_KEY, SOLPAW_CREATOR_WALLET, and SOLANA_PRIVATE_KEY"
    }
  }
}


path: skill.yml
content: name: solpaw-launcher
version: 1.0.0
description: Launch tokens on Solana via Pump.fun from OpenClaw agents
author: Redclay
license: MIT
repository: https://github.com/LvcidPsyche/solpaw-skill
main: solpaw-skill.ts
types: solpaw-skill.ts
keywords:
  - solana
  - pumpfun
  - token
  - launchpad
  - crypto
  - memecoin
  - defi
config:
  - name: api_endpoint
    type: string
    required: true
    default: https://api.solpaw.fun/api/v1
    description: SolPaw API endpoint
  - name: api_key
    type: string
    required: true
    secret: true
    description: Your agent API key from SolPaw
  - name: default_creator_wallet
    type: string
    required: true
    description: Default Solana wallet address for receiving fees
commands:
  - name: launch
    description: Launch a token on Pump.fun
    usage: '!launch name:<name> symbol:<symbol> description:<desc> fee_sig:<signature>'


path: solpaw-skill.ts
content: // ═══════════════════════════════════════════════════════════════════
// SolPaw — OpenClaw Agent Skill
// Drop-in skill for OpenClaw agents to launch tokens on Pump.fun.
// Install: openclaw skills install solpaw-launcher
//
// Launch flow:
//   1. Agent sends 0.1 SOL to platform wallet
//   2. Agent calls launchToken() with the tx signature
//   3. Server verifies the payment onchain, then launches
//   4. No ongoing fees ever.
// ═══════════════════════════════════════════════════════════════════

interface SolPawConfig {
  apiEndpoint: string;
  [REDACTED_SECRET];
  defaultCreatorWallet: string;
}

interface TokenLaunchParams {
  name: string;
  symbol: string;
  description: string;
  launch_fee_signature: string; // tx sig of 0.1 SOL payment to platform wallet
  image_url?: string;
  creator_wallet?: string;
  twitter?: string;
  telegram?: string;
  website?: string;
  initial_buy_sol?: number;
  slippage?: number;
  priority_fee?: number;
}

interface LaunchResult {
  success: boolean;
  mint?: string;
  signature?: string;
  pumpfun_url?: string;
  solscan_url?: string;
  error?: string;
  launch_fee?: {
    amount_sol: number;
    platform_wallet: string;
    payment_signature: string;
  };
}

interface PlatformInfo {
  platform_wallet: string;
  launch_fee_sol: number;
  daily_limit: number;
}

/**
 * SolPaw Launch Skill for OpenClaw Agents
 *
 * Usage in agent config:
 *   skills:
 *     - name: solpaw-launcher
 *       config:
 *         api_endpoint: https://api.solpaw.fun/api/v1
 *         [REDACTED_SECRET]
 *         default_creator_wallet: ${CREATOR_WALLET}
 *
 * Launch flow:
 *   1. Call getPlatformInfo() to get the platform wallet address
 *   2. Send 0.1 SOL to the platform wallet (agent handles this via Solana SDK)
 *   3. Call launchToken() with the payment tx signature + token details
 *   4. Server verifies payment onchain → launches token on Pump.fun
 *
 * Agent can then call:
 *   !launch name: MyToken symbol: MTK description: "A cool token" fee_sig: 5xK...
 */
export class SolPawSkill {
  private config: SolPawConfig;
  private csrfToken: string | null = null;
  private csrfExpiresAt: number = 0;

  // Platform wallet cached from /info endpoint
  static readonly PLATFORM_WALLET = [REDACTED_SECRET];
  static readonly LAUNCH_FEE_SOL = 0.1;

  constructor(config: SolPawConfig) {
    if (!config.apiEndpoint) throw new Error("SolPaw: apiEndpoint is required");
    if (!config.apiKey) throw new Error("SolPaw: apiKey is required");
    if (!config.defaultCreatorWallet)
      throw new Error("SolPaw: defaultCreatorWallet is required");

    this.config = {
      ...config,
      apiEndpoint: config.apiEndpoint.replace(/\/$/, ""),
    };
  }

  /**
   * Make an authenticated request to the SolPaw API.
   * API key is sent in the Authorization header — never in query params or body.
   */
  private async request<T>(
    method: string,
    path: string,
    body?: Record<string, unknown>,
    headers?: Record<string, string>
  ): Promise<T> {
    const url = `${this.config.apiEndpoint}${path}`;

    const response = await fetch(url, {
      method,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${this.config.apiKey}`,
        ...headers,
      },
      body: body ? JSON.stringify(body) : undefined,
      signal: AbortSignal.timeout(120000), // 2 min timeout for launches
    });

    const data = (await response.json()) as {
      success: boolean;
      data: T;
      error?: { message: string };
    };

    if (!response.ok || !data.success) {
      throw new Error(
        data.error?.message ||
          `API error: ${response.status} ${response.statusText}`
      );
    }

    return data.data;
  }

  /**
   * Get a fresh CSRF token (cached for 25 minutes).
   * Called automatically before any state-changing operation.
   */
  private async getCsrfToken(): Promise<string> {
    // Return cached token if still valid (with 5 min buffer)
    if (this.csrfToken && this.csrfExpiresAt > Date.now() + 5 * 60 * 1000) {
      return this.csrfToken;
    }

    const result = await this.request<{
      csrf_token: string;
      expires_in: number;
    }>("GET", "/agents/csrf");

    this.csrfToken = result.csrf_token;
    this.csrfExpiresAt = Date.now() + result.expires_in * 1000;

    return this.csrfToken;
  }

  /**
   * Get platform info — wallet address, launch fee, and daily limit.
   * Use this to know where to send the 0.1 SOL launch fee.
   */
  async getPlatformInfo(): Promise<PlatformInfo> {
    const result = await this.request<{
      platform_wallet: string;
      launch_fee: {
        amount_sol: number;
        amount_lamports: number;
      };
      guardrails: {
        daily_launch_limit: string;
      };
    }>("GET", "/info");

    return {
      platform_wallet: result.platform_wallet,
      launch_fee_sol: result.launch_fee.amount_sol,
      daily_limit: parseInt(result.guardrails.daily_launch_limit) || 1,
    };
  }

  /**
   * Launch a token on Pump.fun via the SolPaw API.
   *
   * IMPORTANT: Before calling this, the agent must:
   *   1. Send 0.1 SOL to the platform wallet (GosroTTvsbgc8FdqSdNtrmWxGbZp2ShH5NP5pK1yAR4K)
   *   2. Wait for transaction confirmation
   *   3. Pass the transaction signature as launch_fee_signature
   *
   * The server verifies the payment onchain before proceeding.
   * Each signature can only be used once.
   *
   * Fee: 0.1 SOL one-time per launch. No ongoing fees ever.
   */
  async launchToken(params: TokenLaunchParams): Promise<LaunchResult> {
    try {
      // Validate required fields
      if (!params.name || params.name.length < 2) {
        return { success: false, error: "Token name required (min 2 chars)" };
      }
      if (!params.symbol || params.symbol.length < 2) {
        return { success: false, error: "Token symbol required (min 2 chars)" };
      }
      if (!params.description || params.description.length < 10) {
        return {
          success: false,
          error: "Description required (min 10 chars)",
        };
      }
      if (!params.launch_fee_signature) {
        return {
          success: false,
          error:
            "launch_fee_signature is required. Send 0.1 SOL to " +
            SolPawSkill.PLATFORM_WALLET +
            " and pass the tx signature.",
        };
      }

      // Get fresh CSRF token
      const csrfToken = await this.getCsrfToken();

      // Launch via Lightning API
      const result = await this.request<{
        mint: string;
        signature: string;
        pumpfun_url: string;
        solscan_url: string;
        launch_fee: {
          amount_sol: number;
          platform_wallet: string;
          payment_signature: string;
        };
      }>("POST", "/tokens/launch", {
        name: params.name,
        symbol: params.symbol.toUpperCase(),
        description: params.description,
        image_url: params.image_url,
        creator_wallet:
          params.creator_wallet || this.config.defaultCreatorWallet,
        twitter: params.twitter,
        telegram: params.telegram,
        website: params.website,
        initial_buy_sol: params.initial_buy_sol || 0,
        slippage: params.slippage || 10,
        priority_fee: params.priority_fee || 0.0005,
        launch_fee_signature: params.launch_fee_signature,
        csrf_token: csrfToken,
      });

      // Invalidate CSRF token (it's single-use)
      this.csrfToken = null;
      this.csrfExpiresAt = 0;

      return {
        success: true,
        mint: result.mint,
        signature: result.signature,
        pumpfun_url: result.pumpfun_url,
        solscan_url: result.solscan_url,
        launch_fee: result.launch_fee,
      };
    } catch (err) {
      return {
        success: false,
        error: (err as Error).message,
      };
    }
  }

  /**
   * Get the agent's launched tokens.
   */
  async getMyTokens(
    page: number = 1,
    limit: number = 20
  ): Promise<{
    tokens: Array<{
      mint: string;
      name: string;
      symbol: string;
      created_at: string;
      pumpfun_url: string;
    }>;
    total: number;
  }> {
    return this.request("GET", `/tokens?page=${page}&limit=${limit}`);
  }

  /**
   * Get fee summary for the agent's launches.
   */
  async getFeeSummary(): Promise<{
    total_fees_sol: number;
    platform_share_sol: number;
    token_count: number;
  }> {
    return this.request("GET", "/tokens/fees/summary");
  }

  /**
   * Get public platform stats.
   */
  async getPlatformStats(): Promise<Record<string, unknown>> {
    return this.request("GET", "/tokens/stats/platform");
  }
}

// ── Default Export for OpenClaw Skill Loader ─────────────────────
export default SolPawSkill;

// ── Example Usage ───────────────────────────────────────────────
/*
import SolPawSkill from './solpaw-skill';
import { Connection, Keypair, SystemProgram, Transaction, sendAndConfirmTransaction } from '@solana/web3.js';

const solpaw = new SolPawSkill({
  apiEndpoint: 'https://api.solpaw.fun/api/v1',
  [REDACTED_SECRET],
  defaultCreatorWallet: 'YourSolanaWallet...',
});

// Step 1: Send 0.1 SOL launch fee to platform wallet
const connection = new Connection('https://api.mainnet-beta.solana.com');
const payer = Keypair.fromSecretKey(...); // your agent's keypair
const feeTx = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: payer.publicKey,
    toPubkey: new PublicKey(SolPawSkill.PLATFORM_WALLET),
    lamports: 100_000_000, // 0.1 SOL
  })
);
const feeSig = await sendAndConfirmTransaction(connection, feeTx, [payer]);

// Step 2: Launch token with the fee signature
const result = await solpaw.launchToken({
  name: 'CoolToken',
  symbol: 'COOL',
  description: 'The coolest token on Solana, launched by an AI agent',
  image_url: 'https://example.com/cool-token.png',
  twitter: 'https://x.com/cooltoken',
  launch_fee_signature: feeSig, // tx sig from step 1
  initial_buy_sol: 0.5,
});

if (result.success) {
  console.log(`Token launched: ${result.pumpfun_url}`);
  console.log(`Mint: ${result.mint}`);
  console.log(`Launch fee: 0.1 SOL (one-time, no ongoing fees)`);
} else {
  console.error(`Launch failed: ${result.error}`);
}
*/


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