hyperd.budget.guardian
Check recent USDC spend from your wallet before initiating a paid x402 call. Returns total spend, destination breakdown, projected rate, and optional cap compliance.
Instructions
Agent spend visibility: aggregates recent outbound USDC transfers from a wallet over a configurable window (1h/24h/7d/30d). Returns total spend, by-destination breakdown, projected-24h rate, and an optional under_cap flag if cap_usd is provided. Use this BEFORE initiating the next paid x402 call to enforce a self-imposed budget. Bridged USDC.e variants are NOT counted. Costs $0.01 in USDC.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | 0x EVM wallet address | |
| chain | No | Chain to compute spend on. Default 'base'. | |
| window | No | Lookback window. Default '24h'. | |
| cap_usd | No | Optional self-imposed USDC cap. When provided, response includes under_cap, remainingUsd, and anyTxExceedsTenthOfCap. |
Implementation Reference
- src/server.ts:406-423 (registration)Registration of the 'hyperd.budget.guardian' tool using server.tool() with its name, description, schema, and handler.
// hyperd.budget.guardian — agent spend visibility ($0.01) server.tool( "hyperd.budget.guardian", "Agent spend visibility: aggregates recent outbound USDC transfers from a wallet over a configurable window (1h/24h/7d/30d). Returns total spend, by-destination breakdown, projected-24h rate, and an optional under_cap flag if cap_usd is provided. Use this BEFORE initiating the next paid x402 call to enforce a self-imposed budget. Bridged USDC.e variants are NOT counted. Costs $0.01 in USDC.", { address: z.string().describe("0x EVM wallet address"), chain: z .enum(["base", "ethereum", "polygon", "arbitrum", "optimism", "avalanche", "bnb"]) .optional() .describe("Chain to compute spend on. Default 'base'."), window: z .enum(["1h", "24h", "7d", "30d"]) .optional() .describe("Lookback window. Default '24h'."), cap_usd: z.number().positive().optional().describe("Optional self-imposed USDC cap. When provided, response includes under_cap, remainingUsd, and anyTxExceedsTenthOfCap."), }, async (args) => asText(await paidGet("/api/budget/guardian", args)), ); - src/server.ts:410-421 (schema)Zod schema defining the tool's input parameters: address (required string), chain (optional enum), window (optional enum), and cap_usd (optional positive number).
{ address: z.string().describe("0x EVM wallet address"), chain: z .enum(["base", "ethereum", "polygon", "arbitrum", "optimism", "avalanche", "bnb"]) .optional() .describe("Chain to compute spend on. Default 'base'."), window: z .enum(["1h", "24h", "7d", "30d"]) .optional() .describe("Lookback window. Default '24h'."), cap_usd: z.number().positive().optional().describe("Optional self-imposed USDC cap. When provided, response includes under_cap, remainingUsd, and anyTxExceedsTenthOfCap."), }, - src/server.ts:422-422 (handler)The handler function: calls paidGet() to the remote API endpoint '/api/budget/guardian' and wraps the response via asText().
async (args) => asText(await paidGet("/api/budget/guardian", args)), - src/server.ts:79-92 (helper)Helper function 'paidGet' that constructs a URL with query parameters and delegates to paidRequest() for the x402 payment flow.
async function paidGet( path: string, query: Record<string, string | number | boolean | undefined>, ): Promise<unknown> { if (!httpClient) { throw new Error(WALLET_NOT_CONFIGURED_MSG); } const url = new URL(`${API_BASE}${path}`); for (const [k, v] of Object.entries(query)) { if (v !== undefined && v !== "" && v !== null) url.searchParams.set(k, String(v)); } return paidRequest("GET", url, undefined); } - src/server.ts:114-147 (helper)Helper function 'paidRequest' implementing the x402 payment flow: first attempt, then if 402 is returned, creates and sends a payment payload, retries the request.
async function paidRequest( method: "GET" | "POST" | "DELETE", url: URL, body: unknown, ): Promise<unknown> { const requestInit = (extraHeaders: Record<string, string> = {}): RequestInit => { const headers: Record<string, string> = { ...extraHeaders }; let payload: string | undefined; if (body !== undefined && method !== "GET") { headers["Content-Type"] = "application/json"; payload = JSON.stringify(body); } return { method, headers, body: payload }; }; const first = await fetch(url, requestInit()); if (first.status === 200 || first.status === 201) return first.json(); if (first.status !== 402) { throw new Error(`HTTP ${first.status} on initial ${method} request: ${await first.text()}`); } const paymentRequired = httpClient!.getPaymentRequiredResponse( (name) => first.headers.get(name), undefined, ); const paymentPayload = await httpClient!.createPaymentPayload(paymentRequired); const paymentHeaders = httpClient!.encodePaymentSignatureHeader(paymentPayload); const second = await fetch(url, requestInit(paymentHeaders)); if (!second.ok) { throw new Error(`HTTP ${second.status} on payment retry: ${await second.text()}`); } return second.json(); }