Skip to main content

Scenario

A user holds 1,000 USDT on Ethereum and wants Aave USDC (aEthUSDC). No single routing edge turns USDT into aEthUSDC, so the route takes two hops: swap USDT to USDC, then deposit the USDC into Aave. sdk.route (POST /compose/route) plans those hops for you. You pass the token pair, an amount and a signer; the server builds the route, compiles it and returns the same ComposeCompileResult as builder.compile(). It plans up to two hops on one chain, and a lifi.swap can only be the first hop. The other hops are lifi.zap catalog edges: a protocol deposit or withdrawal, a wrap or unwrap. For a longer route, a route you choose yourself, or guards on intermediate outputs, author a Flow as in Swap and deposit.

Full example

Install the SDK and viem with npm install @lifi/composer-sdk @lifi/compose-spec viem and set LIFI_API_KEY; see Before you start. The example also signs with a private key: set PRIVATE_KEY on your server and never ship it to a browser.

Run it

Save the file as server-planned-route.mts and run node server-planned-route.mts.
It sends real transactions on Ethereum: the USDT approval (unless the allowance already covers it), then execute, in result.actions order.

What to check

  • The node ids follow a fixed pattern: hop0, hop1, … and a last node named zap. The server does not return the Flow it built.
  • outputs['hop0.amountOut'] is the swap’s USDC, with role: 'consumed' and consumedBy: 'zap'. Its floor comes from the swap quote.
  • outputs['zap.amountOut'] is the aEthUSDC the signer receives: role: 'terminal', delivery: { when: 'now' }. amount.estimate is simulated; amount.minimum (basis: 'guard') is 1% below it. Read this key at any route length.
  • epilogue.remainder is the sweepTo address, which receives any leftover USDT or USDC.
  • The execute transaction is atomic: if the aEthUSDC would fall below the floor, it reverts and the USDT stays with the signer.

Request fields

The SDK serialises bigint amounts to decimal strings on the wire. sdk.route(request) lists the TypeScript types. To check which pairs the catalog connects before calling the server, pass await sdk.client.getZapPacks() to buildReachability. It does not report swap-headed routes, so USDT to aEthUSDC shows as unreachable there; see the SDK reference.

Errors

  • no_route_error (HTTP 404, SDK code NOT_FOUND): no route within the hop limit. The details carry maxHops and searchTruncated. A plain token-to-token swap, such as USDC to UNI, fails this way: use lifi.swap.
  • validation_error (HTTP 400) “sweepTo is required”: the pair needs a swap and the request has no sweepTo.
For other failures, see Error codes.