Que fait OpenSea Tool SDK ?
Créez, enregistrez et contrôlez l'accès à des endpoints d'outils appelables par IA en utilisant le registre d'outils OpenSea (ERC-8257) sur Base.
Quand utiliser cette compétence (scope_in)
Utilisez opensea-tool-sdk lorsque vous avez besoin de :
- Échafauder un endpoint d'outil appelable par IA (HTTPS, JSON Schema, manifeste
.well-known) pour Vercel, Cloudflare ou Express - Enregistrer un outil sur la blockchain sur le ToolRegistry de Base afin que d'autres agents puissent le découvrir
- Contrôler l'accès via x402 paiement à l'appel (USDC) ou des prédicats (propriété ERC-721/ERC-1155, abonnements, contrôle par traits, solde ERC-20, composites)
- Appeler un outil contrôlé ou payant : paiements 402 (
paidFetch), authentification par prédicat (eip3009AuthenticatedFetch), ou les deux (paidAuthenticatedFetch) - Rechercher et découvrir les outils enregistrés via l'API REST d'OpenSea
Quand NE PAS utiliser cette compétence (scope_out, transfert)
| Besoin | Utilisez plutôt |
|---|---|
| Interroger les données NFT/token, rechercher, statistiques de collection | opensea-api |
| Acheter/vendre des NFT | opensea-marketplace |
| Échanger des tokens ERC20 | opensea-swaps |
| Configurer des fournisseurs de signature de portefeuille | opensea-wallet |
Ce SDK est destiné aux fournisseurs et consommateurs d'outils. Pour interroger les données de la place de marché OpenSea (prix planchers, annonces, transactions), utilisez plutôt la compétence opensea-api.
Concepts
| Terme | Signification |
|---|---|
| Outil | Un seul endpoint d'API REST avec une interface JSON Schema, découvrable via /.well-known/ai-tool/<slug>.json. Chaque outil doit effectuer une opération ciblée. |
| Manifeste | JSON canonisé JCS décrivant le nom, l'endpoint, les entrées, les sorties, le prix et la politique d'accès de l'outil |
| ToolRegistry | Contrat on-chain (Base) où les outils sont enregistrés avec un hash de manifeste et un prédicat d'accès optionnel |
| Prédicat d'accès | Un contrat IAccessPredicate qui contrôle qui peut invoquer un outil (propriété NFT, abonnements, contrôle par traits, solde ERC-20, composites) |
| x402 | Protocole de paiement à l'appel basé sur HTTP 402 (l'appelant signe une TransferWithAuthorization USDC ; le serveur règle après exécution) |
| Authentification EIP-3009 | Signature TransferWithAuthorization USDC de valeur nulle utilisée pour authentifier les appelants pour les outils contrôlés par prédicat |
| Facilitateur | Service tiers qui vérifie et règle les paiements x402 (PayAI ou Coinbase CDP) |
Contraintes importantes
Un outil = un endpoint. Chaque enregistrement d'outil représente un seul endpoint d'API REST avec un objectif et une intention uniques. L'URL de l'endpoint dans votre manifeste doit pointer vers une route API spécifique qui effectue une opération bien définie (par exemple, POST /api/price-check ou POST /api/translate), et non une page HTML générique, un site de documentation ou une URL multi-usages. Considérez chaque outil enregistré de la même manière que vous considérez un endpoint d'API REST individuel. Il doit accepter une entrée spécifique, effectuer une action spécifique et retourner une sortie spécifique.
Liaison d'origine : le manifeste et l'endpoint doivent partager exactement la même origine. Votre manifeste .well-known/ai-tool/<slug>.json et l'endpoint d'invocation de votre outil doivent être servis depuis exactement la même origine (schéma, hôte et port identiques selon la RFC 6454). Les sous-domaines ne comptent pas comme la même origine. example.com et api.example.com sont des origines différentes. Ceci est appliqué au moment de l'enregistrement. Si l'origine du manifeste et l'origine de l'endpoint ne correspondent pas exactement, l'outil sera rejeté et marqué comme désenregistré.
- Valide : manifeste à
https://my-tool.example.com/.well-known/ai-tool/my-tool.json, endpoint àhttps://my-tool.example.com/api/my-tool - Invalide : manifeste à
https://example.com/.well-known/ai-tool/my-tool.json, endpoint àhttps://api.example.com/api/my-tool
Si vous avez besoin que votre API soit sur un sous-domaine, servez le manifeste depuis ce même sous-domaine (par exemple, les deux sur api.example.com).
Contrats déployés (Ethereum mainnet, Base, Shape, Abstract, Monad, Robinhood Chain)
Déploiements canoniques v0.2 — adresse CREATE2 identique sur chaque chaîne prise en charge.
| Contrat | Adresse |
|---|---|
| ToolRegistry (v0.2) | 0x265BB2DBFC0A8165C9A1941Eb1372F349baD2cf1 |
| ERC721OwnerPredicate (v0.2) | 0xc8721c9A776958FfFfEb602DA1b708bf1D318379 |
| ERC1155OwnerPredicate (v0.2) | 0x77373Dc3c1AE9A1e937eF3e5E08F4807D47c7c11 |
| SubscriptionPredicate (v0.2) | 0xCBe0cd9B1d99d95Baa9c58f2767246C52e461f25 |
| TraitGatedPredicate (v0.2) | 0x10abF07CfA34Bf22372C57f27e8bd9C2DCF93fA1 |
| ERC20BalancePredicate (v0.2) | 0x1a834FC48B5f6e119c62C12a98b32137bCFA77cD |
Découverte d'outils [Bêta]
Recherchez ou consultez les outils enregistrés via l'API REST d'OpenSea. Nécessite OPENSEA_API_KEY.
# Réutilisez OPENSEA_API_KEY si déjà défini ; sinon récupérez une clé instantanée gratuite
# (pas d'inscription — 600/h lectures, 30/h écritures, expiration 7 jours) et ENREGISTREZ-LA pour réutilisation.
if [ -z "${OPENSEA_API_KEY:-}" ]; then
KEY_FILE="${OPENSEA_CONFIG_DIR:-$HOME/.opensea}/api_key"
if [ -s "$KEY_FILE" ]; then
export OPENSEA_API_KEY=$(cat "$KEY_FILE") # réutiliser la clé en cache
else
api_key=$(curl -s -X POST https://api.opensea.io/api/v2/auth/keys | jq -r '.api_key')
mkdir -p "$(dirname "$KEY_FILE")"
(umask 077; printf '%s\n' "$api_key" > "$KEY_FILE") # enregistrer avant de l'utiliser
export OPENSEA_API_KEY="${api_key}"
fi
fi
Enregistrez toujours une clé instantanée récupérée et réutilisez-la plutôt que de la récupérer à nouveau. La compétence opensea-api fournit un assistant auth/opensea-resolve-key.sh qui fait cela (env → fichier en cache → récupérer + enregistrer) ; voir sa section « Résolution de clé API ». Pour des limites de débit plus élevées, créez une clé complète dans Paramètres → Développeur.
Lister les outils : GET /api/v2/tools (docs)
| Paramètre | Requis | Description |
|---|---|---|
sort_by | Non | Trier par : newest (par défaut), oldest |
type | Non | Filtrer par type d'accès : open, nft_gated, token_gated, subscription, gated |
limit | Non | Résultats par page (1–100) |
cursor | Non | Curseur de pagination |
Rechercher des outils : GET /api/v2/tools/search (docs)
| Paramètre | Requis | Description |
|---|---|---|
query | Non | Texte de la requête de recherche |
registry_chain | Non | Filtrer par ID de chaîne du registre |
tags | Non | Filtrer par tags |
access_type | Non | Filtrer par type d'accès : open, nft_gated, subscription |
creator | Non | Filtrer par adresse du créateur |
sort_by | Non | Trier par : relevance (par défaut), newest, most_used |
limit | Non | Résultats par page (1–200) |
cursor.value | Non | Curseur de pagination |
Obtenir un outil : GET /api/v2/tools/{registry_chain}/{registry_addr}/{tool_id} (docs)
| Paramètre | Requis | Description |
|---|---|---|
registry_chain | Oui | ID de chaîne du registre (ex : 1, 8453) |
registry_addr | Oui | Adresse du contrat du registre |
tool_id | Oui | ID numérique de l'outil |
# Lister les outils triés par les plus récents
curl -s "https://api.opensea.io/api/v2/tools?sort_by=newest&limit=10" \
-H "x-api-key: $OPENSEA_API_KEY" | jq
# Lister les outils filtrés par type
curl -s "https://api.opensea.io/api/v2/tools?type=open&sort_by=oldest" \
-H "x-api-key: $OPENSEA_API_KEY" | jq
# Rechercher des outils par mot-clé
curl -s "https://api.opensea.io/api/v2/tools/search?query=nft" \
-H "x-api-key: $OPENSEA_API_KEY" | jq
# Obtenir un outil spécifique sur Base
curl -s "https://api.opensea.io/api/v2/tools/8453/0x265BB2DBFC0A8165C9A1941Eb1372F349baD2cf1/1" \
-H "x-api-key: $OPENSEA_API_KEY" | jq
# Filtrer par type d'accès
curl -s "https://api.opensea.io/api/v2/tools/search?access_type=open&limit=10" \
-H "x-api-key: $OPENSEA_API_KEY" | jq
1. Créer un outil
1a. Échafauder un projet
npx @opensea/tool-sdk init --runtime vercel # ou : cloudflare, express
Cela génère :
src/manifest.ts— définition du manifeste de l'outilsrc/handler.ts— gestionnaire de requêtes avec schémas d'entrée/sortieapi/index.ts— point d'entrée de l'adaptateur du frameworkpublic/llms.txt— page de découverte lisible par les agentsapi/well-known/[slug].ts— sert le manifeste à/.well-known/ai-tool/<slug>.json
1b. Définir le manifeste
import { defineManifest } from "@opensea/tool-sdk"
export const manifest = defineManifest({
name: "Mon Outil",
description: "Ce que fait cet outil",
endpoint: "https://my-tool.example.com/api",
creatorAddress: "0xYOUR_WALLET_ADDRESS",
inputs: {
type: "object",
properties: {
query: { type: "string", description: "Requête de recherche" },
},
required: ["query"],
},
outputs: {
type: "object",
properties: {
result: { type: "string" },
},
},
// Optionnel : ajouter un prix pour le péage x402 (voir references/x402.md)
// pricing: paywall.pricing,
// Optionnel : ajouter des exigences d'accès (voir references/predicate-gating.md)
// access: { logic: "OR", requirements: [...] },
})
1c. Écrire le gestionnaire
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: [], // Ajouter des barrières ici (voir references/x402.md et references/predicate-gating.md)
handler: async (input) => {
return { result: `Traité : ${input.query}` }
},
})
1d. Câbler l'adaptateur
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 }
2. Enregistrer un outil sur la blockchain
2a. Via CLI
# Configurer le portefeuille
export PRIVATE_KEY=0x...
export RPC_URL=https://mainnet.base.org
# Enregistrer (accès ouvert — pas de prédicat)
npx @opensea/tool-sdk register \
--metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \
--network base
# Enregistrer avec un prédicat d'accès
npx @opensea/tool-sdk register \
--metadata https://my-tool.example.com/.well-known/ai-tool/my-tool.json \
--network base \
--access-predicate 0xPREDICATE_ADDRESS
# Essai à blanc (pas de transaction)
npx @opensea/tool-sdk register --metadata ... --network base --dry-run
Le CLI :
- Récupère le manifeste depuis l'URL
--metadata - Valide le schéma du manifeste
- Vérifie que
manifest.creatorAddresscorrespond à votre portefeuille - Calcule le hash du manifeste JCS keccak256
- Appelle
ToolRegistry.registerTool(metadataURI, manifestHash, accessPredicate) - Retourne le
toolIdà partir de l'événementToolRegistered
2b. Via SDK (programmatique)
import { 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, // votre objet ToolManifest
accessPredicate: "0x0000...0000", // address(0) = accès ouvert
})
console.log(`Outil ${toolId} enregistré dans la tx ${txHash}`)
3. Contrôle d'accès aux outils
Les outils peuvent être contrôlés de trois manières :
| Barrière | Mécanisme | Référence |
|---|---|---|
| Péage x402 | Paiement à l'appel (USDC, EIP-3009) | references/x402.md |
| Barrière par prédicat | Vérification on-chain (NFT, abonnement, contrôle par traits, solde ERC-20, composite) | references/predicate-gating.md |
| Combinée | Authentification EIP-3009 et paiement (prédicat d'abord, puis x402) | references/predicate-gating.md |
Pour les adresses de prédicats déployés, les encodages d'exigences et les assistants SDK comme describeToolAccess / decodeRequirement, voir references/known-predicates.md.
4. Configuration du portefeuille
Le SDK prend en charge plusieurs fournisseurs de portefeuille via @opensea/wallet-adapters. Définissez les variables d'environnement et le SDK détecte automatiquement le fournisseur. Voir la compétence opensea-wallet pour la table complète des fournisseurs, les variables d'environnement, les guides de configuration et la configuration de la politique de signature.
| Fournisseur | Variables d'environnement | Idéal pour |
|---|---|---|
| Clé privée | PRIVATE_KEY | Développement local, scripts |
| Privy | PRIVY_APP_ID, PRIVY_APP_SECRET, PRIVY_WALLET_ID | Portefeuilles serveur |
| Turnkey | TURNKEY_API_PUBLIC_KEY, TURNKEY_API_PRIVATE_KEY, TURNKEY_ORGANIZATION_ID | Signature d'entreprise |
| Fireblocks | FIREBLOCKS_API_KEY, FIREBLOCKS_API_SECRET, FIREBLOCKS_VAULT_ACCOUNT_ID | Conservation institutionnelle |
| Bankr | BANKR_API_KEY | Portefeuilles d'agents (via API HTTP) |
Pour tout fournisseur, RPC_URL (ou le drapeau --rpc-url) définit le point de terminaison RPC pour les lectures et écritures on-chain. Lorsqu'aucun n'est défini, les commandes CLI utilisent par défaut le RPC public du réseau, qui peut être lent ou limité.
import { createWalletFromEnv } from "@opensea/tool-sdk"
// Détection automatique : Privy > Fireblocks > Turnkey > Bankr > PrivateKey
const adapter = createWalletFromEnv()
const address = await adapter.getAddress()
Pour Bankr (signataire externe) :
import { createBankrAccount } from "@opensea/tool-sdk"
const account = await createBankrAccount("votre-clé-api-bankr")
// Utiliser avec eip3009AuthenticatedFetch ou paidAuthenticatedFetch
5. Réponse
…
[écrêté pour la traduction]