Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.li.fi/llms.txt

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

Overview

LI.FI SDK v4 introduces a client-based architecture that provides better type safety, improved modularity, and clearer separation of concerns. The SDK now uses a client instance pattern instead of global configuration, making it easier to manage multiple SDK instances and improving testability. To get started, install the latest version of LI.FI SDK.
yarn add @lifi/sdk

Configuration

The most significant change in v4 is the move from a global configuration pattern to a client-based architecture. Instead of calling createConfig() and using global functions, you now create a client instance and pass it to all SDK functions.

Before (v3)

// SDK v3
import { createConfig, getQuote, ChainId } from '@lifi/sdk';

createConfig({
  integrator: 'Your dApp/company name',
});

const quote = await getQuote({
  fromAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  fromChain: ChainId.ARB,
  toChain: ChainId.OPT,
  fromToken: '0x0000000000000000000000000000000000000000',
  toToken: '0x0000000000000000000000000000000000000000',
  fromAmount: '1000000000000000000',
});

After (v4)

// SDK v4
import { createClient, getQuote, ChainId } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

const quote = await getQuote(client, {
  fromAddress: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045',
  fromChain: ChainId.ARB,
  toChain: ChainId.OPT,
  fromToken: '0x0000000000000000000000000000000000000000',
  toToken: '0x0000000000000000000000000000000000000000',
  fromAmount: '1000000000000000000',
});

Function Signatures

All SDK action functions now require the client as the first parameter. This includes:
  • getRoutes(client, {...})
  • getQuote(client, {...})
  • getContractCallsQuote(client, {...})
  • getChains(client, {...})
  • getTools(client, {...})
  • getConnections(client, {...})
  • getTokens(client, {...})
  • getToken(client, chain, token)
  • getTokenBalance(client, walletAddress, token)
  • getTokenBalances(client, walletAddress, tokens)
  • getTokenBalancesByChain(client, walletAddress, tokensByChain)
  • getWalletBalances(client, walletAddress)
  • getStatus(client, {...})
  • getStepTransaction(client, step)
  • executeRoute(client, route, options)
  • resumeRoute(client, route, options)
  • getGasRecommendation(client, {...})
  • getTransactionHistory(client, {...})
  • getNameServiceAddress(client, name, chainType?)
  • getRelayerQuote(client, {...})
  • relayTransaction(client, {...})
  • getRelayedTransactionStatus(client, {...})
  • patchContractCalls(client, {...})

Example Migration

Before (v3)

// SDK v3
import { getRoutes, executeRoute } from '@lifi/sdk';

const result = await getRoutes({
  fromChainId: 42161,
  toChainId: 10,
  fromTokenAddress: '0x...',
  toTokenAddress: '0x...',
  fromAmount: '10000000',
});

const executedRoute = await executeRoute(result.routes[0], {
  updateRouteHook(route) {
    console.log(route);
  },
});

After (v4)

// SDK v4
import { createClient, getRoutes, executeRoute } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

const result = await getRoutes(client, {
  fromChainId: 42161,
  toChainId: 10,
  fromTokenAddress: '0x...',
  toTokenAddress: '0x...',
  fromAmount: '10000000',
});

const executedRoute = await executeRoute(client, result.routes[0], {
  updateRouteHook(route) {
    console.log(route);
  },
});

Provider Packages

In v4, ecosystem providers have been moved to separate packages for better modularity and tree-shaking. You need to install the provider packages separately and import providers from their respective packages.

Install Provider Packages

yarn add @lifi/sdk-provider-ethereum @lifi/sdk-provider-solana @lifi/sdk-provider-bitcoin @lifi/sdk-provider-sui @lifi/sdk-provider-tron
Only install the provider packages for the ecosystems you need. For example, if you only support EVM chains, you only need @lifi/sdk-provider-ethereum.

Provider Configuration

Before (v3)

// SDK v3
import { createConfig, EVM, Solana } from '@lifi/sdk';

createConfig({
  integrator: 'Your dApp/company name',
  providers: [
    EVM({
      getWalletClient: () => Promise.resolve(walletClient),
    }),
    Solana({
      getWalletAdapter: () => Promise.resolve(walletAdapter),
    }),
  ],
});

After (v4)

// SDK v4
import { createClient } from '@lifi/sdk';
import { EthereumProvider } from '@lifi/sdk-provider-ethereum';
import { SolanaProvider } from '@lifi/sdk-provider-solana';

const client = createClient({
  integrator: 'Your dApp/company name',
});

client.setProviders([
  EthereumProvider({
    getWalletClient: () => Promise.resolve(walletClient),
  }),
  SolanaProvider({
    getWallet: () => Promise.resolve(wallet), // wallet-standard Wallet
  }),
]);

Provider Names

Provider factory names have been updated to be more descriptive:
  • EVMEthereumProvider (from @lifi/sdk-provider-ethereum)
  • SolanaSolanaProvider (from @lifi/sdk-provider-solana)
  • UTXOBitcoinProvider (from @lifi/sdk-provider-bitcoin)
  • SuiSuiProvider (from @lifi/sdk-provider-sui)
  • New: TronProvider (from @lifi/sdk-provider-tron) — adds Tron ecosystem support

Solana Provider: getWalletAdaptergetWallet

The Solana provider now uses @solana/kit and the Wallet Standard instead of @solana/web3.js and the legacy wallet adapter.

Before (v3)

// SDK v3
import { Solana } from '@lifi/sdk';

Solana({
  getWalletAdapter: () => Promise.resolve(walletAdapter),
});

After (v4)

// SDK v4
import { SolanaProvider } from '@lifi/sdk-provider-solana';

SolanaProvider({
  getWallet: () => Promise.resolve(wallet), // wallet-standard Wallet
});

Sui Provider: getWalletgetClient + getSigner

The Sui provider now uses @mysten/sui v2 and requires a ClientWithCoreApi and a Signer instead of a wallet object.

Before (v3)

// SDK v3
import { Sui } from '@lifi/sdk';

Sui({
  getWallet: () => Promise.resolve(wallet),
});

After (v4)

// SDK v4
import { SuiProvider } from '@lifi/sdk-provider-sui';

SuiProvider({
  getClient: () => Promise.resolve(suiClient),
  getSigner: () => Promise.resolve(signer),
});

Configuration Management

Before (v3)

// SDK v3
import { config } from '@lifi/sdk';

// Update configuration
config.set({
  integrator: 'Updated name',
});

// Set providers
config.setProviders([...]);

// Get chains
const chains = await config.getChains();

After (v4)

// SDK v4
import { createClient } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

// Access configuration (read-only)
console.log(client.config.integrator);

// Set providers
client.setProviders([...]);

// Get chains
const chains = await client.getChains();

// Get specific chain
const chain = await client.getChainById(1);

// Get RPC URLs
const rpcUrls = await client.getRpcUrls();

Execution Model: Process → Action

The execution tracking model has been renamed for clarity. What was previously called a “process” is now called an “action.”

Type and field renames

  • Execution.processExecution.actions
  • ProcessExecutionAction
  • ProcessTypeExecutionActionType
  • getProcessMessage()getActionMessage() + getSubstatusMessage()

New action types

The TOKEN_ALLOWANCE process type has been split into more granular action types:
  • CHECK_ALLOWANCE - Checking token allowance
  • RESET_ALLOWANCE - Resetting token allowance
  • SET_ALLOWANCE - Setting token allowance
Additionally, the NATIVE_PERMIT action type has been added.

Before (v3)

// SDK v3
step.execution?.process.forEach((process) => {
  if (process.txHash) {
    console.log(process.type, process.txHash);
  }
});

After (v4)

// SDK v4
import { getActionMessage } from '@lifi/sdk';

step.execution?.actions.forEach((action) => {
  if (action.txHash) {
    console.log(action.type, action.txHash);
  }
  const message = getActionMessage(action.type, action.status);
  console.log(message);
});

ExecutionOptions Changes

The switchChainHook and disableMessageSigning options have been removed from ExecutionOptions and moved to EthereumProviderOptions, which is configured when setting up the EVM provider. Note that switchChainHook has been renamed to switchChain on the provider (as shown in the example below).

Before (v3)

// SDK v3
executeRoute(route, {
  switchChainHook: async (chainId) => { ... },
  disableMessageSigning: true,
});

After (v4)

// SDK v4
import { EthereumProvider } from '@lifi/sdk-provider-ethereum';

client.setProviders([
  EthereumProvider({
    getWalletClient: () => Promise.resolve(walletClient),
    switchChain: async (chainId) => { ... },
    disableMessageSigning: true,
  }),
]);

executeRoute(client, route, {
  // switchChainHook and disableMessageSigning are no longer here
});

Token Allowance Functions

Token allowance functions are now exported from the Ethereum provider package instead of the main SDK package.

Before (v3)

// SDK v3
import { getTokenAllowance, setTokenAllowance } from '@lifi/sdk';

const allowance = await getTokenAllowance(token, ownerAddress, spenderAddress);
const txHash = await setTokenAllowance(approvalRequest);

After (v4)

// SDK v4
import { createClient } from '@lifi/sdk';
import { getTokenAllowance, setTokenAllowance } from '@lifi/sdk-provider-ethereum';

const client = createClient({
  integrator: 'Your dApp/company name',
});

const allowance = await getTokenAllowance(client, token, ownerAddress, spenderAddress);
const txHash = await setTokenAllowance(client, approvalRequest);

The actions() Helper

If you prefer calling SDK functions without passing the client as the first parameter each time, you can use the actions() helper. It returns an object with all SDK action functions pre-bound to the client.
// SDK v4
import { createClient, actions } from '@lifi/sdk';

const client = createClient({
  integrator: 'Your dApp/company name',
});

const api = actions(client);

// No need to pass client as the first parameter
const quote = await api.getQuote({
  fromChain: 42161,
  toChain: 10,
  fromToken: '0x...',
  toToken: '0x...',
  fromAmount: '10000000',
  fromAddress: '0x...',
});

New Utilities

v4 exports common utilities from @lifi/sdk so you no longer need viem or other libraries for basic formatting:
import { formatUnits, parseUnits } from '@lifi/sdk';

// Format token amount for display
const formatted = formatUnits(1000000n, 6); // "1"

// Parse user input to token amount
const amount = parseUnits("1", 6); // 1000000n

Removed Parameters

Some configuration parameters have been removed or changed:
  • chains - No longer passed to createClient. Chains are fetched automatically from the API.

Client Instance Pattern

The client instance pattern allows you to:
  1. Create multiple clients with different configurations
  2. Better testability - easier to mock and test
  3. Type safety - better TypeScript support
  4. Explicit dependencies - clear what functions depend on

Example: Multiple Clients

// SDK v4 - Multiple clients
import { createClient } from '@lifi/sdk';

const mainnetClient = createClient({
  integrator: 'MyApp',
  apiUrl: 'https://li.quest/v1',
});

const testnetClient = createClient({
  integrator: 'MyApp',
  apiUrl: 'https://staging.li.quest/v1',
});

// Use different clients for different environments
const mainnetRoutes = await getRoutes(mainnetClient, {...});
const testnetRoutes = await getRoutes(testnetClient, {...});

Migration Checklist

  • Update package installation to include provider packages
  • Replace createConfig() with createClient() and store the client instance
  • Update all function calls to include client as the first parameter (or use the actions() helper)
  • Update provider imports to use separate provider packages
  • Update provider factory names (EVMEthereumProvider, etc.)
  • For Solana: replace getWalletAdapter with getWallet (returns wallet-standard Wallet)
  • For Sui: replace getWallet with getClient + getSigner
  • Move switchChainHook (renamed to switchChain) and disableMessageSigning from ExecutionOptions to EthereumProviderOptions
  • Update execution monitoring code: execution.processexecution.actions
  • Replace getProcessMessage() with getActionMessage() and getSubstatusMessage()
  • Update token allowance function imports to @lifi/sdk-provider-ethereum
  • Update token allowance function calls to include client parameter
  • Replace config.set() and config.getChains() with client methods
  • Remove any references to global config object
  • Replace viem’s formatUnits/parseUnits with @lifi/sdk exports if desired

Examples

Check out our complete examples in the SDK repository, and feel free to file an issue if you encounter any problems.

Changelog

For a detailed view of all the changes, please see the CHANGELOG.