Tokenized Agents
LeoYeAI/openclaw-master-skills
Build payment flows for Pump Tokenized Agents using @pump-fun/agent-payments-sdk.
A skill your agent uses when the user wants to charge users for actions.
$ npx skills add nirholas/three.ws --skill tokenized-agents -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install nirholas/three.ws tokenized-agents --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/nirholas/three.ws.git skills-src && mkdir -p .claude/skills && cp -r skills-src/pump-fun-skills/tokenized-agents .claude/skills/tokenized-agents && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "tokenized-agents" agent skill from https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agents into .claude/skills/tokenized-agents/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tokenized-agents", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agentsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add nirholas/three.ws --skill tokenized-agents -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install nirholas/three.ws tokenized-agents --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nirholas/three.ws.git skills-src && mkdir -p .agents/skills && cp -r skills-src/pump-fun-skills/tokenized-agents .agents/skills/tokenized-agents && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "tokenized-agents" agent skill from https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agents into .agents/skills/tokenized-agents/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tokenized-agents", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add nirholas/three.ws --skill tokenized-agents -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install nirholas/three.ws tokenized-agents --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nirholas/three.ws.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/pump-fun-skills/tokenized-agents .cursor/skills/tokenized-agents && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "tokenized-agents" agent skill from https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agents into .cursor/skills/tokenized-agents/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tokenized-agents", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/nirholas/three.ws.git --path pump-fun-skills/tokenized-agents--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add nirholas/three.ws --skill tokenized-agents -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install nirholas/three.ws tokenized-agents --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nirholas/three.ws.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/pump-fun-skills/tokenized-agents .gemini/skills/tokenized-agents && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "tokenized-agents" agent skill from https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agents into .gemini/skills/tokenized-agents/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tokenized-agents", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install nirholas/three.ws tokenized-agentsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add nirholas/three.ws --skill tokenized-agents -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/nirholas/three.ws.git skills-src && mkdir -p .github/skills && cp -r skills-src/pump-fun-skills/tokenized-agents .github/skills/tokenized-agents && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "tokenized-agents" agent skill from https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agents into .github/skills/tokenized-agents/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tokenized-agents", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add nirholas/three.ws --skill tokenized-agents -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install nirholas/three.ws tokenized-agents --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/nirholas/three.ws.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/pump-fun-skills/tokenized-agents .opencode/skills/tokenized-agents && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "tokenized-agents" agent skill from https://github.com/nirholas/three.ws/tree/main/pump-fun-skills/tokenized-agents into .opencode/skills/tokenized-agents/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "tokenized-agents", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
tokenized-agentsA skill your agent uses when the user wants to charge users for actions.
Tokenized Agents is an agent skill from nirholas/three.ws. Use when the user wants to charge users for actions. Use @three-ws/agent-payments, to build Solana payment transactions, verify on-chain invoice payments, or integrate Solana wallet adapters for agent payment flows.
Its SKILL.md is about 5.6k tokens, which your agent loads only when the skill is triggered. The skill folder holds 9 other files, including reference files (for example `README.md`, `SCENARIOS.md` and `WALLET_INTEGRATION.md`).
It sits in Backend & APIs, covering Forms and invoices and Smart contracts. It works with Solana and Circle USDC. The repository describes itself as: Open-source platform for 3D AI agents. Turn text or a photo into a rigged, animated GLB avatar, give it an LLM brain, memory and a wallet, and embed it anywhere with one web… The licence is Apache-2.0.
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 238ef60. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (JavaScript), which the agent can run.
Shell commands in SKILL.md call:
npmFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
rpc.solanatracker.ioapi.mainnet-beta.solana.comrpc.ankr.comAlso links to:
raw.githubusercontent.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Tokenized Agents loads about 5.6k tokens when it runs, and up to ~6.7k if it reads all its reference files. Until then it costs about 58 tokens; SKILL.md has 1,586 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
Create a `.env` (or `.env.local` for Next.js) file with the following:Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from nirholas/three.ws at commit 238ef60, republished under its Apache-2.0 licence (© nirholas). 1,586 words, ~5,553 tokens.
.claude/skills/tokenized-agents/SKILL.md (or your agent's skills folder). This skill also uses 8 other files; get the full folder from GitHub.MANDATORY — Do NOT write or modify any code until every item below is answered by the user:
You MUST ask the user for ALL unchecked items in your very first response. Do not assume defaults. Do not proceed until the user has explicitly answered each one.
amount > 0 before creating an invoice.endTime > startTime and both are valid Unix timestamps.validateInvoicePayment before delivering any service. Never trust the client alone — clients can be spoofed.buildAcceptPaymentInstructions accepts number for numeric fields, validateInvoicePayment accepts number, and getInvoiceIdPDA accepts number.computeUnitLimit defaults to 100_000) are not contradicted.@three-ws/agent-payments, not internal module paths.| Currency | Decimals | Smallest unit example |
|---|---|---|
| USDC | 6 | 1000000 = 1 USDC |
| Wrapped SOL | 9 | 1000000000 = 1 SOL |
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=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1vRPC for mainnet-beta: The default Solana public RPC (https://api.mainnet-beta.solana.com) does not support sending transactions. You MUST ask the user which RPC endpoint to use. Present these free mainnet-beta options if the user does not have their own:
https://rpc.solanatracker.io/publichttps://rpc.ankr.com/solanaDo NOT silently pick one — wait for the user to confirm before proceeding.
Read these values from process.env at runtime. Never hard-code mint addresses or RPC URLs.
npm install @three-ws/agent-payments @solana/web3.js@^1.98.0@three-ws/agent-payments depends on @solana/web3.js and @solana/spl-token. When the app also installs these packages directly, mismatched versions can cause runtime errors.
Rules:
@solana/web3.js, @solana/spl-token, or any @solana/wallet-adapter-* package, first check what versions @three-ws/agent-payments declares in its own package.json (inspect it via npm info @three-ws/agent-payments dependencies). Install the same ranges — or ranges that resolve to the same major.minor — so npm/pnpm hoists a single copy instead of two.@three-ws/agent-payments.PumpAgent is the main class. It can build payment instructions and verify invoices.
import { PumpAgent } from "@three-ws/agent-payments";
import { PublicKey } from "@solana/web3.js";
const agentMint = new PublicKey(process.env.AGENT_TOKEN_MINT_ADDRESS!);new PumpAgent(mint: PublicKey, environment?: "mainnet" | "devnet", connection?: Connection)| Parameter | Type | Default | Description |
|---|---|---|---|
mint | PublicKey | — | The tokenized agent's token mint address |
environment | "mainnet" | "devnet" | "mainnet" | Network environment |
connection | Connection (optional) | undefined | Solana 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);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.
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.
BuildAcceptPaymentParams)| Parameter | Type | Description |
|---|---|---|
user | PublicKey | The payer's wallet address |
currencyMint | PublicKey | Mint address of the payment currency (USDC, wSOL) |
amount | bigint | number | string | Price in the currency's smallest unit |
memo | bigint | number | string | Unique invoice identifier (random number) |
startTime | bigint | number | string | Unix timestamp — when the invoice becomes valid |
endTime | bigint | number | string | Unix timestamp — when the invoice expires |
tokenProgram | PublicKey (optional) | Token program for the currency (defaults to SPL Token) |
computeUnitLimit | number (optional) | Compute unit budget (default 100_000). Increase if transactions fail with compute exceeded. |
computeUnitPrice | number (optional) | Priority fee in microlamports per CU. If provided, a SetComputeUnitPrice instruction is prepended. |
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
});The returned TransactionInstruction[] always starts with compute budget instructions, followed by the payment instructions:
SetComputeUnitLimit is always prepended (default 100_000 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:
You do not need to handle SOL wrapping or compute budget yourself — buildAcceptPaymentInstructions does it for you.
amount, memo, startTime, and endTime must exactly match when verifying later.(mint, currencyMint, amount, memo, startTime, endTime) can only be paid once — the on-chain Invoice ID PDA prevents duplicate payments.memo for each invoice (e.g. Math.floor(Math.random() * 900000000000) + 100000).The Invoice ID is a PDA (PublicKey) that uniquely identifies an invoice on-chain. It is derived deterministically from the six invoice parameters. Both buildAcceptPaymentInstructions and validateInvoicePayment derive it internally, but you can also compute it yourself.
import { getInvoiceIdPDA } from "@three-ws/agent-payments";
import { PublicKey } from "@solana/web3.js";getInvoiceIdPDA returns [PublicKey, number]. The first element is the Invoice ID; the second is the PDA bump seed.
const tokenMint = new PublicKey(process.env.AGENT_TOKEN_MINT_ADDRESS!);
const currencyMint = new PublicKey(process.env.CURRENCY_MINT!);
const amount = 1000000;
const memo = 123456789;
const startTime = 1700000000;
const endTime = 1700086400;
const [invoiceId] = getInvoiceIdPDA(
tokenMint,
currencyMint,
amount,
memo,
startTime,
endTime,
);
console.log("Invoice ID:", invoiceId.toBase58());All numeric parameters (amount, memo, startTime, endTime) are plain number values. BN conversion is handled internally.
The Invoice ID is derived with program AgenTMiC2hvxGebTsgmsD4HHBa8WEcqGFf87iwRRxLo7 using these seeds:
| Seed index | Value |
|---|---|
| 0 | "invoice-id" (UTF-8 bytes) |
| 1 | tokenMint (32 bytes) |
| 2 | currencyMint (32 bytes) |
| 3 | amount (8 bytes, little-endian) |
| 4 | memo (8 bytes, little-endian) |
| 5 | startTime (8 bytes, little-endian) |
| 6 | endTime (8 bytes, little-endian) |
Because the PDA is deterministic, the same six parameters always produce the same Invoice ID. The on-chain program uses this to reject duplicate payments — once an Invoice ID PDA is created, the same combination cannot be paid again.
const [invoiceId] = getInvoiceIdPDA(
tokenMint,
currencyMint,
amount,
memo,
startTime,
endTime,
);
const accountInfo = await connection.getAccountInfo(invoiceId);
if (accountInfo !== null) {
// This invoice was already paid — generate a new memo
}false, derive the Invoice ID and inspect it on a Solana explorer to see whether the account exists.This is the complete flow for building a transaction on the server, signing it on the client, and sending it on-chain.
function generateInvoiceParams() {
const memo = Math.floor(Math.random() * 900000000000) + 100000;
const now = Math.floor(Date.now() / 1000);
const startTime = now;
const endTime = now + 86400; // valid for 24 hours
const amount = Number(process.env.PRICE_AMOUNT) || 1000000; // e.g. 1 USDC
return { amount, memo, startTime, endTime };
}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 } from "@solana/web3.js";
import { PumpAgent } from "@three-ws/agent-payments";
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(...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.
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.
Use validateInvoicePayment to confirm that a specific invoice was paid on-chain.
Derives the Invoice ID PDA from the six parameters (mint, currencyMint, amount, memo, startTime, endTime) using getInvoiceIdPDA internally. The resulting PublicKey uniquely identifies the invoice on-chain.
Queries the Pump HTTP API — sends a GET request with invoice-id (base58) and mint as query parameters. If the endpoint returns a response, it validates every field individually:
data.user === user (base58)data.tokenized_agent_mint === mint (base58)data.currency_mint === currencyMint (base58)data.amount === amount (BN equality)data.memo === memo (BN equality)data.start_time === startTime (BN equality)data.end_time === endTime (BN equality)All seven checks must pass for the method to return true.
RPC fallback — if the HTTP API is unavailable (network error or non-200 status) and a Connection was provided to the PumpAgent constructor, it falls back to scanning on-chain transaction logs. It fetches all signatures for the Invoice ID address, parses each transaction's logs for the agentAcceptPaymentEvent event, and performs the same field-by-field validation. Without a Connection, there is no fallback and the method returns false.
Returns true if a matching payment event is found by either path, false otherwise.
| Parameter | Type | Description |
|---|---|---|
user | PublicKey | The wallet that paid |
currencyMint | PublicKey | Currency used for payment |
amount | number | Amount paid (smallest unit) |
memo | number | The invoice memo |
startTime | number | Invoice start time (Unix timestamp) |
endTime | number | Invoice end time (Unix timestamp) |
Type note:
validateInvoicePaymentexpectsamount,memo,startTime, andendTimeasnumber, not strings. If you stored them as strings, parse them first:Number(memo).
import { PumpAgent } from "@three-ws/agent-payments";
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.
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;
}1. Agent decides on price → generates unique memo(number) → 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: with the exactly same parameters used for buildAcceptPaymentInstructions server validateInvoicePayment({...}) → returns true/false (ALWAYS verify server-side)
8. Agent delivers the service (or asks user to retry)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.
© nirholas, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 8 other files (references) in pump-fun-skills/tokenized-agents of nirholas/three.ws.
Open the folder on GitHubat commit 238ef60
Tokenized Agents next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Tokenized Agents this skillnirholas/three.ws | 226 | — | ~5.6k | Automated safety check: Notes | Apache-2.0 | |
| Tokenized AgentsLeoYeAI/openclaw-master-skills | 2.2k | — | ~4.6k | Automated safety check: Notes | MIT | |
| Alchemy Agentic Gatewaymoonpay/skills | 113 | — | ~2.1k | Automated safety check: Notes | MIT | |
| Swap Tokenscirclefin/skills | 155 | — | ~4.6k | Automated safety check: Notes | Apache-2.0 | |
| Unify Balancecirclefin/skills | 155 | — | ~4.7k | Automated safety check: Notes | Apache-2.0 | |
| Use Usdccirclefin/skills | 155 | — | ~2.4k | Automated safety check: Notes | Apache-2.0 |
LeoYeAI/openclaw-master-skills
Build payment flows for Pump Tokenized Agents using @pump-fun/agent-payments-sdk.
moonpay/skills
A skill your agent uses when accessing Alchemy APIs for RPC calls, token balances, NFT metadata, asset transfers, transaction simulation, or Alchemy-specific features.
circlefin/skills
Build browser or server token swaps with Circle App Kit or standalone Swap Kit.
circlefin/skills
Build browser or server unified cross-chain USDC balances with Circle App Kit or standalone Unified Balance Kit.
circlefin/skills
USDC is Circle's stablecoin deployed across multiple blockchain ecosystems including EVM chains (Ethereum, Base, Arbitrum, Polygon, Arc) and Solana.
circlefin/skills
Build non-custodial wallets where end users retain control of their private keys via Circle's user-controlled wallets SDK.
nirholas/three.ws
Add the Shaders WebGPU mouse effect used for the Tidal Commons hero: a white twinkling halftone cursor trail driven by ChromaFlow, masked through a DotGrid, finished with chromatic ripples and film…
nirholas/three.ws
Package a finished local project into an intentional GitHub repository, create a strong README and visual preview, push it safely, configure a public GitHub Pages URL when the project is compatible…
nirholas/three.ws
Audit a website or digital experience against its supplied source references for originality and plagiarism risk.
nirholas/three.ws
Turn a completed daily UI inspiration capture into exactly five original landing-page builds, one per separate Codex task, using Sites.
nirholas/three.ws
Write, rewrite, review, or continuously refine X/Twitter posts in Meng To's current voice using his deduplicated authored-post corpus, personal and product context, shared resources, and Content…
nirholas/three.ws
Create polished 60 fps 4:3 4K browser screen-recording style videos from Codex in-app browser captures, with browser-only crop, natural macOS cursor styling, deliberate click choreography…
Works with
Categories
A skill your agent uses when the user wants to charge users for actions. ws. Use when the user wants to charge users for actions.
Tokenized Agents fits situations like: the user wants to charge users for actions; tasks that involve Forms and invoices; tasks that involve Smart contracts.
Run `npx skills add nirholas/three.ws --skill tokenized-agents -a claude-code`. Or copy the skill folder (pump-fun-skills/tokenized-agents in nirholas/three.ws) into .claude/skills/tokenized-agents in your project. Claude Code loads it when a task matches its description.
Run `npx skills add nirholas/three.ws --skill tokenized-agents -a codex`. Or copy the skill folder (pump-fun-skills/tokenized-agents in nirholas/three.ws) into .agents/skills/tokenized-agents in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add nirholas/three.ws --skill tokenized-agents -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/tokenized-agents, .gemini/skills/tokenized-agents, .github/skills/tokenized-agents and .opencode/skills/tokenized-agents in your project.
Going by SKILL.md and its folder, Tokenized Agents needs JavaScript for the scripts in its folder and the command-line tools its instructions call (npm). Our summary lists: Node.js.
SKILL.md names 4 domains. In commands or code: rpc.solanatracker.io, api.mainnet-beta.solana.com and rpc.ankr.com; the agent is likely to contact these when it follows the instructions. As links in the text: raw.githubusercontent.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Tokenized Agents is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.6k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.1k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Tokenized Agents: Tokenized Agents (LeoYeAI/openclaw-master-skills, 2.2k stars), Alchemy Agentic Gateway (moonpay/skills, 113 stars), Swap Tokens (circlefin/skills, 155 stars) and Unify Balance (circlefin/skills, 155 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
nirholas (a GitHub user) maintains it in nirholas/three.ws, which has 226 GitHub stars. The repository holds 165 skills in this directory. The repository was last updated on October 7, 2026.
Source: nirholas/three.ws on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.