Skip to content

Quoting the order book

The order book is where most swap volume clears. Your bot posts prices, traders fill against them, and you earn your spread. Stitch handles the whole loop; this page explains what it does on your behalf and which knobs you control.

What your quotes are

Each quote Stitch posts is a signed limit order: a commitment to trade a specific amount at a specific price, valid until it expires or is replaced. Posting is free and gasless. Your funds only move when a trader actually fills your order, and each order can fill exactly once. The taker pays a small protocol fee on top of your price (per chain, set by the on-chain SellFirstFeeController: 1 bps on BSC and Celo, 5 bps on Ethereum), so the price you quote is the price you get.

What Stitch does each tick

Stitch polls your price feed every few seconds and keeps a two-sided ladder of orders around it:

  • a buy side that spends USDT to buy the non-USD asset (cNGN, wARS, wBRL, XAUt) below the feed price,
  • a sell side that sells the non-USD asset for USDT above it.

When the price moves past your refresh threshold, or orders near expiry, Stitch replaces the whole ladder in one atomic call: the book never shows a half-updated set of your quotes. It also re-checks your wallet every tick and never posts more than your current balance and approvals can actually cover, so normal fills just shrink the next ladder instead of leaving dead orders.

The knobs you control

All of this lives in stitch.toml, per corridor:

SettingWhat it does
Buy / sell offset (bps)Your spread: how far from the feed price each side quotes. This is your margin per fill.
Total liquidity per sideHow much the ladder commits. "max" quotes your full wallet balance; a fixed amount sets a hard cap below it.
Minimum slice / max ordersThe shape of the ladder: how small the smallest order is, and how many orders deep it goes.
Order lifetime (TTL)How long a quote stays valid before it expires. Shorter is safer when the market moves fast.
Refresh threshold (bps)How far the price must move before Stitch requotes.

Start wide and small: a larger offset and a low fixed liquidity cap. Tighten the spread and raise the cap once you've watched the bot trade for a while.

Filling traders' limit orders

Traders can rest their own limit orders in the book, and those are fills you can take proactively instead of waiting for one to cross your quotes. With limit_taker_enabled = true in the pool's config, Stitch checks the resting orders every tick and fills any that are priced at or beyond your own quote — a trader selling cNGN at or below your bid, or buying it at or above your ask. Your spreads are the margin; there is no separate pricing to configure.

Two differences from quoting: taking costs gas (one on-chain transaction per batch of fills), and the protocol's taker fee is on you rather than the trader — Stitch reads the fee from the chain and only fills when the order clears your spread after fee, with an optional per-order minimum profit as a dust guard. It's off by default; see the Stitch configuration reference for the knobs.

Operating notes

  • Approvals matter. Run stitch approve before going live, and again for any new token. Orders from an unapproved or under-approved wallet post but silently never fill; a live start refuses to run without approvals. Approving the maximum once is the standard choice. A capped approval (--exact) is consumed as orders fill and must be re-run every time you raise liquidity.
  • Inventory drifts. Every buy-side fill spends USDT and delivers the counter-asset (cNGN, wARS, wBRL, XAUt) to your wallet. Rebalance or off-ramp on your own schedule; Stitch quotes whatever is actually there.
  • Fixed sides don't auto-grow. A side sized with a fixed amount caps depth even after a wallet top-up. Stitch now logs an info line whenever a fixed-sized side could fund strictly more than it quotes, so you notice and either raise the cap or switch the side to "max".
  • "max" is shared, not duplicated. When several corridors spend the same token (two corridors that both buy with USDT, say) and more than one side is set to "max", Stitch splits that token's uncommitted balance evenly across those sides each tick, so one corridor can't drain the wallet before the others quote. A single "max" side still gets the full balance.
  • Watch the logs. Stitch logs every quote, fill, and skip with the reason. Dry-run mode (--dry-run) shows the full ladder it would post without posting it.
  • Config changes need a restart. Stitch reads stitch.toml at startup.

Advanced: the order book API

You only need this if you're building your own integration instead of running Stitch.

Orders are UniswapX-style exclusive limit orders, signed with EIP-712 and funded through Permit2. One Permit2 nonce can fill once, ever, across all your orders; reusing a nonce in a new order supersedes the old one, which is how requoting works without spending anything.

Submission and reads go through the Textile GraphQL API:

  • submitFillerOrder(input) — post or replace a single order.
  • submitFillerOrders(input: [...]) — atomically replace a whole ladder in one call.
  • submitLimitOrder(input) — post a trader limit order (proceeds always pay to the signer; expiry capped at a year).
  • fillerOrderBook(chainId, collateral, debt) — the live book for a corridor, best price first.
  • fillerLiveEstimate(input) — what a given taker amount would fill at right now.
  • fillerCommittedInput(chainId, maker, inputToken) — the total input your live orders could spend if all filled.
  • restingLimitOrders(chainId, inputToken, outputToken) — resting trader limit orders for one direction, with everything a taker needs to fill them. Verify the signatures yourself before executing, as Stitch does.
  • limitOrdersByWallet(chainId, wallet) — a wallet's limit orders and their statuses.
  • fillerTradesByWallet(wallet) — fill history.

Key fields per order: chainId, clientOrderId, reactor, maker, inputToken, inputAmount, outputToken, outputAmount, recipient, nonce, deadline, signature. Keep clientOrderId stable across requotes (Stitch uses slot IDs like bid:17) so replacements supersede cleanly. Stitch's source is the reference implementation of all of this.

Next