Docs
Everything an agent, or the person setting one up, needs. Short on purpose: the router speaks standard MCP and standard x402, so most of this is the two addresses and the rules around them.
Quickstart: your agent
One package gives you a wallet on Hedera and Arc and a call that pays the 402 for you. Testnet keys; fund a wallet that exists only for this.
npm install onchainrouterimport { createWallet, pay } from "onchainrouter"; const wallet = createWallet({ hedera: { accountId: "0.0.12345", privateKey: "0x..." }, // ECDSA key arc: { privateKey: "0x..." }, // or a Circle wallet maxPerCall: { hbar: "0.2", usdc: "0.05" }, // defaults }); const { status, data, receipt } = await pay( "https://onchainrouter.io/api/tools/lending-rates", { asset: "USDC", chain: "base" }, wallet, ); data.assessment; // the answer receipt?.explorer; // HashScan link on Hedera; Gateway transfer id on Arc
wallet.fetch is a drop-in fetch that pays 402s anywhere. walletFromEnv() reads the same keys from the environment. Over MCP instead: wrapMCPClientWithPayment(mcpClient, wallet.client) from @x402/mcp, connected to https://onchainrouter.io/mcp.
Quickstart: Claude Code
Claude Code cannot sign a payment, so it gets two MCP servers: the router, and a wallet that signs when a tool asks. Keys stay in your environment.
claude mcp add --transport http onchainrouter https://onchainrouter.io/mcp claude mcp add onchain-wallet \ -e HEDERA_AGENT_ACCOUNT_ID=0.0.12345 -e HEDERA_AGENT_PRIVATE_KEY=0x... \ -e ARC_AGENT_PRIVATE_KEY=0x... \ -- npx -y onchainrouter wallet
Then ask something the tools can answer: where should I lend USDC on base? Claude calls lending_rates, gets a payment-required result, hands it to sign_x402_payment, calls the tool again with the signature, and reads the answer. Three tool calls, no action from you. For Arc through a Circle agent wallet, pass the four CIRCLE_* variables instead of a key.
HTTP reference
Every tool is one endpoint. POST a JSON body; the response is JSON.
POST https://onchainrouter.io/api/tools/<slug> GET https://onchainrouter.io/api/tools the catalogue, free
402 | Unpaid. PAYMENT-REQUIRED header carries base64 JSON with accepts: one entry per rail with network, amount (atomic units), asset, payTo. |
200 | Paid and answered. Send the signed payment in PAYMENT-SIGNATURE (or X-PAYMENT). PAYMENT-RESPONSE on the reply carries the settlement receipt. |
400 | Malformed input. Answered before the paywall; nothing to pay. |
404 | Unknown tool, or a tool with no answer for this input: { answer: null, reason, charged: false }. Never settled. |
502 | The tool or a facilitator failed. Never settled. |
MCP reference
Streamable HTTP at https://onchainrouter.io/mcp, stateless. tools/list is free and returns every tool with its input schema. A paid call without a payment returns a result with isError: true whose structuredContent is the same payment-required object as the HTTP 402. Pass the signed payment back either in _meta["x402/payment"] (what @x402/mcp does) or as a payment argument (what a chat client does). The receipt comes back in _meta["x402/payment-response"].
submit_tool is also on the server, free: it probes an endpoint's 402 and returns a listing request. See Sell a tool.
Tools
6 tools, 0.1 HBAR or 0.01 USDC per call. Names below are the MCP names; the HTTP slug replaces underscores with dashes. Generated from the registry, so this is what is served.
lending_rates tool page
Best place to lend or borrow an asset, weighed against liquidity depth.
asset: Asset symbol, e.g. USDC or WETH.chain: Chain to search. One of ethereum, arbitrum, bsc, avalanche, polygon, base, optimism, gnosis, scroll.
{"asset":"USDC","chain":"ethereum"}governance_power tool page
How concentrated a protocol's voting power is, and how much of it never votes.
protocol: Protocol whose delegate table to measure. One of ampleforth, compound, cryptex, ens, euler, gitcoin, hifi, hop, ousd, pooltogether, radicle, rarible, reflexer, threshold, uniswap.
{"protocol":"uniswap"}withdrawal_risk tool page
Whether a deposit can actually leave a lending market right now, and how much can.
asset: Asset symbol, e.g. USDC or WETH.chain: Chain to search. One of ethereum, arbitrum, bsc, avalanche, polygon, base, optimism, gnosis, scroll.amountUsd(optional): Withdrawal size in USD, to check whether it clears.
{"asset":"USDC","chain":"base","amountUsd":50000}liquidation_pressure tool page
Whether borrowers against an asset are being liquidated right now, and how much room the terms leave.
asset: Asset symbol, e.g. WETH or USDC.chain: Chain to search. One of ethereum, arbitrum, bsc, avalanche, polygon, base, optimism, gnosis, scroll.
{"asset":"USDC","chain":"base"}protocol_health tool page
Whether a protocol is growing or draining, and whether it earns anything from what it holds.
protocol: Protocol name. One of aave-amm, aave-arc, aave-rwa, aave-v2, aave-v3, abracadabra, alpaca-finance-lending, banker-joe, bastion-protocol, benqi, burrow, compound-v2, compound-v3, cream-finance, dforce, euler-finance, geist-finance, goldfinch, inverse-finance, iron-bank, kinza-finance, liquity, makerdao, maple-finance-v1, maple-finance-v2, moonwell, morpho-aave-v2, morpho-aave-v3, morpho-compound, pac-finance, qidao, radiant-capital, rari-fuse, scream, seamless-protocol, seismic, sonne-finance, spark-lend, truefi, uwu-lend, venus, vesta-finance, zerolend.chain: Chain the deployment runs on. One of ethereum, arbitrum, bsc, avalanche, polygon, base, optimism, gnosis, scroll.
{"protocol":"moonwell","chain":"base"}governance_pulse tool page
Whether a protocol's governance is still deciding anything, and whether votes clear quorum.
protocol: Protocol whose proposal history to read. One of ampleforth, compound, cryptex, ens, euler, gitcoin, hifi, hop, ousd, pooltogether, radicle, rarible, reflexer, threshold, uniswap.
{"protocol":"ens"}Sell a tool
Wrap a function in an x402 paywall on your own server. Both rails, your address in the 402, settlement straight to you. Return null when there is no answer and the caller is not charged.
import { paid } from "onchainrouter/server"; export const POST = paid( { price: { hbar: "0.1", usdc: "0.01" }, payTo: { hedera: "0.0.12345", arc: "0xYourAddress" }, description: "Liquidation risk for a lending position", parse: (body) => Input.parse(body), // optional; throw to answer 400 unpaid }, async (input) => { const result = await yourExistingLogic(input); if (!result) return null; return result; }, );
That is a Next.js route handler and a plain (Request) => Response for Hono, Bun, Workers or Express. Then list it: the submit page reads price, rails and payout off your 402 and opens a prefilled GitHub issue. Agents can do the same with submit_tool over MCP or POST https://onchainrouter.io/api/submit; both return the issue URL and the external() entry a pull request would add to lib/tools/registry.ts. Already on x402? Skip the wrapper; the router relays your endpoint as is. Endpoints quoting only some other network are refused, since nothing here could pay them.
Rails and prices
| Hedera testnet | hedera:testnet · 0.1 HBAR per call · Blocky402 facilitator, which also sponsors the gas. Gas sponsored. |
| Arc testnet | eip155:5042002 · 0.01 USDC per call · Circle Gateway, gasless from a deposited balance. Gasless. |
One 402 offers both; the client pays on whichever it holds. Testnet only for now. Hedera pays in native HBAR (no token association needed); Arc pays USDC from a Circle Gateway balance, batched, so the receipt is a transfer id rather than a per-payment transaction hash. Spend caps in the client default to 0.2 HBAR and 0.05 USDC per payment.
Funding a wallet
This is the part that takes time. Do it once, in a wallet used for nothing else.
Hedera
- portal.hedera.com: create a testnet account, ECDSA key type. It comes with test HBAR.
- Set
HEDERA_AGENT_ACCOUNT_IDandHEDERA_AGENT_PRIVATE_KEY. Gas is sponsored by the facilitator; the balance only pays the price.
Arc
- An EVM key (
ARC_AGENT_PRIVATE_KEY), or a Circle developer-controlled wallet on ARC-TESTNET (EOA, not SCA) viaCIRCLE_API_KEY,CIRCLE_ENTITY_SECRET,CIRCLE_WALLET_ID,CIRCLE_WALLET_ADDRESS. - Test USDC from faucet.circle.com (Arc Testnet) to that address.
- Deposit once into Circle Gateway (
0x0077777d7EBA4688BDeF3E311b846F25870A19B9); payments draw on that balance, gasless. The repo hasnpm run arc:depositfor this.
Rules
- The agent pays with its own wallet. The router holds no keys and no funds. The playground is the one exception: a capped wallet we fund so the product can be tried without one.
- No answer, no charge. A 4xx on HTTP or
isErroron MCP is never settled. - 0% commission. The 402 names the author's address; money goes agent to author.
- Two rails. Hedera and Arc, testnet. Listings on other networks are refused.
- Coverage is measured.
npm run proberecords which subgraphs answer; the catalogue reads from that.
Source and issues: github.com/web3xDev/onchainrouter. For agents, the same in one file: /llms.txt.