Skip to main content
This guide explains how to bridge tokens across chains using the LI.FI API with Crossmint wallets. LI.FI aggregates bridges and DEXs to find optimal cross-chain routes.

Prerequisites

  • A Crossmint wallet with Base set as the default chain
  • A production API Key with the scope: wallets:transactions.create (create in the Production Console)
  • USDC on Base mainnet in the wallet
  • ETH on Base for gas fees (not required if gas sponsorship is enabled)

Bridge Tokens

High level steps to bridging tokens with LI.FI and Crossmint:
  1. Request a bridge quote from the LI.FI API
  2. Approve the LI.FI router to spend the source token
  3. Execute the bridge transaction using the quote calldata
  4. Poll the LI.FI status endpoint until the bridge completes
Cross-chain bridges operate on mainnet only. The wallet must hold sufficient tokens on the source chain and ETH for gas fees.
import { useWallet, EVMWallet } from "@crossmint/client-sdk-react-ui";
import { encodeFunctionData, erc20Abi, parseUnits } from "viem";

const LIFI_API = "https://li.quest/v1";
const FROM_CHAIN = "8453"; // Base
const TO_CHAIN = "137"; // Polygon
const FROM_TOKEN = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; // USDC on Base
const TO_TOKEN = "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"; // USDC on Polygon
const USDC_DECIMALS = 6;

export function BridgeComponent() {
    const { wallet } = useWallet();

    async function bridge(amount: string) {
        if(!wallet) return;
        const evmWallet = EVMWallet.from(wallet);

        // 1. Get a bridge quote from the LI.FI API
        const quoteRes = await fetch(
            `${LIFI_API}/quote?` +
                new URLSearchParams({
                    fromChain: FROM_CHAIN,
                    toChain: TO_CHAIN,
                    fromToken: FROM_TOKEN,
                    toToken: TO_TOKEN,
                    fromAmount: parseUnits(amount, USDC_DECIMALS).toString(),
                    fromAddress: wallet.address,
                    integrator: "crossmint",
                })
        );
        if (!quoteRes.ok) {
            throw new Error(`Quote request failed: ${quoteRes.status}`);
        }
        const quote = await quoteRes.json();

        // 2. Approve the LI.FI router to spend USDC
        if (quote.estimate.approvalAddress) {
            await evmWallet.sendTransaction({
                to: FROM_TOKEN,
                data: encodeFunctionData({
                    abi: erc20Abi,
                    functionName: "approve",
                    args: [
                        quote.estimate.approvalAddress,
                        parseUnits(amount, USDC_DECIMALS),
                    ],
                }),
            });
        }

        // 3. Execute the bridge transaction
        const tx = await evmWallet.sendTransaction({
            to: quote.transactionRequest.to,
            data: quote.transactionRequest.data,
            value: quote.transactionRequest.value
                ? BigInt(quote.transactionRequest.value)
                : 0n,
        });

        // 4. Poll the LI.FI status endpoint until completion
        let status = "PENDING";
        while (status === "PENDING" || status === "NOT_FOUND") {
            await new Promise((r) => setTimeout(r, 5000));
            const statusRes = await fetch(
                `${LIFI_API}/status?` +
                    new URLSearchParams({
                        txHash: tx.hash,
                        fromChain: FROM_CHAIN,
                        toChain: TO_CHAIN,
                    })
            );
            const s = await statusRes.json();
            status = s.status;
        }
    }

    return (
        <button onClick={() => bridge("5")}>Bridge Tokens</button>
    );
}
See the React SDK reference for more details.

Customizing the Bridge

You can bridge any token pair that LI.FI supports by changing the chain and token constants. You can also perform cross-chain swaps — changing both the asset and the chain in a single operation:
const FROM_CHAIN = "1"; // Ethereum
const TO_CHAIN = "42161"; // Arbitrum
const FROM_TOKEN =
    "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; // USDC on Ethereum
const TO_TOKEN =
    "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"; // USDC on Arbitrum
See the full list of supported chains and tokens in the LI.FI Documentation.

Troubleshooting

Verify the wallet holds enough USDC on Base and ETH for gas fees. Use the Check Balances guide to confirm token balances before bridging.
Ensure the approval amount is greater than or equal to the bridge amount. If a previous approval exists for a smaller amount, send a new approval transaction with the correct value. Verify the API key has the wallets:transactions.create scope.
Cross-chain bridges can take several minutes depending on the route and chain congestion. The LI.FI /status endpoint returns PENDING until both the source and destination chain transactions confirm. If the status does not change after 10 minutes, check the source transaction on a block explorer to verify it was included.

Next Steps