Build / Cross-chain Swaps and Bridging
Integrating the LI.FI SDK
The LI.FI SDK lets you add cross-chain and same-chain swaps and bridging directly inside your Somnia dApp. Instead of redirecting users to an external bridge, you request a route, execute it, and track its status. All from your own interface.
Under the hood, LI.FI aggregates dozens of bridges and DEX aggregators across 50+ chains, normalises token standards, and picks the optimal route. Your dApp only talks to one SDK.
In this guide, you'll learn how to:
- Install and configure the LI.FI SDK for Somnia
- Request a quote to bridge assets into Somnia
- Execute the route and track its status in your app
- Query supported chains, tokens, and tools to keep your UI accurate
Note
The LI.FI SDK is a JavaScript/TypeScript toolkit that runs in both front-end and back-end environments. This guide shows the front-end (browser wallet) flow. For the full API surface and the latest details, always refer to the official docs: https://docs.li.fi/sdk/overview.
Prerequisites
Before you start, ensure you have:
- A working JavaScript/TypeScript dApp (React or Next.js recommended). This guide assumes familiarity with both.
- Wallet connection already set up. If not, see Wallet Integration and Auth.
- Node.js 18+ and a package manager (npm, pnpm, or yarn).
- The Somnia network details on hand:
| Property | Value |
|---|---|
| Chain ID | 5031 |
| Native currency | SOMI (18 decimals) |
| RPC URL | https://api.infra.mainnet.somnia.network/ |
| Explorer | https://explorer.somnia.network |
Step 1: Install the SDK
The SDK uses Viem under the hood, so install it alongside.
npm install @lifi/sdk viem
Note
This guide was written and verified against
@lifi/sdkv3.16.x andviemv2.x. API surfaces evolve — if a signature differs in your version, the official SDK docs are the source of truth.
Step 2: Configure the SDK
Call createConfig once when your app boots. The integrator string identifies your app to LI.FI (and is used for fee monetisation later).
Because Somnia may not ship in Viem's default chain list, define it explicitly with defineChain so the SDK's wallet provider can switch to it.
lib/lifi.ts
import { createConfig, EVM, ChainId } from '@lifi/sdk';
import { createWalletClient, custom, defineChain } from 'viem';
import { mainnet, arbitrum, optimism, base } from 'viem/chains';
import { switchChain } from 'viem/actions';
// Somnia may be newer than the ChainId enum in your installed SDK version,
// so cast the numeric id where the SDK's TypeScript types expect a ChainId.
const SOMNIA = 5031 as ChainId;
// Define Somnia Mainnet for Viem
export const somnia = defineChain({
id: 5031,
name: 'Somnia',
nativeCurrency: { name: 'Somnia', symbol: 'SOMI', decimals: 18 },
rpcUrls: {
default: { http: ['https://api.infra.mainnet.somnia.network/'] },
},
blockExplorers: {
default: { name: 'Somnia Explorer', url: 'https://explorer.somnia.network' },
},
});
// Chains your dApp will let users move assets between
const chains = [mainnet, arbitrum, optimism, base, somnia];
// A Viem wallet client backed by the user's injected wallet (e.g. MetaMask)
const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum!),
});
createConfig({
integrator: 'YourSomniaDApp', // required; max 23 chars (letters, numbers, . - _)
rpcUrls: {
[SOMNIA]: ['https://api.infra.mainnet.somnia.network/'], // let the SDK use Somnia's RPC
},
providers: [
EVM({
getWalletClient: async () => walletClient,
switchChain: async (chainId) => {
await switchChain(walletClient, { id: chainId });
return walletClient;
},
}),
],
});
Tip
The SDK automatically fetches chain, bridge, and token metadata from LI.FI at runtime — you don't have to hard-code bridge addresses. The
defineChainblock is only needed so the wallet can switch networks during execution, andrpcUrlslets the SDK use your preferred Somnia endpoint. For production, pass an authenticated RPC URL rather than a public one.
Warning
TypeScript note: the SDK's types use a
ChainIdenum for parameters likerpcUrlskeys andgetTokens({ chains }). If your installed SDK version predates Somnia's addition to that enum, the raw number5031will fail to type-check — cast it with5031 as ChainId(shown above). The runtime value is unaffected; this is purely a type-level workaround.getQuote'sfromChain/toChainaccept a plainnumberand need no cast.
Step 3: Request a quote
A quote is a single, ready-to-execute route with the optimal pricing LI.FI could find. The example below bridges USDC on Arbitrum → USDC.e on Somnia (routed via Stargate at the time of writing).
Amounts are always passed as strings in the token's smallest unit (USDC has 6 decimals, so 10 USDC = "10000000"). A chain's native token is represented by the zero address.
Bridge USDC (Arbitrum) → USDC.e (Somnia)
import { getQuote } from '@lifi/sdk';
const quote = await getQuote({
fromChain: 42161, // Arbitrum
toChain: 5031, // Somnia
fromToken: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
toToken: '0x28BEc7E30E6faee657a03e19Bf1128AaD7632A00', // USDC.e (bridged USDC) on Somnia
fromAmount: '10000000', // 10 USDC (6 decimals)
fromAddress: userWalletAddress, // the connected wallet
});
console.log(quote.estimate.toAmount); // estimated USDC.e received (6 decimals)
Tokens routable to Somnia
These are the tokens LI.FI can currently route to Somnia (Chain ID 5031):
| Symbol | Address | Decimals | Notes |
|---|---|---|---|
| SOMI | 0x0000000000000000000000000000000000000000 |
18 | Native gas token |
| WSOMI | 0x046EDe9564A72571df6F5e44d0405360c0f4dCab |
18 | Wrapped SOMI |
| USDC.e | 0x28BEc7E30E6faee657a03e19Bf1128AaD7632A00 |
6 | Bridged USDC (Stargate) |
| USDT | 0x67B302E35Aef5EEE8c32D934F5856869EF428330 |
6 | Bridged USDT (Stargate) |
| WETH | 0x936Ab8C674bcb567CD5dEB85D8A216494704E9D8 |
18 | Wrapped ETH |
Warning
This list reflects LI.FI's coverage at the time of writing and grows over time. Always fetch the current set with
getTokensat runtime rather than hard-coding it (see Step 6).
Step 4: Execute the route
A quote must first be converted to a route with convertQuoteToRoute, then passed to executeRoute. The SDK handles token approvals, network switching, and signing through the wallet provider you configured in Step 2. Use updateRouteHook to react to progress in your UI.
import { convertQuoteToRoute, executeRoute } from '@lifi/sdk';
// A quote cannot be executed directly — convert it to a route first
const route = convertQuoteToRoute(quote);
const executedRoute = await executeRoute(route, {
updateRouteHook: (updatedRoute) => {
// Called whenever the route changes during execution — drive your progress UI from here
updatedRoute.steps.forEach((step, i) => {
step.execution?.process.forEach((process) => {
console.log(`Step ${i + 1}:`, process.type, process.status);
if (process.txHash) console.log(' tx hash:', process.txHash);
});
});
},
});
Note
executeRoutealso accepts other hooks such asacceptExchangeRateUpdateHook(confirm a changed rate before continuing) andswitchChainHook. See the official Execute Routes guide for the full list.
Step 5: Handle the outcome
Status updates arrive through the updateRouteHook from Step 4, read each step's execution.status and execution.process to drive your UI. Cross-chain transfers don't always end in an exact 1:1 result, so handle the final states explicitly:
| Final state | Meaning | What to show the user |
|---|---|---|
| Completed | Success, exact destination token received | "Funds arrived on Somnia" |
| Partial | Success, but a different token was received (still full value) | "Completed, received an alternate token" |
| Refunded | The transfer failed and funds were returned | "Refunded on the source chain" |
| Failed | Execution failed | Prompt the user to retry or contact support |
Note
A same-chain swap is atomic: it either fully succeeds or reverts. A cross-chain transfer can have the bridge succeed while the destination step fails, in that case the bridged asset is refunded on the destination chain.
To resume tracking an interrupted transfer (for example, after a page reload), the SDK can pick up an in-progress route again. See the official Execute Routes guide. For server-side or out-of-band status checks, query the REST status endpoint directly.
Step 6: Keep your UI in sync
Use the SDK's query helpers to populate dropdowns and verify that Somnia routes and tokens are live before showing them to users.
import { ChainId, ChainType, getChains, getTokens, getTools } from '@lifi/sdk';
// Confirm Somnia (5031) is currently supported
const chains = await getChains({ chainTypes: [ChainType.EVM] });
const somniaSupported = chains.some((c) => c.id === 5031);
// Tokens available on Somnia — getTokens returns a map keyed by chain ID
// (cast 5031 to ChainId if your SDK version predates Somnia in the enum)
const { tokens } = await getTokens({ chains: [5031 as ChainId] });
const somniaTokens = tokens[5031] ?? [];
// Available bridges and exchanges
const { bridges, exchanges } = await getTools();
Warning
Somnia support on LI.FI is live and expanding. Treat
getChainsandgetTokensas the source of truth at runtime rather than hard-coding lists, new tokens and bridges are added regularly.
Monetization (optional)
Integrators can charge a fee on transactions routed through their app. Configure a fee when requesting a route and withdraw collected fees via LI.FI's Partner Portal.
See the official guide for the current setup: https://docs.li.fi/sdk/monetize-sdk.
Troubleshooting
- No route found: Try a different token pair or a larger amount. Very small amounts may not cover bridge/gas costs.
- Slippage / minimum-received error: Increase the
slippageparameter (default0.005= 0.5%) when requesting the quote. - Rate limited (
429): Without an API key you're limited to 200 requests / 2 hours. Request a key for production and back off with retries. - Insufficient balance: Ensure the user holds enough of the source token plus native gas on the source chain.
- Network switch fails: Confirm Somnia (
5031) is added to the user's wallet. See Connect Your Wallet to Mainnet.
Need Help?
- LI.FI SDK docs (source of truth): https://docs.li.fi/sdk/overview
- Somnia Discord: https://discord.gg/somnia
- Somnia Developer Telegram: https://t.me/+s_oRMnGpOyQ3ODQ0
Disclaimers
- LI.FI is a third-party provider. Always integrate from the official packages (
@lifi/sdk) and verify chain/token data against the live API. - Bridging and swapping involve smart-contract and market risk. Test thoroughly on a small amount before enabling production flows.
Copied from docs.somnia.network (somnia-main-docs) by scripts/import-gitbook.mts, until it finds a home in a product's docs.Edit this page