> ## 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.

# swap: Types

> Types: 17 exports of the swap module of @eco-incorp/sauce, including SwapPoolType, UndispatchablePoolType, ZERO_POOL_KEY, SWAP_PARAMS_FIELDS, POOL_KEY_FIELDS, isCallbackVenue.

The `swap` namespace emits a complete `function main() { ... }` program with one `ISauceRouter.swap(...)` statement per spec. Compile with `baseDirs: [...swap.SWAP_BASE_DIRS]`.

```typescript theme={null}
import { swap } from "@eco-incorp/sauce";
```

This page covers `sdk/dist/swap/types.d.ts`.

<Note>
  Generated from the type declarations shipped in `@eco-incorp/sauce` 0.99.4. Each entry shows the package authors' JSDoc and declaration for this SDK version. For runtime compatibility and deployed addresses, see [architecture and deployments](/programmable-transactions/sauce/architecture-and-deployments).
</Note>

### `swap.SwapPoolType`

*Variable, Type* · `sdk/dist/swap/types.d.ts`

`SwapPoolType` - pinned verbatim from the engine's `IRouter.sol` `enum SwapPoolType`, whose own
doc says values are APPEND-ONLY (the enum rides `SwapParams.poolType` as `uint8`, so reordering
breaks the ABI of every compiled recipe). Only 0..8 are dispatchable through the unified
`swap()` entry point - see `UndispatchablePoolType` for 9/10.

```typescript theme={null}
SwapPoolType: {
    readonly UniV2: 0;
    readonly UniV3: 1;
    readonly UniV4: 2;
    readonly Curve: 3;
    readonly BalancerV2: 4;
    readonly DODOV2: 5;
    readonly TraderJoeLB: 6;
    readonly MaverickV2: 7;
    readonly WOOFi: 8;
}
export type SwapPoolType = (typeof SwapPoolType)[keyof typeof SwapPoolType];
```

### `swap.UndispatchablePoolType`

*Variable, Type* · `sdk/dist/swap/types.d.ts`

Pool types that exist on the engine's `SwapPoolType` enum but are NOT dispatchable through the
unified `swap()` - `Router.sol`'s `swap()` dispatch chain covers only 0..8 and falls through to
`revert SwapFailed()` for anything else. PancakeInfinity's CL/Bin pools need their own
`swapInfinityCL`/`swapInfinityBin` entry points (a different, 6-field `InfinityPoolKey` that
`SwapParams` cannot carry) - out of scope for this first cut. Exported so the value is nameable;
`toSwapParams` throws when handed one of these, pointing at this follow-up.

```typescript theme={null}
UndispatchablePoolType: {
    readonly PancakeInfinityCL: 9;
    readonly PancakeInfinityBin: 10;
}
export type UndispatchablePoolType = (typeof UndispatchablePoolType)[keyof typeof UndispatchablePoolType];
```

### `swap.ZERO_POOL_KEY`

*Variable* · `sdk/dist/swap/types.d.ts`

All-zero `poolKey`, used for any pool type that doesn't consult it (see `usesPoolKey`).

```typescript theme={null}
ZERO_POOL_KEY: PoolKey
```

### `swap.SWAP_PARAMS_FIELDS`

*Variable* · `sdk/dist/swap/types.d.ts`

`SwapParams`'s top-level field names, in exact ABI-declaration order (pinned against the
vendored `ISauceRouter.json` artifact in `sdk/test/swap.test.ts`).

```typescript theme={null}
SWAP_PARAMS_FIELDS: readonly (keyof SwapParams)[]
```

### `swap.POOL_KEY_FIELDS`

*Variable* · `sdk/dist/swap/types.d.ts`

`SwapParams.poolKey`'s field names, in exact ABI-declaration order.

```typescript theme={null}
POOL_KEY_FIELDS: readonly (keyof PoolKey)[]
```

### `swap.isCallbackVenue`

*Function* · `sdk/dist/swap/types.d.ts`

True for the three pool types `Router.sol` (`~279-283`) allows a non-empty `callback` for - the
pool re-enters the contract mid-swap to pull input, so servicing it requires the router's
compiled code. NOT the same partition as `isCallbackFree`: MaverickV2 is callback-driven
yet its handler still takes `abs(amountSpecified)` (see `amountSpecifiedFor`).

```typescript theme={null}
export declare function isCallbackVenue(poolType: SwapPoolType): boolean;
```

### `swap.isCallbackFree`

*Function* · `sdk/dist/swap/types.d.ts`

True for the pool types whose swap logic is callback-free (`Router.sol` reads reserves / calls a
plain `pool.swap(...)`) and so MAY, as a follow-up, be replicated as direct
`transfer` + `pool.swap` SauceScript instead of going through the Router. This module always
routes through the unified `swap()` regardless - see `sdk/src/swap/index.ts`'s scope notes.

```typescript theme={null}
export declare function isCallbackFree(poolType: SwapPoolType): boolean;
```

### `swap.usesPoolKey`

*Function* · `sdk/dist/swap/types.d.ts`

True for the pool types where `SwapParams.poolKey` is actually consulted by the engine:
UniV4 (all 5 fields, via `V4SwapParams`) and, less obviously, UniV2 (`Router.sol#_swapV2` reads
`poolKey.fee` as the pair's LP fee in ppm - `0` defaults to 3000 / 0.30%, `>= 1_000_000` reverts).
Every other pool type ignores `poolKey` entirely.

```typescript theme={null}
export declare function usesPoolKey(poolType: SwapPoolType): boolean;
```

### `swap.Address`

*Type* · `sdk/dist/swap/types.d.ts`

A 20-byte EVM address, as an ordinary `0x`-prefixed hex string.

```typescript theme={null}
export type Address = `0x${string}`;
```

### `swap.Hex`

*Type* · `sdk/dist/swap/types.d.ts`

A `0x`-prefixed hex byte string (used for `SwapParams.callback`).

```typescript theme={null}
export type Hex = `0x${string}`;
```

### `swap.AddressInput`

*Type* · `sdk/dist/swap/types.d.ts`

Anything `toSwapParams` accepts for an address-shaped field.

```typescript theme={null}
export type AddressInput = Address | bigint;
```

### `swap.AmountInput`

*Type* · `sdk/dist/swap/types.d.ts`

Anything `toSwapParams` accepts for a numeric-shaped field.

```typescript theme={null}
export type AmountInput = bigint | number | string;
```

### `swap.PoolKey`

*Interface* · `sdk/dist/swap/types.d.ts`

`SwapParams.poolKey`, fully normalized - 5 bigint fields, in ABI-declaration order.

```typescript theme={null}
export interface PoolKey {
    currency0: bigint;
    currency1: bigint;
    fee: bigint;
    tickSpacing: bigint;
    hooks: bigint;
}
```

### `swap.PoolKeyInput`

*Interface* · `sdk/dist/swap/types.d.ts`

`SwapParams.poolKey` as the caller may supply it - every field optional; unset fields default to
`0n` (see `toSwapParams`'s per-pool-type rules for which defaults are actually meaningful).

```typescript theme={null}
export interface PoolKeyInput {
    currency0?: AddressInput;
    currency1?: AddressInput;
    fee?: AmountInput;
    tickSpacing?: AmountInput;
    hooks?: AddressInput;
}
```

### `swap.SwapSpec`

*Interface* · `sdk/dist/swap/types.d.ts`

The chain-agnostic swap SPEC a caller builds - the input to `toSwapParams` /
`swapCallStatement` / `swapSource`. `amountIn` is always a single, unambiguous POSITIVE
exact-input amount; `amountSpecifiedFor` does the per-path sign normalization.

`payer`/`recipient` default to the SauceScript call `ctx.self()` (Router swap entries are
`onlySelf`) - leave them unset unless you specifically need a different payer/recipient (which
then disqualifies a non-empty `callback`, see `toSwapParams`'s guard).

```typescript theme={null}
export interface SwapSpec {
    poolType: SwapPoolType;
    pool: AddressInput;
    poolKey?: PoolKeyInput;
    tokenIn: AddressInput;
    tokenOut: AddressInput;
    amountIn: AmountInput;
    sqrtPriceLimitX96?: AmountInput;
    payer?: AddressInput;
    recipient?: AddressInput;
    callback?: Hex;
}
```

### `swap.SwapSourceSpec`

*Type* · `sdk/dist/swap/types.d.ts`

The one extra shape `swapCallStatement`/`swapSource` accept beyond `SwapSpec`:
`amountIn: "balance"` emits a RUNTIME `IERC20.at(tokenIn).balanceOf(ctx.self())` read instead
of a baked-in literal - the shape a multi-leg program needs when a later leg's input is an
earlier leg's (unknown at compile time) output. `toSwapParams` does NOT accept this shape: it
produces a concrete `SwapParams` object, which a runtime-derived amount cannot be.

```typescript theme={null}
export type SwapSourceSpec = SwapSpec | (Omit<SwapSpec, "amountIn"> & {
    amountIn: "balance";
});
```

### `swap.SwapParams`

*Interface* · `sdk/dist/swap/types.d.ts`

`ISauceRouter.swap`'s `SwapParams`, fully normalized - every scalar a `bigint` (SauceScript- and
viem-native), in exact ABI-declaration order (see `SWAP_PARAMS_FIELDS`, pinned against the
vendored artifact in `sdk/test/swap.test.ts`). `payer`/`recipient` are `bigint | "self"`: `"self"`
is the unresolved `ctx.self()` sentinel (this contract's own address, not knowable off-chain
without the Pot address), preserved rather than eagerly resolved so a caller can tell the two
cases apart.

**Sign note (load-bearing, do not "fix" from the struct doc comment):** `IRouter.sol`'s own
`SwapParams.amountSpecified` comment claims "Negative = exact input, Positive = exact output"
universally. That is wrong for UniV3 - `Router.sol:431` passes it straight into Uniswap V3's
pool, whose OWN convention is positive = exact input (fork-verified; see this repo's CLAUDE.md).
`amountSpecifiedFor` follows the CODE, not the comment.

```typescript theme={null}
export interface SwapParams {
    poolType: SwapPoolType;
    pool: bigint;
    poolKey: PoolKey;
    tokenIn: bigint;
    tokenOut: bigint;
    amountSpecified: bigint;
    sqrtPriceLimitX96: bigint;
    payer: bigint | "self";
    recipient: bigint | "self";
    callback: Hex;
}
```
