Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.o1.exchange/llms.txt

Use this file to discover all available pages before exploring further.

The O1Router handles all wrapping and unwrapping internally. From the API caller’s perspective there are two flags:
FlagWhereWhat it does
useNativeIn/submit (and /execute)When true, send msg.value = amountIn and the router wraps to WETH before dispatching legs.
unwrapNativeOut/submit (and /execute)When true, the router unwraps WETH to ETH for the recipient before completing the swap.

Sentinel addresses for native ETH

When you want to swap native ETH in tokenIn or tokenOut, use one of these sentinels:
SentinelNotes
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeEStandard EIP-7528 native sentinel. Recommended.
0x0000000000000000000000000000000000000000Zero-address fallback, also accepted.
The aggregator detects either form and sets routePlan.nativeIn or routePlan.nativeOut to true automatically. You still need to set the corresponding flag on /submit or /execute, since the user might have changed their mind about wrapping between quote and submit.

The four common cases

Sell native ETH, receive an ERC-20 like USDC.Quote:
{
  "tokenIn": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
  "tokenOut": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
  "amountIn": "1000000000000000000",
  "slippageBps": 100,
  "chainId": 8453
}
Submit:
{
  "quoteId": "...",
  "user": "0x...",
  "useNativeIn": true
}
Send transaction: the response value will equal amountIn (1000000000000000000).
await walletClient.sendTransaction({
  to: submit.to,
  data: submit.data,
  value: BigInt(submit.value), // = 1 ETH
});
Approval: none needed.

Common mistakes

Forgot useNativeIn

/submit response has value: "0" even though tokenIn was the native sentinel. Cause: you didn’t set useNativeIn: true on /submit. The API errs on the side of safety and assumes you might have changed your mind.

Sending msg.value with an ERC-20 swap

The router rejects any non-zero msg.value when useNativeIn is false. If your wallet is sending ETH along, double-check you didn’t carry over value from a previous swap.

Approving WETH unnecessarily

For an ETH → ERC-20 swap with useNativeIn: true, the user does not need to approve WETH. The router handles the wrap from msg.value and the resulting WETH never leaves the router contract.

Missing unwrapNativeOut

User receives WETH instead of ETH because unwrapNativeOut was omitted on /submit. Always set it explicitly when you want native ETH back.

Why both quote and submit need the flag

The aggregator detects native intent on /quote from the sentinel and sets routePlan.nativeIn / routePlan.nativeOut. But /submit requires you to re-confirm with the explicit flag because:
  1. The quoteId is independent of the user. The same quote can be submitted by different users with different preferences.
  2. Some integrators want to auto-wrap on the user’s behalf, e.g. always pull ERC-20 WETH from the user even when the quote was for native ETH.
Always pass useNativeIn / unwrapNativeOut explicitly on /submit to remove ambiguity.