# Buying from 3Route

`https://3route.agents.bakingbad.dev` — a multichain DEX aggregator by Baking Bad. It
finds liquidity, can split an order across pools, and returns either a read-only
quote or an unsigned swap transaction. It never signs or broadcasts anything.

## The order of operations

1. `GET /openapi.json` — canonical for operations, parameters, prices and payment
   metadata. Read it before building a request; do not cache it across sessions.
2. Take the chain from `components.parameters.chainId.schema.enum`. Do not guess a
   chain ID and do not look for a chain-discovery endpoint. Today the enum is
   `["128064", "42793"]` — Tezos X and Etherlink.
3. `GET /api/v6.1/{chainId}/tokens` — free. Resolve addresses **and decimals** here.
4. `GET /api/v6.1/{chainId}/quote` — $0.001. Inspect the amounts.
5. `GET /api/v6.1/{chainId}/swap` — $0.005. Only after the user authorized building a
   transaction.

Steps 1–3 are free; 4 and 5 answer `402` and are paid with the client in this skill.
Pay for a quote before a swap: a swap built on an unseen price is a swap nobody
approved.

## Amounts

`amount` is an unsigned decimal string in the token's smallest unit — the human
amount multiplied by `10^decimals`, and greater than zero. 10 XTZ at 18 decimals is
`10000000000000000000`. Never compute it with floating point.

By default `amount` is the amount to sell. With `isExactOutput=true` it is the
desired output and `srcAmount` in the response is the required input.

The zero address means the chain's native asset; `0xeeee…eeee` is accepted for the
same purpose, case-insensitively.

## Optional parameters worth knowing

- `includeTokensInfo`, `includeProtocols`, `includeBlockNumber` only add fields to
  the response. Ask for them in the same paid call rather than paying twice — but treat
  them as best-effort: a deployment may accept the parameter and return nothing.
  Resolve decimals from the free `/tokens` endpoint *before* paying, never from the
  paid response, or a silent omission costs you the call.
- `protocols` / `excludedProtocols` take comma-separated DEX names taken from a
  `protocols` response. An allow-list of names the API does not know fails with 400.
- `fee` is a referral percentage (0–3) deducted from the input and visible in
  `srcAmount`. On swap, pair it with `referrer` — a fee without a referrer is paid to
  the zero address. Disclose any fee to the user.
- `gasPrice` overrides the gas price used for route selection and, on swap, the
  returned `tx.gasPrice`.

## Reading failures

**Branch on the HTTP status, never on the body's `statusCode`.** The no-route case
answers HTTP `400` while the body reports `statusCode: 404` and
`error: "Quote not found"`. Error bodies carry `error`, `description`, `statusCode`,
`requestId` and an optional `meta` array.

**The payment gate runs before validation, so these errors are not free.** An unpaid
invalid request answers `402`, not `400`; the `400` arrives only after the call has been
charged. A route-less pair costs $0.001 to discover. Report the charge, and change the
pair, the amount or the filters before trying again — an unchanged retry is charged
again.

- `400` with `Quote not found` — no route exists. Change the pair, the amount or the
  protocol filters. Retrying the same request just fails again.
- `400` otherwise — fix the chain, token, address, amount or slippage. Never re-pay
  an unchanged invalid request.
- `402` — re-read the challenge. Do not retry if no Etherlink offer is present or the
  price exceeds the cap.

## Before asking for a signature on a swap

The swap response is an unsigned transaction, not proof of anything. Confirm chain
ID, `src`, `dst`, `amount`, exact-input/output mode, `from`, `receiver` (it defaults
to `from`) and slippage. Compare the amounts against a fresh quote and refuse an
unexplained deterioration. Validate `tx.to`, `tx.data`, `tx.value` and the gas fields.

For an ERC-20 source token, approve only the router returned in `tx.to`, only with
explicit user authorization, and only for `srcAmount`. A native source asset needs no
approval and is supplied through `tx.value`.

Signing, broadcasting and confirming are separate steps, each needing its own
authorization. Never claim execution without a confirmed receipt.

## Paying

Free endpoints need no client. For quote and swap:

```sh
ORIGIN=https://3route.agents.bakingbad.dev
uv run scripts/x402_etherlink.py --preflight \
  "$ORIGIN/api/v6.1/128064/quote?src=0x0000000000000000000000000000000000000000&dst=0x2306c83638becff7f567d5b330602d0ddb5780af&amount=10000000000000000000"
```

Then repeat with `--approve` (first paid call from a wallet) or with no flag.

The service also offers Base and Solana rails, which AgentCash can pay
(`npx -y agentcash@latest fetch "$URL"`). AgentCash does not support Etherlink — use
the client in this skill for that.
