web3_challenge
Obtain a Sign-In with Ethereum (SIWE) challenge for a wallet address, the first step to generate a free API key using only a wallet. No browser or email required.
Instructions
Get a SIWE (Sign-In with Ethereum) challenge message for a wallet address. This is the first step to create a free API key using only a wallet — no browser or email required. The returned message must be signed with personal_sign (EIP-191), then submitted to web3_signup.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Ethereum wallet address (e.g., '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18') |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | Result data object |
Implementation Reference
- src/index.ts:2073-2112 (registration)Registration of the web3_challenge tool via server.registerTool. Includes the tool name 'web3_challenge', description (SIWE challenge for wallet address), inputSchema (address), annotations, and the async handler.
server.registerTool( "web3_challenge", { description: "Get a SIWE (Sign-In with Ethereum) challenge message for a wallet address. " + "This is the first step to create a free API key using only a wallet — no browser or email required. " + "The returned message must be signed with personal_sign (EIP-191), then submitted to web3_signup.", inputSchema: { address: z.string().describe("Ethereum wallet address (e.g., '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18')"), }, outputSchema: ObjectOutputSchema, annotations: AUTH_TOOL_ANNOTATIONS, }, async (params: any) => { // This tool works even without an API key — it calls the unauthenticated challenge endpoint try { if (client) { const data = await api().web3.challenge(params.address); return formatResponse(data); } // If no client, make a direct fetch const response = await fetch("https://api.0xarchive.io/v1/auth/web3/challenge", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: params.address }), }); const data = await response.json(); if (!response.ok) { return { content: [{ type: "text" as const, text: `Error: ${data.error || "Challenge request failed"}` }], isError: true, }; } return formatResponse(data); } catch (err) { const error = err instanceof OxArchiveError ? err : new OxArchiveError(String(err), 500); return formatError(error); } } ); - src/index.ts:2086-2111 (handler)The handler function for web3_challenge. It first tries to call api().web3.challenge(params.address) if an SDK client exists, otherwise it makes a direct POST to https://api.0xarchive.io/v1/auth/web3/challenge with the address, returning the challenge message.
async (params: any) => { // This tool works even without an API key — it calls the unauthenticated challenge endpoint try { if (client) { const data = await api().web3.challenge(params.address); return formatResponse(data); } // If no client, make a direct fetch const response = await fetch("https://api.0xarchive.io/v1/auth/web3/challenge", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ address: params.address }), }); const data = await response.json(); if (!response.ok) { return { content: [{ type: "text" as const, text: `Error: ${data.error || "Challenge request failed"}` }], isError: true, }; } return formatResponse(data); } catch (err) { const error = err instanceof OxArchiveError ? err : new OxArchiveError(String(err), 500); return formatError(error); } } - src/index.ts:2064-2070 (helper)AUTH_TOOL_ANNOTATIONS — annotation helper marking web3 tools as non-read-only (since they create API keys). Used by web3_challenge registration.
// Web3 tools are NOT read-only (they create accounts/keys) const AUTH_TOOL_ANNOTATIONS = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true, } as const; - src/index.ts:24-34 (helper)MISSING_KEY_MESSAGE constant that references web3_challenge (and web3_signup) in the setup instructions shown when no API key is configured.
const MISSING_KEY_MESSAGE = `API key not configured. To use 0xArchive tools:\n\n` + `Option A — Browser signup:\n` + `1. Sign up at https://0xarchive.io and go to Dashboard to create an API key\n\n` + `Option B — Wallet signup (no browser needed):\n` + `1. Use the web3_challenge and web3_signup tools to get a free API key with your Ethereum wallet\n\n` + `Then reconfigure the MCP server with your key:\n\n` + ` claude mcp remove 0xarchive\n` + ` claude mcp add 0xarchive -s user -t stdio -e OXARCHIVE_API_KEY=0xa_your_api_key -- node /path/to/build/index.js\n\n` + `Start a new Claude Code session after configuring.\n\n` + `Free tier includes BTC historical data. Upgrade at https://0xarchive.io/pricing for all coins.`; - src/index.ts:2075-2083 (schema)Input/output schemas for web3_challenge: inputSchema requires a single 'address' field (Ethereum wallet address string), outputSchema uses ObjectOutputSchema.
{ description: "Get a SIWE (Sign-In with Ethereum) challenge message for a wallet address. " + "This is the first step to create a free API key using only a wallet — no browser or email required. " + "The returned message must be signed with personal_sign (EIP-191), then submitted to web3_signup.", inputSchema: { address: z.string().describe("Ethereum wallet address (e.g., '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD18')"), }, outputSchema: ObjectOutputSchema,