Getting started

Getting started

Plan a purchase, buy it under a policy, and check the receipt. About ten minutes on Robinhood Chain testnet.

Tollex runs on Robinhood Chain testnet (eip155:46630) and pays in testnet USDG. Writes to mainnet are disabled until an independent audit is complete. See Security.

What you need

  • The base URL of a Tollex service. Everything else is discovered from /.well-known/tollex.json.
  • An agent wallet with testnet USDG. The private key stays in your signer; Tollex never receives it.
  • A few limits you are comfortable with: the most a single call may cost, and a daily budget.

1. Plan without spending

Ask for what you need with a cost ceiling. Resolve looks at every capability, rules out the ones that cannot meet your constraints, ranks the rest and tells you which one it would buy and why. Nothing is signed and nothing is charged. This works from any language:

HTTP · runs in the Tollex test suite
const response = await fetch(`${TOLLEX_URL}/v1/resolve`, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    need: "spot price for a trading pair",
    input: { pair: "ETH-USD" },
    constraints: { maxCost: "5000", receiptRequired: true }, // atomic units: 0.005 USDG
    quote: true,
  }),
});
const { resolutionId, plan, quote, execute } = await response.json();
// plan.selected, plan.evaluations[].rejections, plan.ranking.formula
// execute: { url, method, headers } to call with an x402 client

maxCost is in atomic units. USDG has six decimals, so "5000" is 0.005 USDG.

2. Set up the client

The TypeScript client wraps your wallet in a policy. The policy is checked before the wallet is asked to sign anything.

TypeScript · runs in the Tollex test suite
import { TollexClient, TollexTools, usdg, type AgentPolicyProfile } from "@tollex/client";
import { PolicyEngine } from "@tollex/policy";
import { verifyReceipt } from "@tollex/receipts";

const client = new TollexClient({
  wallet, // a viem account or a remote signer; the key never leaves it
  policy: new PolicyEngine({
    id: "research-policy",
    agentId: "research-03",
    networks: [NETWORK],
    assets: [{ network: NETWORK, address: USDG_ADDRESS, decimals: 6 }],
    schemes: ["exact"],
    maxPerRequest: usdg("0.01"),
    budgets: { daily: usdg("5") },
  }),
  requireReceipt: true,
});
const tollex = new TollexTools(client, TOLLEX_URL);

3. Buy the outcome

do() resolves the intent, re-reads the live payment terms, pays within your policy, runs the capability and returns the result together with the payment and the signed receipt.

TypeScript · runs in the Tollex test suite
const result = await tollex.do<{ address: string; balance: string }>({
  need: "token balance of a wallet",
  input: { address: wallet.address },
  constraints: { maxCost: usdg("0.001"), receiptRequired: true },
});

result.result.balance; // the capability's output
result.payment.actualAmount; // what was charged, in atomic USDG
result.receiptVerification?.valid; // the signed receipt checked out
result.settlement?.status.settlement; // "included", "finalized", ...

4. Check settlement

A result can arrive before its settlement is final. When you need to know, ask for the operation’s state rather than inferring it from a timeout.

TypeScript · runs in the Tollex test suite
const { status, reached } = await tollex.awaitSettlement(result.tool.id, result.operationId!, {
  until: "included",
  timeoutMs: 30_000,
});

if (!reached && status.status.moneyInFlight) {
  // Not known yet. Do not pay again: ask for the status later.
}

5. Verify the receipt yourself

TypeScript · runs in the Tollex test suite
const res = await fetch(`${TOLLEX_URL}/.well-known/tollex-receipt-keys`);
const { keys } = (await res.json()) as { keys: { address: `0x${string}`; status: string }[] };
const check = await verifyReceipt(result.receipt!, {
  trustedSigners: keys.filter((k) => k.status === "active").map((k) => k.address),
});

check.valid; // signature, content hash and bindings all hold
result.receipt!.body.quote?.quoteHash; // the quote this payment was bound to

That check trusts whatever keys the merchant publishes at that moment. In production, pin the receipt keys you trust instead; Receipts explains how.

Where to go next

  • Intents: every constraint you can set and how they combine.
  • Economic policy: budgets, allow lists and signature lifetimes.
  • SDKs: what the TypeScript and Python clients and the MCP server cover.
Discovery entry point
GET /.well-known/tollex.json
→ endpoints.resolve, endpoints.catalog, endpoints.openapi, endpoints.operation, ...