Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
SIWA (Sign-In With Agent) authentication for ERC-8004 registered agents.
SIWA (Sign-In With Agent) authentication for ERC-8004 registered agents.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run.
Sign-In With Agent (SIWA) lets AI agents authenticate with services using their ERC-8004 onchain identity.
npm install @buildersgarden/siwa
Choose based on your wallet provider: Bankr β Bankr Agent API wallets Circle β Circle developer-controlled wallets Privy β Privy server wallets Private Key β Raw private key (viem LocalAccount) Keyring Proxy β Self-hosted proxy with optional 2FA
Server-Side Verification β Next.js, Express, Hono, Fastify
ImportDescription@buildersgarden/siwaCore: signSIWAMessage, verifySIWA, createSIWANonce, parseSIWAMessage, buildSIWAMessage, createClientResolver, parseChainId@buildersgarden/siwa/signerSigner factories (see wallet-specific skills above)@buildersgarden/siwa/erc8128ERC-8128 HTTP signing/verification@buildersgarden/siwa/receiptHMAC receipt helpers@buildersgarden/siwa/nonce-storeNonce stores (Memory, Redis, KV)@buildersgarden/siwa/identitySIWA_IDENTITY.md helpers@buildersgarden/siwa/registryOnchain agent registration@buildersgarden/siwa/client-resolverDynamic PublicClient resolution for multi-chain servers@buildersgarden/siwa/nextNext.js middleware (withSiwa, siwaOptions)@buildersgarden/siwa/expressExpress middleware (siwaMiddleware, siwaJsonParser, siwaCors)@buildersgarden/siwa/honoHono middleware (siwaMiddleware, siwaCors)@buildersgarden/siwa/fastifyFastify middleware (siwaPlugin, siwaAuth)@buildersgarden/siwa/x402x402 payment helpers@buildersgarden/siwa/captchaReverse CAPTCHA (prove you're an AI)
When an API requires payment, it returns HTTP 402 with a Payment-Required header. The agent decodes the payment options, constructs a signed payment, and retries with a Payment-Signature header β all while maintaining SIWA authentication.
import { encodeX402Header, decodeX402Header, type PaymentRequired, type PaymentPayload, } from "@buildersgarden/siwa/x402"; import { signAuthenticatedRequest } from "@buildersgarden/siwa/erc8128"; // 1. Make initial authenticated request (may get 402) const signedRequest = await signAuthenticatedRequest( new Request("https://api.example.com/premium", { method: "POST" }), receipt, signer, 84532, ); const res = await fetch(signedRequest); if (res.status === 402) { // 2. Decode payment requirements from header const header = res.headers.get("Payment-Required"); const { accepts, resource } = decodeX402Header<PaymentRequired>(header!); // 3. Pick a payment option and construct payload const option = accepts[0]; const payload: PaymentPayload = { signature: "0x...", // sign the payment with your wallet payment: { scheme: option.scheme, network: option.network, amount: option.amount, asset: option.asset, payTo: option.payTo, }, resource, }; // 4. Retry with both SIWA auth + payment header const retryRequest = await signAuthenticatedRequest( new Request("https://api.example.com/premium", { method: "POST", headers: { "Payment-Signature": encodeX402Header(payload), }, }), receipt, signer, 84532, ); const paidRes = await fetch(retryRequest); // paidRes.headers.get("Payment-Response") contains { txHash, ... } }
HeaderDirectionDescriptionPayment-RequiredServer β AgentBase64-encoded JSON with accepted payment options. Sent with 402.Payment-SignatureAgent β ServerBase64-encoded signed payment payload.Payment-ResponseServer β AgentBase64-encoded settlement result with transaction hash.
Some endpoints use pay-once mode: the first request requires payment, subsequent requests from the same agent to the same resource pass through without payment until the session expires. If you receive a 200 on a previously-paid endpoint, the session is still active β no need to pay again.
SIWA includes a "reverse CAPTCHA" mechanism β inspired by MoltCaptcha β that proves an entity is an AI agent, not a human. Challenges exploit how LLMs generate text in a single autoregressive pass (satisfying multiple constraints simultaneously), while humans must iterate. Two integration points: Sign-in flow β server requires captcha before issuing a nonce Per-request β middleware randomly challenges agents during authenticated API calls
The SDK provides two convenience wrappers for the captcha retry pattern: Sign-In Captcha: solveCaptchaChallenge() import { solveCaptchaChallenge } from "@buildersgarden/siwa/captcha"; // 1. Request nonce const nonceRes = await fetch("/api/siwa/nonce", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address, agentId, agentRegistry }), }); const data = await nonceRes.json(); // 2. Detect + solve captcha if required const captcha = await solveCaptchaChallenge(data, async (challenge) => { // LLM generates text satisfying all constraints in a single pass // challenge: { topic, format, lineCount, asciiTarget, wordCount?, timeLimitSeconds, ... } // Your LLM generates text satisfying all constraints in one pass. // Use any provider (Anthropic, OpenAI, etc.) β the solver just returns a string. return await generateText(challenge); }); if (captcha.solved) { // 3. Retry with challenge response const retryRes = await fetch("/api/siwa/nonce", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address, agentId, agentRegistry, challengeResponse: captcha.challengeResponse }), }); } Per-Request Captcha: retryWithCaptcha() import { signAuthenticatedRequest, retryWithCaptcha } from "@buildersgarden/siwa/erc8128"; const url = "https://api.example.com/action"; const body = JSON.stringify({ key: "value" }); // 1. Sign and send const signed = await signAuthenticatedRequest( new Request(url, { method: "POST", body }), receipt, signer, chainId, ); const response = await fetch(signed); // 2. Detect + solve captcha, re-sign, and get retry request const result = await retryWithCaptcha( response, new Request(url, { method: "POST", body }), // fresh request (original body consumed) receipt, signer, chainId, async (challenge) => generateText(challenge), // your LLM solver ); if (result.retry) { const retryResponse = await fetch(result.request); } Note: Pass a fresh, unconsumed Request to retryWithCaptcha β the original is consumed after signing/sending.
LevelTime LimitConstraintseasy30sLine count + ASCII sum of first charsmedium20s+ word counthard15s+ character at specific positionextreme10s+ total character count
Documentation ERC-8004 ERC-8128
Agent frameworks, memory systems, reasoning layers, and model-native orchestration.
Largest current source with strong distribution and engagement signals.