verify_utr
Verify a Universal Trade Receipt hash by checking its on-chain Solana anchor via memo transaction. Returns chain, signature, slot, explorer URL, and notarizer pubkey for independent verification.
Instructions
Look up a Universal Trade Receipt by hash. Returns whether Tradallo has anchored that hash on-chain via a Solana memo transaction, and if so, returns the chain, signature, slot, posted_at, explorer URL, and notarizer pubkey so the caller can independently verify the anchor on Solana Explorer. The signed-envelope response is ed25519-verified before this tool returns.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| utr_hash | Yes | The 64-char hex SHA-256 UTR hash to look up. |
Implementation Reference
- src/index.ts:219-241 (handler)The MCP tool handler for 'verify_utr'. Validates the utr_hash (64-char hex), then calls client.getSigned to fetch from /api/v1/utrs/{hash}/notarization with ed25519 signature verification.
case "verify_utr": { const utr_hash = String((args as { utr_hash?: unknown })?.utr_hash ?? "") .trim() .toLowerCase(); if (!/^[0-9a-f]{64}$/.test(utr_hash)) { return errorResult("utr_hash must be a 64-char SHA-256 hex string"); } // Direct lookup against the public notarization endpoint. The // TradalloClient verifies the ed25519 signature before returning // the payload, so the MCP layer can trust the booleans below. const data = await client.getSigned<{ utr_hash: string; found: boolean; anchored_on_chain: boolean; chain?: string; signature?: string; slot?: number; posted_at?: string; explorer_url?: string; notarizer_pubkey?: string; }>(`/api/v1/utrs/${encodeURIComponent(utr_hash)}/notarization`); return jsonResult(data); } - src/index.ts:127-143 (schema)The tool registration and schema definition for 'verify_utr', including its name, description, and inputSchema (object with required string property 'utr_hash' matching pattern ^[0-9a-fA-F]{64}$).
{ name: "verify_utr", description: "Look up a Universal Trade Receipt by its SHA-256 hash. Returns whether Tradallo has anchored that hash on-chain via a Solana memo transaction, and if so, the chain, signature, slot, posted_at, Solana Explorer URL, and notarizer pubkey so the caller can independently verify the anchor on chain. The signed envelope is ed25519-verified before this tool returns.\n\nExample:\n - verify_utr(\"b81f2c7e9a4d5e6f8a3b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f\")", inputSchema: { type: "object", properties: { utr_hash: { type: "string", pattern: "^[0-9a-fA-F]{64}$", description: "The 64-char hex SHA-256 UTR hash to look up.", }, }, required: ["utr_hash"], }, annotations: READ_ONLY_ANNOTATIONS, }, - src/client.ts:117-130 (helper)The TradalloClient.getSigned<T>() method used by verify_utr handler. Fetches a signed envelope from the API and verifies the ed25519 signature before returning the inner data payload.
async getSigned<T>(path: string): Promise<T> { const res = await fetch(`${this.baseUrl}${path}`, { headers: { ...this.headers, accept: "application/json" }, }); if (res.status === 404) { throw new Error(`not_found: ${path}`); } if (!res.ok) { throw new Error(`request failed: ${res.status} ${res.statusText} (${path})`); } const envelope = (await res.json()) as SignedEnvelope<T>; await this.verifyEnvelope(envelope); return envelope.data; } - src/client.ts:64-80 (helper)The verifyEd25519 function that cryptographically verifies the signature using Web Crypto API, used by the verify_utr pipeline.
async function verifyEd25519( message: Uint8Array, signature: Uint8Array, pubkeyRaw: Uint8Array, ): Promise<boolean> { if (pubkeyRaw.length !== 32) { throw new Error(`expected 32-byte ed25519 public key, got ${pubkeyRaw.length} bytes`); } const key = await crypto.subtle.importKey( "raw", pubkeyRaw as BufferSource, { name: "Ed25519" }, false, ["verify"], ); return crypto.subtle.verify("Ed25519", key, signature as BufferSource, message as BufferSource); } - src/index.ts:75-177 (registration)The tool catalog registration via ListToolsRequestSchema handler. The verify_utr tool is registered alongside other tools in the list returned to MCP clients.
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: "get_track_record", description: "Fetch a verified trading track record for a Tradallo profile (human) or agent. Returns cryptographically-verified statistics (Sharpe, Sortino, win rate, max drawdown, PnL, trade count, expectancy, profit factor) across all-time and rolling 30/90/365-day windows. The signature is ed25519-verified against Tradallo's published pubkey before this tool returns.\n\nExamples:\n - get_track_record(\"alpha-momentum-v3\") — agent (default)\n - get_track_record(\"aaronjordan\", \"human\") — human profile", inputSchema: { type: "object", properties: { handle: { type: "string", minLength: 1, maxLength: 40, pattern: "^[a-z0-9_-]+$", description: "The Tradallo handle to look up (e.g. 'aaronjordan' for a human, 'alpha-momentum-v3' for an agent). Lowercase letters, digits, hyphens, underscores.", }, principal_type: { type: "string", enum: ["human", "agent"], default: "agent", description: "Whether the handle is a human profile or an agent. Defaults to 'agent' (the more common reputation-query use case).", }, }, required: ["handle"], }, annotations: READ_ONLY_ANNOTATIONS, }, { name: "search_records", description: "Discover verified trading records by performance filters. Returns a list of summary records sorted by the chosen metric. Useful when an agent is shopping for strategies that meet specific risk/return criteria rather than looking up a known handle. Every result is signature-verified against Tradallo's published pubkey.\n\nExample:\n - search_records({ min_sharpe: 1.5, min_trades: 100, max_drawdown: 0.15, sort_by: \"sharpe\", limit: 10 })", inputSchema: { type: "object", properties: { min_sharpe: { type: "number", minimum: 0, description: "Minimum annualized Sharpe ratio." }, min_trades: { type: "integer", minimum: 0, description: "Minimum trade count." }, max_drawdown: { type: "number", minimum: 0, maximum: 1, description: "Maximum drawdown as a fraction (e.g. 0.25 for 25%)." }, venue: { type: "string", description: "Restrict to a specific venue (e.g. 'hyperliquid', 'dydx')." }, principal_type: { type: "string", enum: ["human", "agent"] }, sort_by: { type: "string", enum: ["sharpe", "net_pnl", "trade_count", "win_rate"], default: "net_pnl", description: "Field to sort results by (descending). Default: net_pnl.", }, limit: { type: "integer", minimum: 1, maximum: 100, default: 25, description: "Max results (1-100)." }, }, }, annotations: READ_ONLY_ANNOTATIONS, }, { name: "verify_utr", description: "Look up a Universal Trade Receipt by its SHA-256 hash. Returns whether Tradallo has anchored that hash on-chain via a Solana memo transaction, and if so, the chain, signature, slot, posted_at, Solana Explorer URL, and notarizer pubkey so the caller can independently verify the anchor on chain. The signed envelope is ed25519-verified before this tool returns.\n\nExample:\n - verify_utr(\"b81f2c7e9a4d5e6f8a3b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f\")", inputSchema: { type: "object", properties: { utr_hash: { type: "string", pattern: "^[0-9a-fA-F]{64}$", description: "The 64-char hex SHA-256 UTR hash to look up.", }, }, required: ["utr_hash"], }, annotations: READ_ONLY_ANNOTATIONS, }, { name: "get_versions", description: "Fetch the full version history of an agent: semver tags, version_hash, policy_hash, when each version was deployed and superseded. Use this to understand which version of an agent's policy produced a given track record before delegating capital. Signature-verified.\n\nExample:\n - get_versions(\"alpha-momentum-v3\")", inputSchema: { type: "object", properties: { agent_handle: { type: "string", minLength: 1, maxLength: 40, pattern: "^[a-z0-9_-]+$", description: "The agent's Tradallo handle." }, }, required: ["agent_handle"], }, annotations: READ_ONLY_ANNOTATIONS, }, { name: "get_utrs", description: "Fetch raw Universal Trade Receipts for an agent. Each UTR is a v2 canonical receipt with its SHA-256 hash recomputed by Tradallo so consumers can spot-check individual receipts against `verify_utr`. Paginated cursor-style on closed_at — pass the prior response's `next_since` to advance.\n\nExample:\n - get_utrs(\"alpha-momentum-v3\", undefined, 50)", inputSchema: { type: "object", properties: { agent_handle: { type: "string", minLength: 1, maxLength: 40, pattern: "^[a-z0-9_-]+$", description: "The agent's handle." }, since: { type: "string", format: "date-time", description: "ISO timestamp; only return UTRs closed at or after this. Defaults to the agent's registration anchor.", }, limit: { type: "integer", minimum: 1, maximum: 500, default: 100, description: "Page size (1-500)." }, }, required: ["agent_handle"], }, annotations: READ_ONLY_ANNOTATIONS, }, ], }));