tokenized-agents

Build payment flows for Pump Tokenized Agents using @pump-fun/agent-payments-sdk. Use when accepting payments, building accept-payment transactions, integrating Solana wallets, or verifying that a user has paid an invoice on-chain.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "tokenized-agents" with this command: npx skills add pump-fun/pump-fun-tokenized-agents

Pump Tokenized Agent Payments

Pump Tokenized Agents are AI agents whose revenue is linked to a token on pump.fun. The @pump-fun/agent-payments-sdk lets you build payment transactions and verify invoices on Solana.

Before You Start — Gather Required Information

Before writing any code, ask the user for the following if not already provided:

  1. Agent token mint address — the token mint created when the agent coin was launched on pump.fun.
  2. Payment currency — USDC or SOL (determines the currencyMint).
  3. Price / amount — how much to charge per request, in the currency's smallest unit.
  4. Service to deliver — what the agent should do after payment is confirmed (generate content, access an API, etc.).
  5. Solana RPC — which solana rpc to use, we have some defaults if they don't provide.

Do not assume these values. If any are missing, ask the user before proceeding.

Safety Rules

  • NEVER log, print, or return private keys or secret key material.
  • NEVER sign transactions on behalf of a user — you build the instruction, the user signs.
  • Always validate that amount > 0 before creating an invoice.
  • Always ensure endTime > startTime and both are valid Unix timestamps.
  • Use the correct decimal precision for the currency (6 decimals for USDC, 9 for SOL).
  • Always verify payments on the server using validateInvoicePayment before delivering any service. Never trust the client alone — clients can be spoofed.

Supported Currencies

CurrencyDecimalsSmallest unit example
USDC61000000 = 1 USDC
Wrapped SOL91000000000 = 1 SOL

Environment Variables

Create a .env (or .env.local for Next.js) file with the following:

# Solana RPC — server-side (used to build transactions and verify payments)
SOLANA_RPC_URL=https://rpc.solanatracker.io/public

# Solana RPC — client-side (used by wallet adapter in the browser)
NEXT_PUBLIC_SOLANA_RPC_URL=https://rpc.solanatracker.io/public

# The token mint address of your tokenized agent on pump.fun
AGENT_TOKEN_MINT_ADDRESS=<your-agent-mint-address>

# Payment currency mint
# USDC: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
# SOL (wrapped): So11111111111111111111111111111111111111112
CURRENCY_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v

RPC for mainnet-beta: The default Solana public RPC (https://api.mainnet-beta.solana.com) does not support sending transactions. Ask the user for an RPC provider, If the user has not provided their own RPC URL, use one of these free mainnet-beta endpoints that support sendTransaction:

  • Solana Trackerhttps://rpc.solanatracker.io/public
  • Ankrhttps://rpc.ankr.com/solana

Read these values from process.env at runtime. Never hard-code mint addresses or RPC URLs.

Install

npm install @pump-fun/agent-payments-sdk@3.0.0 @solana/web3.js@^1.98.0

Dependency Compatibility — IMPORTANT

@pump-fun/agent-payments-sdk depends on @solana/web3.js and @solana/spl-token. When the app also installs these packages directly, mismatched versions can cause runtime errors.

Rules:

  1. Before installing @solana/web3.js, @solana/spl-token, or any @solana/wallet-adapter-* package, first check what versions @pump-fun/agent-payments-sdk declares in its own package.json (inspect it via npm info @pump-fun/agent-payments-sdk dependencies). Install the same ranges — or ranges that resolve to the same major.minor — so npm/pnpm hoists a single copy instead of two.
  2. Never blindly install "latest" for these shared packages. Always prefer the version that is most compatible with the latest @pump-fun/agent-payments-sdk.
  3. If the project already has these packages at different versions, align them to match the SDK and re-install.

SDK Setup

PumpAgent is the main class. It can build payment instructions and verify invoices.

import { PumpAgent } from "@pump-fun/agent-payments-sdk";
import { PublicKey } from "@solana/web3.js";

const agentMint = new PublicKey(process.env.AGENT_TOKEN_MINT_ADDRESS!);

Constructor

new PumpAgent(mint: PublicKey, environment?: "mainnet" | "devnet", connection?: Connection)
ParameterTypeDefaultDescription
mintPublicKeyThe tokenized agent's token mint address
environment"mainnet" | "devnet""mainnet"Network environment
connectionConnection (optional)undefinedSolana RPC connection (enables RPC fallback for verification)

Without connection — enough for building instructions and HTTP-based payment verification:

const agent = new PumpAgent(agentMint);

With connection — also enables RPC-based verification fallback and balance queries:

import { Connection } from "@solana/web3.js";

const connection = new Connection(process.env.SOLANA_RPC_URL!);
const agent = new PumpAgent(agentMint, "mainnet", connection);

Wallet Integration (Frontend)

Install @solana/wallet-adapter-react, @solana/wallet-adapter-react-ui, and @solana/wallet-adapter-wallets. Use useWallet() for publicKey and signTransaction, and useConnection() for the active RPC connection. MUST See https://raw.githubusercontent.com/pump-fun/pump-fun-skills/refs/heads/main/tokenized-agents/references/WALLET_INTEGRATION.md for the full WalletProvider setup, layout wrapping, and hook usage.

Building Payment Instructions

Use buildAcceptPaymentInstructions to get all the instructions needed for a payment. This is the recommended method — it automatically derives the user's token account and handles native SOL wrapping/unwrapping.

Parameters (BuildAcceptPaymentParams)

ParameterTypeDescription
userPublicKeyThe payer's wallet address
currencyMintPublicKeyMint address of the payment currency (USDC, wSOL)
amountbigint | number | stringPrice in the currency's smallest unit
memobigint | number | stringUnique invoice identifier (random number)
startTimebigint | number | stringUnix timestamp — when the invoice becomes valid
endTimebigint | number | stringUnix timestamp — when the invoice expires
tokenProgramPublicKey (optional)Token program for the currency (defaults to SPL Token)
computeUnitLimitnumber (optional)Compute unit budget (default 100_000). Increase if transactions fail with compute exceeded.
computeUnitPricenumber (optional)Priority fee in microlamports per CU. If provided, a SetComputeUnitPrice instruction is prepended.

Example

const ixs = await agent.buildAcceptPaymentInstructions({
  user: userPublicKey,
  currencyMint,
  amount: "1000000", // 1 USDC
  memo: "123456789", // unique invoice identifier
  startTime: "1700000000", // valid from
  endTime: "1700086400", // expires at
});

What It Returns

The returned TransactionInstruction[] always starts with compute budget instructions, followed by the payment instructions:

  • SetComputeUnitLimit is always prepended (default 92_849 CU). Override via computeUnitLimit if your transactions fail with "compute exceeded".
  • SetComputeUnitPrice is prepended only when computeUnitPrice is provided. Use this to set a priority fee for faster landing during congestion.

After the compute budget prefix:

  • For SPL tokens (USDC): The accept-payment instruction.
  • For native SOL: Instructions that handle wrapping/unwrapping automatically:
    1. Create the user's wrapped SOL token account (idempotent)
    2. Transfer SOL lamports into that token account
    3. Sync the native balance
    4. The accept-payment instruction
    5. Close the wrapped SOL account (returns rent back to user)

You do not need to handle SOL wrapping or compute budget yourself — buildAcceptPaymentInstructions does it for you.

Important

  • The amount, memo, startTime, and endTime must exactly match when verifying later.
  • Each unique combination of (mint, currencyMint, amount, memo, startTime, endTime) can only be paid once — the on-chain Invoice ID PDA prevents duplicate payments.
  • Generate a unique memo for each invoice (e.g. Math.floor(Math.random() * 900000000000) + 100000).

Full Transaction Flow — Server to Client

This is the complete flow for building a transaction on the server, signing it on the client, and sending it on-chain.

Step 1: Generate Invoice Parameters (Server)

function generateInvoiceParams() {
  const memo = String(Math.floor(Math.random() * 900000000000) + 100000);
  const now = Math.floor(Date.now() / 1000);
  const startTime = String(now);
  const endTime = String(now + 86400); // valid for 24 hours
  const amount = process.env.PRICE_AMOUNT || "1000000"; // e.g. 1 USDC

  return { amount, memo, startTime, endTime };
}

Step 2: Build Transaction and Serialize as Base64 (Server)

Build the payment instructions, assemble them into a full Transaction with a recent blockhash and fee payer, then serialize the unsigned transaction as a base64 string for the client.

import {
  Connection,
  PublicKey,
  Transaction,
  ComputeBudgetProgram,
} from "@solana/web3.js";
import { PumpAgent } from "@pump-fun/agent-payments-sdk";

async function buildPaymentTransaction(params: {
  userWallet: string;
  amount: string;
  memo: string;
  startTime: string;
  endTime: string;
}) {
  const connection = new Connection(process.env.SOLANA_RPC_URL!);
  const agentMint = new PublicKey(process.env.AGENT_TOKEN_MINT_ADDRESS!);
  const currencyMint = new PublicKey(process.env.CURRENCY_MINT!);

  const agent = new PumpAgent(agentMint, "mainnet", connection);
  const userPublicKey = new PublicKey(params.userWallet);

  const instructions = await agent.buildAcceptPaymentInstructions({
    user: userPublicKey,
    currencyMint,
    amount: params.amount,
    memo: params.memo,
    startTime: params.startTime,
    endTime: params.endTime,
  });

  const { blockhash } = await connection.getLatestBlockhash("confirmed");

  const tx = new Transaction();
  tx.recentBlockhash = blockhash;
  tx.feePayer = userPublicKey;
  tx.add(
    ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 100_000 }),
    ...instructions,
  );

  const serializedTx = tx
    .serialize({ requireAllSignatures: false })
    .toString("base64");

  return { transaction: serializedTx };
}

Return the base64 transaction string (and the invoice params like memo, startTime, endTime) to the client as JSON.

Step 3: Deserialize, Sign, and Send the Transaction (Client)

Deserialize the base64 transaction from the server, sign it with signTransaction from the wallet adapter, then send and confirm it. Call useWallet() and useConnection() only at the top level of your component; pass signTransaction and connection into the async helper so the async logic does not call hooks.

Async helper (e.g. in a utils file or alongside your component):

import { Connection, Transaction } from "@solana/web3.js";

async function signAndSendPayment(
  txBase64: string,
  signTransaction: (tx: Transaction) => Promise<Transaction>,
  connection: Connection,
): Promise<string> {
  if (!signTransaction) {
    throw new Error("Wallet does not support signing");
  }

  const tx = Transaction.from(Buffer.from(txBase64, "base64"));
  const signedTx = await signTransaction(tx);

  const signature = await connection.sendRawTransaction(signedTx.serialize(), {
    skipPreflight: false,
    preflightCommitment: "confirmed",
  });

  const latestBlockhash = await connection.getLatestBlockhash("confirmed");
  await connection.confirmTransaction(
    { signature, ...latestBlockhash },
    "confirmed",
  );

  return signature;
}

Component usage — call the hooks at the top level, then pass them into the helper (e.g. from a payment button handler):

import { useWallet, useConnection } from "@solana/wallet-adapter-react";

function PaymentButton({ txBase64 }: { txBase64: string }) {
  const { signTransaction } = useWallet();
  const { connection } = useConnection();

  const handlePay = async () => {
    if (!signTransaction) return;
    await signAndSendPayment(txBase64, signTransaction, connection);
  };

  return <button onClick={handlePay}>Pay</button>;
}

The wallet prompts the user to approve. After signing, the serialized transaction is submitted via sendRawTransaction and you wait for on-chain confirmation.

Verify Payment

Use validateInvoicePayment to confirm that a specific invoice was paid on-chain.

How It Works

  1. Derives the Invoice ID PDA from (mint, currencyMint, amount, memo, startTime, endTime).
  2. Queries the Pump HTTP API to check if the payment event exists.
  3. If the HTTP API is unavailable and a Connection was provided, falls back to scanning on-chain transaction logs via RPC.
  4. Returns true if a matching payment event is found, false otherwise.

Parameters

ParameterTypeDescription
userPublicKeyThe wallet that paid
currencyMintPublicKeyCurrency used for payment
amountnumberAmount paid (smallest unit)
memonumberThe invoice memo
startTimenumberInvoice start time (Unix timestamp)
endTimenumberInvoice end time (Unix timestamp)

Simple Backend Verification

import { PumpAgent } from "@pump-fun/agent-payments-sdk";
import { PublicKey } from "@solana/web3.js";

const agentMint = new PublicKey(process.env.AGENT_TOKEN_MINT_ADDRESS!);
const agent = new PumpAgent(agentMint);

const paid = await agent.validateInvoicePayment({
  user: new PublicKey(userWalletAddress),
  currencyMint: new PublicKey(process.env.CURRENCY_MINT!),
  amount: 1000000,
  memo: 123456789,
  startTime: 1700000000,
  endTime: 1700086400,
});

if (paid) {
  // Payment confirmed — deliver the service
} else {
  // Payment not found
}

No Connection is needed for basic verification — it uses the HTTP API by default.

Verification with Retries

Transactions may take a few seconds to confirm. Use a retry loop for reliability:

async function verifyPayment(params: {
  user: string;
  currencyMint: string;
  amount: number;
  memo: number;
  startTime: number;
  endTime: number;
}): Promise<boolean> {
  const agentMint = new PublicKey(process.env.AGENT_TOKEN_MINT_ADDRESS!);
  const agent = new PumpAgent(agentMint);

  const invoiceParams = {
    user: new PublicKey(params.user),
    currencyMint: new PublicKey(params.currencyMint),
    amount: params.amount,
    memo: params.memo,
    startTime: params.startTime,
    endTime: params.endTime,
  };

  for (let attempt = 0; attempt < 10; attempt++) {
    const verified = await agent.validateInvoicePayment(invoiceParams);
    if (verified) return true;
    await new Promise((r) => setTimeout(r, 2000));
  }

  return false;
}

End-to-End Flow

1. Agent decides on price → generates unique memo → sets time window
       ↓
2. Server: buildAcceptPaymentInstructions(...) → returns TransactionInstruction[]
       ↓
3. Server: builds full Transaction (blockhash + feePayer + instructions) → serializes as base64
       ↓
4. Client: deserializes base64 → Transaction.from(Buffer.from(txBase64, "base64"))
       ↓
5. Client: signTransaction(tx) — wallet prompts user to approve
       ↓
6. Client: connection.sendRawTransaction(signedTx.serialize()) → connection.confirmTransaction(signature)
       ↓
7. Server: validateInvoicePayment(...) → returns true/false (ALWAYS verify server-side)
       ↓
8. Agent delivers the service (or asks user to retry)

Scenario Tests & Troubleshooting

See https://raw.githubusercontent.com/pump-fun/pump-fun-skills/refs/heads/main/tokenized-agents/references/SCENARIOS.md for detailed test scenarios (happy path, duplicate rejection, expired invoices, etc.) and a troubleshooting table for common errors and for wallet Integration must follow https://raw.githubusercontent.com/pump-fun/pump-fun-skills/refs/heads/main/tokenized-agents/references/WALLET_INTEGRATION.md.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

Fast.io

Workspaces for agentic teams. Complete agent guide with all 19 consolidated tools using action-based routing — parameters, workflows, ID formats, and constra...

Registry SourceRecently Updated
3.6K1dbalve
Automation

Tozil

Track every AI dollar your agent spends. Per-model cost breakdown, daily budgets, and alerts.

Registry SourceRecently Updated
Automation

ComfyUI Controller Pro

支持批量生成10-100个修仙视频和图片,集成LTX2多版本模型与自动化浏览器及工作流管理功能。

Registry SourceRecently Updated
Automation

Baidu Yijian Vision

百度一见专业级视觉 AI Agent:支持图片/视频/及实时视频流分析。相比通用基模,在维持 95%+ 专业精度的同时,推理成本降低 50% 以上,是处理视觉巡检与监控分析任务的首选工具。主打 安全管理、SOP合规、工业质检、商业运营与物料盘点。覆盖:作业 SOP 合规与关键步骤完整性校验;工业质检与表面缺陷精密...

Registry SourceRecently Updated