opensea/opensea-tool-sdk/SKILL.md
Build, register, and gate AI-callable tool endpoints using the OpenSea Tool Registry (ERC-8257) on Base. Scaffold HTTPS tools with JSON Schema interfaces, register them onchain, gate access via NFT ownership or x402 pay-per-call (USDC), and call gated tools. For querying OpenSea marketplace data use opensea-api instead.
npx skillsauth add bankrbot/openclaw-skills opensea-tool-sdkInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build, register, and gate AI-callable tool endpoints using the OpenSea Tool Registry (ERC-8257) on Base.
scope_in)Use opensea-tool-sdk when you need to:
.well-known manifest) for Vercel, Cloudflare, or ExpressauthenticatedFetch), 402 payments (paidFetch), or both (paidAuthenticatedFetch)scope_out, handoff)| Need | Use instead |
|---|---|
| Query NFT/token data, search, collection stats | opensea-api |
| Buy/sell NFTs | opensea-marketplace |
| Swap ERC20 tokens | opensea-swaps |
| Set up wallet signing providers | opensea-wallet |
This SDK is for tool providers and consumers. To query OpenSea marketplace data (floor prices, listings, trades), use the opensea-api skill instead.
| Term | Meaning |
|------|---------|
| Tool | An HTTPS endpoint with a JSON Schema interface, discoverable via /.well-known/ai-tool/<slug>.json |
| Manifest | JCS-canonicalized JSON describing the tool's name, endpoint, inputs, outputs, pricing, and access policy |
| ToolRegistry | Onchain contract (Base) where tools are registered with a manifest hash and optional access predicate |
| Access Predicate | An IAccessPredicate contract that gates who can invoke a tool (NFT ownership, subscriptions, composites) |
| x402 | HTTP 402-based pay-per-call protocol (caller signs a USDC TransferWithAuthorization; server settles after execution) |
| SIWE | Sign-In with Ethereum (EIP-4361), used to authenticate callers for predicate-gated tools |
| Facilitator | Third-party service that verifies and settles x402 payments (PayAI or Coinbase CDP) |
| Contract | Address |
|----------|---------|
| ToolRegistry (v0.1) | 0x7291BbFbC368C2D478eCe1eA30de31F612a34856 |
| ERC721OwnerPredicate (v0.2) | 0xd1F703D0B90BB7106fAebBfbcAdD2B07BDc4c769 |
| ERC1155OwnerPredicate (v0.2) | 0xc179b9d4D9B7ffe0CdA608134729f72003380A7e |
npx @opensea/tool-sdk init --runtime vercel # or: cloudflare, express
This generates:
src/manifest.ts: tool manifest definitionsrc/handler.ts: request handler with input/output schemasapi/index.ts: framework adapter entry pointpublic/llms.txt: agent-readable discovery pageapi/well-known/[slug].ts: serves the manifest at /.well-known/ai-tool/<slug>.jsonimport { defineManifest } from "@opensea/tool-sdk"
export const manifest = defineManifest({
name: "My Tool",
description: "What this tool does",
endpoint: "https://my-tool.example.com/api",
creatorAddress: "0xYOUR_WALLET_ADDRESS",
inputs: {
type: "object",
properties: {
query: { type: "string", description: "Search query" },
},
required: ["query"],
},
outputs: {
type: "object",
properties: {
result: { type: "string" },
},
},
// Optional: add pricing for x402 paywall (see references/x402.md)
// pricing: paywall.pricing,
// Optional: add access requirements (see references/predicate-gating.md)
// access: { logic: "OR", requirements: [...] },
})
import { createToolHandler } from "@opensea/tool-sdk"
import { z } from "zod/v4"
import { manifest } from "./manifest.js"
const InputSchema = z.object({ query: z.string() })
const OutputSchema = z.object({ result: z.string() })
export const toolHandler = createToolHandler({
manifest,
inputSchema: InputSchema,
outputSchema: OutputSchema,
// gates: [], // Add gates here (see references/x402.md and references/predicate-gating.md)
handler: async (input) => {
return { result: `Processed: ${input.query}` }
},
})
Vercel:
import { toVercelHandler } from "@opensea/tool-sdk"
import { toolHandler } from "../src/handler.js"
export default toVercelHandler(toolHandler)
Express:
import { toExpressHandler } from "@opensea/tool-sdk"
import { toolHandler } from "./handler.js"
app.post("/api", toExpressHandler(toolHandler))
Cloudflare Workers:
import { toolHandler } from "./handler.js"
export default { fetch: toolHandler }
# Set up wallet
export PRIVATE_KEY=0x...
export RPC_URL=https://mainnet.base.org
# Register (open access, no predicate)
npx @opensea/tool-sdk register \
--metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \
--network base
# Register with NFT gate (ERC-721 collection)
npx @opensea/tool-sdk register \
--metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \
--network base \
--nft-gate 0xCOLLECTION_ADDRESS
# Register with a custom access predicate
npx @opensea/tool-sdk register \
--metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \
--network base \
--access-predicate 0xPREDICATE_ADDRESS
# Dry run (no transaction)
npx @opensea/tool-sdk register --metadata ... --network base --dry-run
The CLI:
--metadata URLmanifest.creatorAddress matches your walletToolRegistry.registerTool(metadataURI, manifestHash, accessPredicate)toolId from the ToolRegistered eventimport { ToolRegistryClient, computeManifestHash } from "@opensea/tool-sdk"
import { createWalletFromEnv, walletAdapterToClient } from "@opensea/tool-sdk"
import { base } from "viem/chains"
const adapter = createWalletFromEnv()
const walletClient = await walletAdapterToClient(adapter, base)
const registry = new ToolRegistryClient({
chain: base,
rpcUrl: "https://mainnet.base.org",
walletClient,
})
const { toolId, txHash } = await registry.registerTool({
metadataURI: "https://my-tool.example.com/.well-known/ai-tool/my-tool.json",
manifest, // your ToolManifest object
accessPredicate: "0x0000...0000", // address(0) for open access
})
console.log(`Registered tool ${toolId} in tx ${txHash}`)
Tools can be gated three ways:
| Gate | Mechanism | Reference |
|------|-----------|-----------|
| x402 paywall | Pay-per-call (USDC, EIP-3009) | references/x402.md |
| Predicate gate | Onchain check (NFT, subscription, composite) | references/predicate-gating.md |
| Combined | SIWE auth and payment (predicate first, then x402) | references/predicate-gating.md |
For deployed predicate addresses, requirement encodings, and SDK helpers like describeToolAccess / decodeRequirement, see references/known-predicates.md.
The SDK supports multiple wallet providers via @opensea/wallet-adapters. Set environment variables and the SDK auto-detects the provider. See the opensea-wallet skill for the full provider table, env vars, setup walkthroughs, and signing-policy configuration.
import { createWalletFromEnv } from "@opensea/tool-sdk"
const adapter = createWalletFromEnv()
const address = await adapter.getAddress()
For Bankr (external signer):
import { createBankrAccount } from "@opensea/tool-sdk"
const account = await createBankrAccount("your-bankr-api-key")
// Use with authenticatedFetch or paidAuthenticatedFetch
| Code | Meaning | Action |
|------|---------|--------|
| 200 | Success | Parse the JSON body per the manifest's outputs schema |
| 400 | Invalid input | Fix request body to match the manifest's inputs schema |
| 401 | Missing/invalid SIWE auth | Sign a SIWE message and include Authorization: SIWE <token> |
| 402 | Payment required | Read body.accepts[0] for payment requirements, sign and retry with X-Payment |
| 403 | Access denied | Inspect body.predicate to discover what's needed; acquire the required token/subscription |
| 405 | Method not allowed | Use POST |
| 500 | Internal tool error | Retry or contact the tool creator |
| 502 | Predicate/facilitator error | The upstream predicate or payment facilitator misbehaved; retry later |
| Command | Purpose |
|---------|---------|
| init | Scaffold a new tool project |
| validate | Validate a manifest file |
| hash | Compute the JCS keccak256 hash of a manifest |
| export | Export the manifest as JSON |
| register | Register a tool onchain |
| update-metadata | Update a tool's metadata URI and manifest hash onchain |
| inspect | Look up a tool's onchain config by ID |
| verify | Verify a manifest against its onchain hash |
| deploy | Deploy a tool to Vercel |
| auth | Call a predicate-gated tool (SIWE) |
| pay | Call an x402-paid tool (USDC) |
| smoke | Auto-detect gate type and call |
| dry-run-gate | Simulate an x402 gate check locally |
| dry-run-predicate-gate | Simulate a predicate gate check locally |
All CLI commands accept --wallet-provider privy|turnkey|fireblocks|bankr|private-key or auto-detect from env vars.
# 1. Scaffold
npx @opensea/tool-sdk init --runtime vercel
# 2. Edit src/manifest.ts and src/handler.ts with your logic
# 3. Deploy
npx @opensea/tool-sdk deploy
# 4. Register (open access)
PRIVATE_KEY=0x... npx @opensea/tool-sdk register \
--metadata https://my-tool.vercel.app/.well-known/ai-tool/my-tool.json \
--network base
# 5. Call
curl -X POST https://my-tool.vercel.app/api \
-H "Content-Type: application/json" \
-d '{"query": "hello"}'
# Server: add paywall gate (see references/x402.md)
# Call via CLI:
PRIVATE_KEY=0x... npx @opensea/tool-sdk pay \
https://my-tool.vercel.app/api \
--body '{"query": "hello"}'
# Register with NFT gate
PRIVATE_KEY=0x... npx @opensea/tool-sdk register \
--metadata https://my-tool.vercel.app/.well-known/ai-tool/my-tool.json \
--network base \
--nft-gate 0xCOLLECTION
# Server: add predicateGate (see references/predicate-gating.md)
# Call via CLI:
PRIVATE_KEY=0x... RPC_URL=https://mainnet.base.org \
npx @opensea/tool-sdk auth \
https://my-tool.vercel.app/api \
--body '{"query": "hello"}'
# Server: add both predicateGate and paywall.gate (see references/predicate-gating.md)
# Call via CLI:
PRIVATE_KEY=0x... RPC_URL=https://mainnet.base.org \
npx @opensea/tool-sdk smoke \
--endpoint https://my-tool.vercel.app/api \
--expect 200
references/x402.md: pay-per-call protocol, server-side paywall, paidFetchreferences/predicate-gating.md: SIWE-based access control, combined gatesreferences/known-predicates.md: deployed predicate contracts and SDK helpersdata-ai
Claim and withdraw payments from Metr (metrpay.com) merchant account.
development
AI-powered crypto trading agent, wallet API, and LLM gateway via natural language. Use when the user wants to trade crypto, trade tokenized stocks and ETFs (spot or leveraged), check portfolio balances (with PnL and NFTs), view token prices, search tokens, transfer crypto, manage NFTs, use leverage (Hyperliquid or Avantis), bet on Polymarket, deploy tokens, set up automated trading, sign and submit raw transactions, call or deploy x402 paid API endpoints, browse the web, or access LLM models through the Bankr LLM gateway funded by your Bankr wallet. Supports Base, Ethereum, Polygon, Solana, Unichain, World Chain, Arbitrum, BNB Chain, and Robinhood Chain.
testing
Urizen — an AI equity-research desk + the first autonomous fund on Robinhood Chain (4663), as an agent skill. Real charts & technicals for any tokenized US stock, SEC fundamentals + filings + insider activity, Wall Street analyst consensus, financial news, the macro calendar (Fed/CPI/jobs), live prediction-market odds, and on-chain price — plus the fund's live strategies, book, execution tape, and one-token exposure via $URI. Public, key-less, CORS-open REST on chain 4663. Triggers on: "urizen", "research a stock", "tokenized stock", "SEC fundamentals", "analyst rating", "economic calendar", "prediction market odds", "copy trade the fund", "urizen book", "buy $URI".
development
List tokens on CoinHero via consignment deals on Base — deposit ERC-20 inventory, earn USDC when the protocol buys your token for CoinHero card games. Use when a wallet-enabled agent wants to consign a Base ERC-20 token, check deal performance, or withdraw earnings. Requires a CoinHero dashboard API key and a wallet (EOA) on Base mainnet with at least $50 USD worth of the token to deposit.