> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# @sauce/router

> @sauce/router swaps at a venue's pool, with every argument read at run time. Use this reference when a program picks its pool while it runs.

`@sauce/router` swaps at a venue's pool: one function per venue, imported inside a program. Every argument is a value read at run time, so a program can choose the pool, the direction and the amount while it runs, and spend one swap's output in the next. Each function returns an output amount. How it obtains that amount depends on the venue: some use the pool's reported output and others measure a balance change. If your program must verify the recipient's actual receipt, check the recipient's token balance before and after the swap.

```ts swap.sauce.ts theme={null}
// Sells `amount` of the Pot's WETH for USDC in the chain's 0.05% Uniswap V3 pool, paid to `recipient`
// (a wallet, or `pot` to keep it in the Pot), and returns what `recipient` received.
import { uniswapV3 } from "@sauce/router";

function main(amount: Uint256, sqrtPriceLimitX96: Uint256, minOut: Uint256, recipient: Address): Uint256 {
  const pool = UniswapV3.Factory.getPool(WETH, USDC, 500);
  require(pool != 0, "no 0.05% pool");
  return uniswapV3(pool, WETH, USDC, amount, sqrtPriceLimitX96, minOut, recipient);
}
```

The same file compiles for Base and Ethereum, each with its own factory, WETH and USDC.

The swap actions of an [actions document](https://docs.eco.com/sauce-sdk/typescript/actions.md) compile to calls into the same functions, so a JSON document and a hand-written program trade a venue through the same code.

On Solana the same specifier holds a different set of functions, one per Solana venue ([On Solana](#on-solana)). The EVM and Solana implementations export different functions. Importing a function unavailable on your target produces a compile error.

## Functions

Every function takes its arguments in one order, the pool, the two tokens, the amount, the venue's own facts, then the floor and the recipient, and returns what the recipient received:

```text theme={null}
venue(pool, tokenIn, tokenOut, amountIn, ...facts, minOut, recipient): Uint256
```

```ts theme={null}
function uniswapV2(pair: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, feePpm: Uint256, minOut: Uint256, recipient: Address): Uint256
function uniswapV3(pool: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, sqrtPriceLimitX96: Uint256, minOut: Uint256, recipient: Address): Uint256
function uniswapV4(poolManager: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, fee: Uint256, tickSpacing: Uint256, hooks: Address, sqrtPriceLimitX96: Uint256, minOut: Uint256, recipient: Address): Uint256
function curve(pool: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, i: Uint256, j: Uint256, uint256Indices: bool, minOut: Uint256, recipient: Address): Uint256
function balancerV2(vault: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, poolId: Uint256, minOut: Uint256, recipient: Address): Uint256
function dodoV2(pool: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, baseToken: Address, quoteToken: Address, minOut: Uint256, recipient: Address): Uint256
function traderJoeLB(pair: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, tokenX: Address, tokenY: Address, minOut: Uint256, recipient: Address): Uint256
function woofi(pool: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, minOut: Uint256, recipient: Address): Uint256
function maverickV2(pool: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, minOut: Uint256, recipient: Address): Uint256
function infinityCL(vault: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, poolManager: Address, fee: Uint256, parameters: Uint256, hooks: Address, sqrtPriceLimitX96: Uint256, minOut: Uint256, recipient: Address): Uint256
function infinityBin(vault: Address, tokenIn: Address, tokenOut: Address, amountIn: Uint256, poolManager: Address, fee: Uint256, parameters: Uint256, hooks: Address, minOut: Uint256, recipient: Address): Uint256
```

Each has a `try` form with the same arguments: `tryUniswapV2`, `tryUniswapV3`, `tryUniswapV4`, `tryCurve`, `tryBalancerV2`, `tryDodoV2`, `tryTraderJoeLB`, `tryWoofi`, `tryMaverickV2`, `tryInfinityCL` and `tryInfinityBin` ([The try forms](#the-try-forms)).

### Common arguments

* **`amountIn`** is what the Pot pays. Every swap is exact input; there is no exact-output form.
* **`minOut`** is the minimum accepted output. A result below it raises a failure; an unhandled failure reverts the cook. `0` sets no floor, except for `woofi`, which requires a positive one. Where the venue enforces a floor itself (Curve's `min_dy`, the Balancer Vault's `limit`, WooPPV2's `minToAmount`), `minOut` is passed as that floor; otherwise the function checks the amount the venue reports.
* **`recipient`** receives the output. `pot`, the Pot the program runs on ([Names](https://docs.eco.com/sauce/names.md#balances)), keeps it in the Pot, where a later step of the program, or a later cook, spends it.
* **The return value** is what the recipient received, as the pool or the Router reports it. For Curve, whose older pools report nothing, it is the balance change.

### Venue facts

| Function | Pool argument | Its own facts |
| - | - | - |
| `uniswapV2` | the pair | `feePpm`: the pair's LP fee in parts per million: 3000 (0.30%) for Uniswap V2, which `0` also means; 2500 for PancakeSwap V2. 1,000,000 or more reverts |
| `uniswapV3` | the pool | `sqrtPriceLimitX96`: a price at which the swap stops; `0` for none. Slipstream, PancakeSwap V3 and Algebra pools swap through it too |
| `uniswapV4` | the PoolManager | `fee`, `tickSpacing`, `hooks`: with `tokenIn` and `tokenOut` in sort order, the pool key. Native ETH is the zero address, which the Pot pays from its own balance |
| `curve` | the pool | `i`, `j`: coin indices; `uint256Indices`: `true` for a CryptoSwap pool, `false` for StableSwap and NG pools (`int128` indices) |
| `balancerV2` | the Vault | `poolId`: the pool's 32-byte id. The swap is GIVEN\_IN, with internal balances off |
| `dodoV2` | the pool (DVM, DPP or DSP) | `baseToken`, `quoteToken`: the pool's own |
| `traderJoeLB` | the pair | `tokenX`, `tokenY`: the pair's own. Amounts are `uint128` |
| `woofi` | the WooPPV2, not the WooRouterV2 | none; `minOut` is required, because the pool prices from an oracle |
| `maverickV2` | the pool | none; the swap covers the pool's full tick range |
| `infinityCL` | the Infinity Vault | `poolManager`, `fee`, `parameters`, `hooks`, `sqrtPriceLimitX96`: PancakeSwap Infinity's CL pool key and a price limit |
| `infinityBin` | the Infinity Vault | `poolManager`, `fee`, `parameters`, `hooks`: the bin pool key; no price limit |

## How each venue is reached

| Reached | Functions |
| - | - |
| Paid first and called directly by the program | `uniswapV2`, `curve`, `balancerV2`, `dodoV2`, `traderJoeLB`, `woofi` |
| Through the Pot's Router | `uniswapV3`, `uniswapV4`, `maverickV2`, `infinityCL`, `infinityBin` |

The pay-first venues never call back. Each function either pushes the input to the pool first (V2, DODO, Trader Joe, WOOFi) or approves exactly the input for the pool or the Vault to pull (Curve, Balancer), which leaves a zero allowance. Such a swap consumes its whole input or reverts, and runs in any Pot.

Uniswap V3 and its forks, Uniswap V4, Maverick V2 and PancakeSwap Infinity pools call their caller back during the swap to be paid. A program cannot answer a callback, so these functions call the Pot's Router at the Pot's own address. The Pot's fallback delegatecalls the Router, which runs as the Pot and answers the callback. Each callback is authenticated to the pool being swapped, pays once, and pays only the input the pool asks for, never more than `amountIn`. Where a price limit stops the pool early, the unspent input stays in the Pot.

Each Pot has its own Router. A new Pot starts on the Kitchen's current Router, and after that only the Pot's owner can point it at another one. A Router is identified by its address, not by a version number: [Deployments](https://docs.eco.com/sauce-sdk/reference/deployments.md) gives the Router, which `v12RouterAddress()` returns in TypeScript. See [Pot](https://docs.eco.com/sauce/pot.md).

Every token write in the library is [`@sauce/token`](https://docs.eco.com/sauce-libraries/token)'s, with OpenZeppelin `SafeERC20` semantics: USDT works, and a `false` return reverts.

## Flash swaps

`@sauce/router` has no flash function. The Pot's Router has one, `flash(callback, swap)`, which a program calls at the Pot's own address through a JSON ABI that declares it:

* `swap` is the calldata of one of the Router's own swap methods: `swapV3`, `swapV4`, `swapMaverickV2`, `swapInfinityCL` or `swapInfinityBin`.
* `callback` is a program: what `program(...)` returns, its `code` followed by its `args`. The venue sends the output first. The Router then runs `callback` inside the venue's callback, before it pays the venue, and pays out of what the Pot holds by then. A callback that leaves the Pot short fails the payment, and the whole swap reverts.
* The Router runs only the `callback` it was given. A swap whose venue never calls back, a swap of 0 included, reverts with `CallbackNotRun()`.
* It returns what the swap method returns: the input the Router paid, then the output.
* The callback runs while the venue is in the middle of its swap. A Uniswap V3 pool is locked then, so a callback that swaps in the same pool reverts with `LOK`.

```ts flash-swap.sauce.ts theme={null}
// Sells `amountIn` of the Pot's WETH for USDC in the chain's 0.05% Uniswap V3 pool through the
// Router's `flash`. Inside the pool's callback, before the pool is paid, the callback program
// requires the USDC to be in the Pot already. Returns the USDC received.
//
//   sauce simulate flash-swap.sauce.ts --chain <chain> --owner <address> \
//     --assume-balance WETH:<amount> --args <amountIn>
//
//   amountIn: Uint256   the WETH to sell, in wei (18 decimals): 10000000000000000 is 0.01 WETH
import SauceRouterFlash from "./SauceRouterFlash.json";

function main(amountIn: Uint256): Uint256 {
  const pool = UniswapV3.Factory.getPool(WETH, USDC, 500);
  require(pool != 0, "no 0.05% pool");
  const before = USDC.balanceOf(pot);

  // Runs inside the pool's callback: the pool has sent the USDC and is not paid yet.
  const check = program(() => {
    require(USDC.balanceOf(pot) > before, "the USDC has not arrived");
  });
  // The swap the Router runs around it: the calldata of the Router's own `swapV3`.
  const swapV3 = (crypto.keccak256("swapV3(address,address,bool,uint256,uint160,address)") >> 224)
    .toBytesBe(4)
    .concat(abi.encode(pool, WETH, WETH < USDC, amountIn, 0, pot));
  const [paid, received] = SauceRouterFlash.at(pot).flash(check.code.concat(check.args), swapV3);
  return received;
}
```

`SauceRouterFlash.json`, beside it:

```json SauceRouterFlash.json theme={null}
[
  {
    "type": "function",
    "name": "flash",
    "stateMutability": "nonpayable",
    "inputs": [
      { "name": "callback", "type": "bytes" },
      { "name": "swap", "type": "bytes" }
    ],
    "outputs": [
      { "name": "amountInUsed", "type": "uint256" },
      { "name": "amountOut", "type": "uint256" }
    ]
  }
]
```

It compiles for Base and Ethereum. On a local fork of Base at block 53159700 with the current contracts, `sauce simulate flash-swap.sauce.ts --chain base --owner <address> --assume-balance WETH:0.01 --args 10000000000000000` returned `23260395`. The pool sent the Pot 23.260395 USDC, and the Pot paid it 0.01 WETH after the callback:

```text theme={null}
main returns Uint256: 23260395
...
What moved, in order:
...
  [3] 0xd0b5…F224        -> Pot                  23.260395 USDC
  [4] Pot                -> 0xd0b5…F224          0.01 WETH
```

With `amountIn` 0 the cook reverts with `CallbackNotRun()`.

## Direction and orientation

Each function works out the side it trades from its own arguments while the program runs, and reverts rather than trade a side the arguments contradict:

* a Uniswap V2 pair's and a V4 pool's direction is the sort order of `tokenIn` and `tokenOut`;
* `dodoV2` sells base when `tokenIn` is `baseToken` and quote when it is `quoteToken`, and reverts unless the two tokens are those two. The side cannot come from address order, and a wrong one would not revert at the pool;
* `traderJoeLB` checks `tokenX` and `tokenY` the same way;
* the library checks a V3 or Maverick pool's tokens before the swap.

Take the facts from the pool: they are the caller's, like the pool address.

## The try forms

A `try` form can skip a swap and return `0` without moving tokens in the cases listed below. This lets the program continue to another venue. A concentrated-liquidity swap can also stop at its price limit after spending only part of the input; a positive return indicates a completed swap, not necessarily a full fill. A swap that ran returns at least 1, so `0` always means nothing moved. A failure a `try` form does not check for still reverts the program, as the plain form does.

* `tryUniswapV2`, `tryTraderJoeLB`, `tryDodoV2` and `tryWoofi` check before anything moves that the pool takes the whole input at the floor, from the pool's own view (the V2 reserves, `getSwapOut`, `querySellBase`/`querySellQuote`, `query`). All four skip a pool with no code, such as the `0` a factory returns for a missing pair. `tryDodoV2` and `tryWoofi` also skip a pool whose view reverts. `tryUniswapV2` and `tryTraderJoeLB` read the view uncaught, so a contract that has code but is not a pair, such as a token, reverts the program. Once the check passes, the swap runs uncaught.
* `tryCurve` and `tryBalancerV2` skip a pool or Vault with no code. For one with code, they catch the pool's or the Vault's failure, such as an output below `minOut`, and reset the approval to zero.
* `tryUniswapV3`, `tryUniswapV4`, `tryMaverickV2`, `tryInfinityCL` and `tryInfinityBin` catch the Router's call. A pool with no code, a pool for another pair, a key no pool has, or a swap the pool or Router refuses is skipped. A swap that ran is held to `minOut`, and at least 1, on what the recipient's balance gained, or the program reverts, because input the pool kept cannot be returned: an output below `minOut` reverts rather than skips. With no price limit, an empty pool costs a full tick walk before it is skipped; pass a `sqrtPriceLimitX96` to bound it.

On a local fork of Base at block 53005062 with the current contracts:

* Given `0x…dEaD`, an address with no code, each of the eleven `try` forms returned `0`. `tryUniswapV2`, `tryTraderJoeLB`, `tryCurve` and `tryBalancerV2` also returned `0` for the zero address.
* `tryUniswapV2` and `tryTraderJoeLB` given Base's USDC contract, which has code and is not a pair, reverted with no data.
* `tryUniswapV2` at the Uniswap V2 USDC/WETH pair, selling 1,000 USDC, returned 418305883082737258 (0.418 WETH) with a `minOut` of 1, and `0` with nothing moved with a `minOut` of 10^30.
* `tryUniswapV3` at the 0.05% USDC/WETH pool returned 419272799328827730 (0.419 WETH) with a `minOut` of 1, and with a `minOut` of 10^30, above its output, reverted.

On a local fork of Ethereum at block 26258727 with the current contracts:

* `tryUniswapV2`, `tryTraderJoeLB`, `tryCurve` and `tryBalancerV2` returned `0` for `0x…dEaD` and for the zero address. `tryUniswapV2` and `tryTraderJoeLB` given Ethereum's USDC contract reverted with no data.
* `tryUniswapV2` at the Uniswap V2 USDC/WETH pair, selling 1,000 USDC, returned 419238855521904606 (0.419 WETH) with a `minOut` of 1, and `0` with a `minOut` of 10^30.
* `tryCurve` at the 3pool, selling 1,000 USDC for USDT, returned 1000825422 (1,000.825422 USDT) with a `minOut` of 1, and `0` with a `minOut` of 2,000 USDT.
* `tryBalancerV2` at the BAL/WETH pool, selling 0.1 WETH, returned 1935915708649823758613 (1,935.9 BAL) with a `minOut` of 1, and `0` with a `minOut` of 10^30.

The registry has no Trader Joe LB deployment on Base or Ethereum, so `tryTraderJoeLB` was not run against an LB pair there.

The `try` forms are EVM only: the Solana arm has none, and importing one for Solana fails at the import ("`tryUniswapV3` is not exported by module …").

```ts swap-fallback.sauce.ts theme={null}
import { tryUniswapV3, uniswapV2 } from "@sauce/router";

// Sells `amountIn` of the Pot's USDC for WETH at Uniswap V3's 0.05% pool and sends the WETH to
// `recipient`. Where that swap cannot run (no pool, no liquidity in range), it moves nothing and
// the program sells at the Uniswap V2 pair instead. Below `minOut` the whole transaction reverts.
//
//   sauce simulate swap-fallback.sauce.ts --chain <chain> --owner <owner> \
//     --assume-balance USDC:<amount> --args <amountIn> <minOut> <recipient>
//
//   amountIn: Uint256    the USDC to sell, in its smallest units (6 decimals): 1000000000 is 1,000
//   minOut: Uint256      the least WETH to receive, in its smallest units (18 decimals)
//   recipient: Address   who receives the WETH: a wallet, or the Pot's address to keep it there
function main(amountIn: Uint256, minOut: Uint256, recipient: Address): Uint256 {
  const pool = UniswapV3.Factory.getPool(USDC, WETH, 500);
  const got = tryUniswapV3(pool, USDC, WETH, amountIn, 0, minOut, recipient);
  if (got > 0) return got;
  const pair = UniswapV2.Factory.getPair(USDC, WETH);
  return uniswapV2(pair, USDC, WETH, amountIn, 3000, minOut, recipient);
}
```

When a V3 swap stops at a price limit, part of `amountIn` stays in the Pot. A program that must not leave it there sends back `amountIn` less what the swap took: the token balance before the swap minus the balance after. An atomic `try` block around a swap and its checks undoes the whole attempt instead, as the [try-fallback swap](https://docs.eco.com/quickstarts/sauce/try-fallback-swap.md) does.

## Price limits

`sqrtPriceLimitX96` bounds the pool's price after the swap. It is `floor(sqrt(token1Units / token0Units) * 2^96)`, with token0 the lower of the two token addresses.

* Selling token0 moves the price down, so the limit is a floor. Selling token1 moves it up, so the limit is a ceiling.
* It must lie strictly between `4295128739` and `1461446703485210103287273052203988822378723970342`, on the far side of the pool's current price, or the pool reverts with `SPL`.
* `0` means no limit, which leaves `minOut` as the only bound.
* The fee comes on top: under one limit, the last unit a 1% pool fills costs about 1% more than the limit.

`sauce price --chain base WETH USDC 2686.5 --offline` turns a price of 2,686.5 USDC per WETH into the limit for each direction without reading the chain; without `--offline` it also prints a live pool's current price. See [`sauce price`](https://docs.eco.com/sauce-sdk/cli/price).

The library has no quote function. A program can read a quote itself before it swaps, as [Quote, swap and supply](https://docs.eco.com/quickstarts/sauce/quote-swap-supply.md) does; from TypeScript, [`quoteAction`](https://docs.eco.com/sauce-sdk/typescript/actions#quoteaction) builds the `eth_call` that prices a swap.

## On Solana

On Solana a program calls a venue by its namespace, the venue's protocol then its program. Each namespace has `swap(pool, tokenIn, tokenOut, amountIn, priceLimit, minOut)` and `pool(tokenA, tokenB, key)`, which finds the venue's pool for the pair by its tick spacing or fee:

| Namespace | Pool key |
| - | - |
| `Raydium.CLMM` | fee in millionths |
| `Pancakeswap.CLMM` | fee in millionths |
| `Byreal.CLMM` | fee in millionths |
| `Stabble.CLMM` | fee in millionths |
| `Orca.Whirlpool` | tick spacing |
| `Cropper.Whirlpool` | tick spacing |
| `Defituna.Fusion` | tick spacing |
| `Crema.CLMM` | tick spacing |
| `Phoenix.Market` | none: the market's address, an `Address` parameter |

`Meteora.DLMM` has `swap(pool, tokenIn, tokenOut, amountIn, minOut)`, an exact input with no price limit, and its pool is named by address.

```ts orca-swap.solana.sauce.ts theme={null}
// Swaps `amountIn` USDC for WSOL at the first Orca whirlpool that trades, tick spacing 4 then 1,
// and pays the WSOL to `to`.
function main(to: Address, amountIn: Uint256, priceLimit: Uint256, minOut: Uint256): Uint256 {
  let got = 0;
  for (const spacing of [4, 1]) {
    if (got == 0) {
      got = Orca.Whirlpool.swap(Orca.Whirlpool.pool(USDC, WSOL, spacing), USDC, WSOL, amountIn, priceLimit, minOut);
    }
  }
  require(got > 0, "no Orca pool traded");
  WSOL.transfer(to, got);
  return got;
}
```

* **`swap` returns what arrived.** Where the pool cannot trade, or the venue has no pool at the key, it returns `0` having moved nothing. Below `minOut` the cook reverts.
* **`priceLimit`** is the most one unit bought may cost, fee included: input base units per output base unit, times 10^18. The function reads the pool's fee and gives the pool its own limit.
* **The key is written out**, as a number or a loop variable over numbers written out, because the pool's accounts are derived when the cook is built. Compiling adds the pool's nine accounts and the Pot's accounts to `main`.
* **What is bought lands in the Pot's own token account for `tokenOut`.** Forward it with the token methods, as `WSOL.transfer(to, got)` does.
* **A failed call into another program fails the whole Solana transaction** and cannot be caught, so each function checks before anything moves and returns `0` for a pool it cannot trade: no liquidity at its price, already past the limit, swaps paused, or an input too small to buy one unit after the fee.

`sauce pools --chain solana USDC WSOL` prints each pool's key, its price with its fee, and its price as a `priceLimit`. See [`sauce pools`](https://docs.eco.com/sauce-sdk/cli/pools).

### The venue functions by name

Each namespace call compiles to the venue's `@sauce/router` function, keeping every check: the venue's program, the pool's owner, the pair and `minOut`. A program or code generator can import those functions by name. The venues whose swap stops at a price limit (Raydium CLMM, PancakeSwap CLMM, Byreal, Stabble CLMM, Orca Whirlpools, Cropper, DefiTuna, Crema and Phoenix) have four forms each:

| Form | Takes | Returns |
| - | - | - |
| `<venue>`, at a price | `(slot, trader, amountIn, priceLimit, minOut, recipient)` | what the recipient received |
| `<venue>AtLimit`, at the pool's own limit | `(slot, trader, amountIn, limit, minOut, recipient)` | what the recipient received |
| `<venue>Cpi`, the instruction alone | `(program, accounts, source, amountIn, limit, …)` | what the paying account paid |
| `<venue>Data`, the instruction's data | `(amountIn, limit, …)` | the data, to send with `svm.call` |

The functions at a price are `raydiumClmm`, `pancakeswapClmm`, `byreal`, `stabbleClmm`, `orcaWhirlpool`, `cropper`, `defituna`, `crema` and `phoenix`:

```text theme={null}
orcaWhirlpool(slot: Account[], trader: Account[], amountIn, priceLimit, minOut, recipient: Account): Uint256
```

* **`slot`** is the pool's nine accounts, `[program, pool, config, vaultA, vaultB, extra, ticks0, ticks1, ticks2]`, with the System program for any the venue does not take. `sauce pools` prints each pool's slot for the direction paid.
* **`trader`** is `[authority, source, payMint, buyMint, tokenProgram, token2022, memo]`: the authority that signs (the Pot, through the Kitchen), the token account paid from, the two mints, the two token programs and the memo program.
* **`limit`**, in the `AtLimit`, `Cpi` and `Data` forms, is the pool's own: the sqrt price its swap takes, or an order book's price in its market's units. No fee is read for it.
* The eight concentrated-liquidity venues also have a `<venue>Stopped` form, the same swap with its limit held to a `stop` as well, which the `sauce` command compiles a swap to when it holds a pool short of its limit, skips it, or walks it on into its furthest tick array ([Swaps at a price and compute units](https://docs.eco.com/sauce-sdk/cli/solana.md#swaps-at-a-price-and-compute-units)). The stop's low 192 bits are a tighter price limit, bits 192 to 223 a start bound, and on Raydium's code and Crema bits 224 to 255 a deep tick: the last initialized tick of the furthest tick array the pool's accounts give, which the swap walks on to and checks in that array as it runs. A program no stop binds compiles to the plain function.

Invariant and OpenBook v2 have the `AtLimit`, `Cpi` and `Data` forms, and Manifest's book has `manifest`, `manifestCpi` and `manifestData`. The other venues (Raydium CP-Swap, Meteora DLMM and DAMM, and more) swap exactly `amountIn` with no price limit, as `<venue>(slot, trader, amountIn, minOut, recipient)`, `<venue>Cpi` and `<venue>Data`; the venue takes the whole input or the transaction fails. Some, such as PumpSwap, have only the `Cpi` and `Data` forms.

`@eco-incorp/sauce/svm` lists each venue's accounts and data in the order its instruction takes them, for a code generator that calls a venue itself: see [Solana from TypeScript](https://docs.eco.com/sauce-sdk/typescript/solana.md#venue-accounts-and-data).

## Next steps

* [@sauce/token](https://docs.eco.com/sauce-libraries/token.md): the token writes every swap uses.
* [Distributed swap](https://docs.eco.com/quickstarts/sauce/distributed-swap.md): one order spread over several EVM pools with these functions.
* [Distributed swap on Solana](https://docs.eco.com/quickstarts/sauce/solana-distributed-swap.md): the same over Solana pools.
* [Compiling programs](https://docs.eco.com/sauce-sdk/typescript/compiling.md#programs-that-import-a-library): compile a program that imports the library from TypeScript.
* [Pot](https://docs.eco.com/sauce/pot.md): the Pot and its Router.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.