Skip to main content
Amounts are generally one of:
  • string — human-readable, e.g. "50" or "0.03". Scaled by the token’s decimals.
  • bigint — raw wei, used as-is.
  • dynamic() — “use the intent wallet’s runtime balance at execution time”, accepted only on fields that spend a balance. See Dynamic Values.

swap — on-chain token swap

Trade type is inferred from which amount you pass: amountInEXACT_INPUT, amountOutEXACT_OUTPUT. Setting both (or neither) throws. dynamic() is allowed on amountIn for exact-input swaps and maxAmountIn for exact-output swaps. amountOut and minAmountOut must be concrete values because they are execution thresholds.
Defaults:
  • fee: "0.3" (0.3% pool).
  • provider: "UNISWAP_V3". If it isn’t deployed on the destination chain, the error tells you to try SushiSwap.
  • recipient: the intent wallet for the final action; for intermediate actions, output flows back so the next action can consume it. Override only if you want to send output to a third party.

Swap utilities

For anything that isn’t “build calldata for useQuote” — on-chain quoting, pool discovery, raw Call[] composition, address lookups — 0xtrails exports the underlying chain-scoped helpers behind swap. The same adapter shape is exported for both Uniswap V3 and SushiSwap V3: quoteSwap, getPool, swapExactInputSingle, and swapExactOutputSingle.
Low-level helpers take raw bigint wei — use viem’s parseUnits to convert from human-readable amounts. Fee tiers take human strings: "0.01" / "0.05" / "0.3" / "1".
Typical use cases:
  • Pre-flight quoting — render expected output / price impact in the UI before the user commits, using quoteSwap.
  • Pool liquidity check — skip a pair or switch fee tier when getPool returns null.
  • Custom compositions — build Call[] directly and pass them through to.calls (useQuote) or calls (useTrailsSendTransaction) when you need something the typed swap doesn’t cover (e.g. multi-hop paths, permit2, …).

Chain-scoped adapter

uniswapV3.onChain(chain) (or sushiswapV3.onChain(chain)) returns an adapter bound to a specific chain (name or chain ID):

quoteSwap

Query the provider’s V3 quoter — no signing, no broadcast. Use this to render expected output, gas estimate, and price movement before the user commits.
type can be "exactInputSingle" or "exactOutputSingle". Pass amountIn for exact input quotes. For exact output quotes, pass the desired output amount as amountOutMinimum:

getPool

Find the pool address for a pair and fee tier. Returns null when no pool exists — handy for switching fee tier or skipping the pair.

swapExactInputSingle

Build an approval + swap Call[] for an exact-input swap. Pass the calls through to.calls / calls to embed inside an intent, or send them directly from a wallet.
SushiSwap V3 uses the same fields plus a required deadline:

swapExactOutputSingle

Build an approval + swap Call[] for an exact-output swap.
For SushiSwap V3 exact-output calls, include deadline as well.

Address lookups

Top-level helpers return contract addresses per chain:

Capability checks

Not every chain has both providers deployed. isSupportedOn returns false instead of throwing — useful for falling back between providers or warning the user.

lend — supply into a money-market

Use for supported lending markets such as Aave. Use useEarnMarkets to fetch the marketId.
Optional: receiverAddress defaults to the connected user wallet, so aTokens / fTokens / cTokens land on the user’s EOA automatically. Only override when you want the position to belong to a different owner.

deposit — deposit into a vault

Use for vault-shaped markets (ERC-4626, Morpho, Yearn, SummerFi, Sky, …).
Optional params:
  • receiverAddressdefaults to the connected user wallet so vault shares land on the user’s EOA.

assertCondition — on-chain guard

If the condition is false at execution time the entire batch reverts.
assertCondition is the only builder that does not accept dynamic() — its values must be known at quote time.

custom — arbitrary contract call (escape hatch)

Use when nothing above fits. Pair with buildCall and erc20Utils for ergonomic calldata — see ERC-20 Helpers.
If custom calldata contains a dynamic() amount, pass dynamicAmountToken so the encoder knows which ERC-20 balance to hydrate at execution time. The only exception is a bare ERC-20 approve(spender, dynamic()), where the token is inferred from the call target.