@awarizon/swap
Multichain and cross-chain swaps behind one API. Every capable provider is queried in parallel and quotes come back sorted by output amount. Try it live on the swap demo.
Same-chain EVM0x Swap API v2 + LI.FISWAPSame-chain SolanaJupiter + LI.FISWAPCross-chainEVM ↔ EVM, EVM ↔ Solana via LI.FIBRIDGEExecuting swaps that start on Solana also needs @solana/web3.js (an optional peer dependency, loaded only when used).
new SwapClient(config)
import { SwapClient } from "@awarizon/swap" export const swap = new SwapClient({ integrator: "my-app", // LI.FI integrator id zeroEx: { baseUrl: "/api/swap/0x" }, // your proxy — keeps the 0x key server-side lifi: { baseUrl: "/api/swap/lifi" }, jupiter: { baseUrl: "/api/swap/jupiter" }, })
assetListUrlstring | string[]Hosted token list URL(s), tried in order. Defaults to the Awarizon list on jsDelivr.assetListSwapListInline list — skips fetching (tests, SSR).integratorstringLabel sent to LI.FI; needed for fee collection.fee{ bps, evmRecipient?, solanaFeeAccount? }Integrator fee in basis points for 0x and Jupiter routes.zeroEx{ apiKey?, baseUrl? }0x is skipped unless one of these is set.lifi{ apiKey?, baseUrl? }Optional key for higher rate limits.jupiter{ apiKey?, baseUrl? }Uses lite-api without a key.rpcUrlsRecord<number, string>Override RPCs per chain id (recommended for Solana: 501000101).defaultSlippageBpsnumberDefault 50 (0.5%).getQuotes(request)
Tokens can be symbols from the list or any address. Amounts are in base units. fromAddress is optional — without it you get indicative previews.
const { best, quotes, errors } = await swap.getQuotes({ fromChainId: 8453, // Base toChainId: 501000101, // Solana fromToken: "USDC", toToken: "SOL", amount: "25000000", // 25 USDC (6 decimals) fromAddress: "0x…", toAddress: "7xKX…", // required when chain types differ slippageBps: 50, }) best.toAmount // base units of SOL best.toAmountMin // after slippage best.steps // [{ type: "bridge", tool: "Mayan (Swift)", … }] best.estimatedDurationSec
execute(quote, signers)
Switches the wallet to the right chain (adding it if needed), approves the token when required, signs, submits, waits for confirmation and — for cross-chain routes — tracks the bridge until funds arrive.
import { evmSignerFromEip1193 } from "@awarizon/swap" const result = await swap.execute(best, { evm: evmSignerFromEip1193(window.ethereum), solana: window.phantom?.solana, // any wallet-adapter-shaped wallet }, { approval: "exact", // or "infinite" onUpdate: (u) => console.log(u.stage, u.message, u.txLink), }) // preparing → switching-chain → approving → signing → submitted → confirming → bridging → done
Using wagmi? Wrap its wallet client with evmSignerFromViem(walletClient).
Server proxy
Keep aggregator keys off the client. The proxy forwards only the quote, swap, status and token endpoints, so it can’t be used as an open relay.
import { createSwapProxy } from "@awarizon/swap/server" const proxy = createSwapProxy({ basePath: "/api/swap", zeroExApiKey: process.env.ZEROX_API_KEY, lifiApiKey: process.env.LIFI_API_KEY, jupiterApiKey: process.env.JUPITER_API_KEY, }) export const GET = proxy export const POST = proxy
Tokens & chains
await swap.assets.load() swap.assets.chains() // enabled mainnet chains swap.assets.tokens(8453) // listed + user-imported tokens await swap.assets.search("usdc", 8453) // symbol / name, or a pasted address await swap.assets.resolveToken(8453, "0x…") // list → imports → on-chain lookup
Chain ids are EVM chain ids; Solana is 501000101. Provider-specific ids (e.g. LI.FI’s Solana id) are mapped for you by the token list.