walras

Buy: build a client or agent that discovers and pays

You are building software that spends: a client that pays a known paid endpoint, or an agent that first has to find one. Both paths run on stock x402 SDK packages against a walras facilitator; the agent path can also run entirely over MCP with two tools.

Other roles: sell.md · operate.md

What you'll have at the end

A buyer that turns a 402 Payment Required into a signed testnet-USDC payment and a receipt with an on-chain transaction hash — and, if you take the agent path, one that discovers what to pay by searching the Bazaar catalog first. The buyer needs only the payment asset: network fees are sponsored by the facilitator's submitter account (F-006), advertised as extra.areFeesSponsored: true (F-041).

Prerequisites

Path A — HTTP client: pay a known endpoint

1. Install the stock packages

pnpm add @x402/fetch @x402/core @x402/stellar

2. Wrap fetch

The entire client, from demo/buyer.ts — zero custom protocol code:

import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client, x402HTTPClient } from "@x402/core/client";
import { ExactStellarScheme } from "@x402/stellar/exact/client";
import { createEd25519Signer } from "@x402/stellar";

const signer = createEd25519Signer(process.env.CLIENT_STELLAR_PRIVATE_KEY);
const client = new x402Client().register("stellar:*", new ExactStellarScheme(signer));
const fetchWithPayment = wrapFetchWithPayment(fetch, client);

const response = await fetchWithPayment("http://127.0.0.1:4022/weather", { method: "GET" });
const body = await response.json();
const receipt = new x402HTTPClient(client).getPaymentSettleResponse(name =>
  response.headers.get(name),
);
// receipt: { success, transaction, network, payer } — transaction is the on-chain hash (F-038)

3. Know what happens on the wire

One call to fetchWithPayment is two HTTP exchanges, all inside the SDK:

  1. The unpaid request gets a 402 whose terms ride the PAYMENT-REQUIRED header — the v2 canonical name, not X-PAYMENT (F-065).
  2. Your wallet signs a Soroban auth entry authorizing exactly transfer(from, to, amount) — not a pre-signed transaction (F-033).
  3. The retry carries the payment in PAYMENT-SIGNATURE; the receipt comes back in PAYMENT-RESPONSE (F-065).

The whole exchange, stock client on both sides, settled live on stellar:testnet (F-066, S2-2).

Path B — discovery: find what to pay

An agent that has never seen a seller's docs queries the catalog. Semantics you must get right:

curl "http://127.0.0.1:4021/discovery/search?query=current+weather+in+Zurich&limit=5"

demo/agent.ts is the full flow in one file: search, build the request from the listing's info.input, pay with the Path-A client, print the transaction hash and the fee Horizon charged.

Path C — MCP agent: two tools, zero integration code

Point any MCP client at packages/mcp-server over stdio (build first with pnpm build):

{ "command": "node", "args": ["packages/mcp-server/dist/index.js"],
  "env": { "FACILITATOR_URL": "http://127.0.0.1:4021", "CLIENT_STELLAR_PRIVATE_KEY": "S..." } }

Two tools carry the whole discover-then-pay loop (F-080):

Behavior your agent can rely on:

The live example

Troubleshooting

Codes are from the error registry. Discovery errors arrive as error.code on a 4xx; payment rejections arrive as a 200 with isValid: false / success: false plus the code; MCP errors arrive as structuredContent.errorCode of an isError tool result (D-028).

Symptom Code What it means What to do
Search returns 400 walras_missing_search_query The parameter is query, not q (D-006) Rename the parameter
Search returns 400 walras_invalid_search_cursor The cursor was not issued for this query + filter combination (D-027) Restart the walk without a cursor
List/search returns 400 walras_invalid_query_parameter A filter is malformed — limit/offset non-integer, or a repeated parameter Fix the query string
Payment rejected invalid_exact_stellar_payload_simulation_failed Re-simulation did not succeed — an expired auth entry, a replayed payload, and an empty USDC balance all collapse to this code (F-064) Retry with a fresh request; check the buyer's USDC balance and trustline
Payment rejected invalid_exact_stellar_payload_wrong_amount The signed amount does not match the requirements — the tampered-terms case (S5-3) Re-fetch the 402 and pay the terms actually offered
paid_call errors walras_mcp_wallet_not_configured The MCP server has no wallet (D-030) Set CLIENT_STELLAR_PRIVATE_KEY in the server's env
paid_call errors walras_mcp_payment_declined_by_policy The 402 demands more than the spend cap; nothing was signed (D-030) Raise WALRAS_MCP_MAX_AMOUNT if the price is acceptable
paid_call errors walras_mcp_unknown_resource_id The id does not decode to a listing in this catalog (D-029) Re-run search_resources and use a fresh id
Both tools error walras_mcp_facilitator_unreachable The facilitator did not answer at the transport level Check FACILITATOR_URL and that the facilitator is running