> ## 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.

# Multi-VM Support

> Seamlessly connecting every ecosystem for your needs

## Introduction to SDK Ecosystem Providers

The LI.FI SDK supports different blockchain ecosystems, allowing you to integrate with EVM, Solana, Bitcoin, Sui, and Tron networks. Internally, providers act as abstractions for each ecosystem, handling crucial tasks such as address resolution, balance checking, and transaction handling during route/quote execution.

These ecosystem providers are designed with modularity in mind and are fully tree-shakable, ensuring that they do not add unnecessary weight to your bundle if not used.

The SDK offers five provider packages, each with similar configuration options respective to their ecosystems:

* `@lifi/sdk-provider-ethereum` - For EVM-compatible chains
* `@lifi/sdk-provider-solana` - For Solana
* `@lifi/sdk-provider-bitcoin` - For Bitcoin (UTXO)
* `@lifi/sdk-provider-sui` - For Sui
* `@lifi/sdk-provider-tron` - For Tron

```typescript theme={"system"}
import { EthereumProvider } from '@lifi/sdk-provider-ethereum';
import { SolanaProvider } from '@lifi/sdk-provider-solana';
import { BitcoinProvider } from '@lifi/sdk-provider-bitcoin';
import { SuiProvider } from '@lifi/sdk-provider-sui';
import { TronProvider } from '@lifi/sdk-provider-tron';
```

The setup for all providers focuses on utilizing a wallet client, wallet adapter, or a similar wallet interface concept depending on the ecosystem-specific libraries and standards. This unified approach simplifies managing wallets and transactions across EVM-compatible, Solana, Bitcoin, Sui, and Tron chains.

### Different types of wallets/accounts

To execute `GET /quote` or `POST /advanced/routes` via a specific provider, that provider must be capable of signing transactions. SDK providers support signing transactions over the following types of wallets/accounts:

* **Local Accounts (e.g. private key/mnemonic wallets).**

Local accounts are wallets managed using private keys or mnemonic phrases. This setup is often used in backend services or scenarios where automated signing and transaction management are required.

* **JSON-RPC Accounts (e.g. Browser Extension Wallets, WalletConnect, etc.).**

Using JSON-RPC accounts involves connecting through a Web3 provider, e.g. `window.ethereum`, and managing the user's account within the browser or mobile context. This setup is popular among dApps UIs and is often used together with libraries like `Wagmi`, `@solana/wallet-adapter-react`, or `@mysten/dapp-kit`.

These account types and interaction methods allow developers to choose the most suitable approach for integrating the SDK with their applications.

## Setup EVM Provider

The EVM provider execution logic is built based on the `Viem` library, using some of its types and terminology.

**Options available for configuring the EVM provider:**

* `getWalletClient`: A function that returns a Viem `Client` instance (typically a `WalletClient` created via `createWalletClient`).
* `switchChain`: A hook for switching between different networks. Returns an updated `Client` for the target chain.
* `disableMessageSigning`: An optional boolean to disable EIP-712 message signing (e.g., for Permit approvals). Useful for wallets or smart accounts that do not support typed data signing.
* `fallbackTransportConfig`: Optional Viem fallback transport configuration.
* `safeApiKey`: Optional Safe API key for Safe multisig wallets.

### Local Accounts

When using local accounts, developers need a predefined list of chains they plan to interact with in order to switch chains during transaction execution. These chains can be either from the `viem/chains` package or fetched from LI.FI API and adopted to viem's `Chain` type.

Here's a basic example using chains from `viem/chains`:

```typescript theme={"system"}
import { createClient } from '@lifi/sdk';
import { EthereumProvider } from '@lifi/sdk-provider-ethereum';
import type { Chain } from 'viem';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { arbitrum, mainnet, optimism, polygon, scroll } from 'viem/chains';

const account = privateKeyToAccount('PRIVATE_KEY');

const chains = [arbitrum, mainnet, optimism, polygon, scroll];

const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

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

client.setProviders([
  EthereumProvider({
    getWalletClient: async () => walletClient,
    switchChain: async (chainId) =>
      // Switch chain by creating a new wallet client
      createWalletClient({
        account,
        chain: chains.find((chain) => chain.id == chainId) as Chain,
        transport: http(),
      }),
  }),
]);
```

### JSON-RPC Accounts

The best way to interact with JSON-RPC accounts and pass `WalletClient` to the `EthereumProvider` is to use the [Wagmi](https://wagmi.sh/) library. Developers can configure Wagmi chains either by using chains from the `viem/chains` package or fetching chains from the LI.FI API and adapting them to Viem's `Chain` type.

Below is a simplified example of how to set up the EVM provider using chains from the LI.FI API in conjunction with Wagmi and React.

We provide a `useSyncWagmiConfig` hook that synchronizes fetched chains with the Wagmi configuration and updates connectors. Please note that we do not initialize the Wagmi configuration with connectors. Additionally, we set `reconnectOnMount` to `false` since the `reconnect` action will be called within `useSyncWagmiConfig` hook after the chains are synchronized with the configuration and connectors.

```typescript theme={"system"}
import { ChainType, createClient, getChains } from '@lifi/sdk';
import { EthereumProvider } from '@lifi/sdk-provider-ethereum';
import { useSyncWagmiConfig } from '@lifi/wallet-management';
import { useQuery } from '@tanstack/react-query';
import { getWalletClient, switchChain } from '@wagmi/core';
import { type FC, type PropsWithChildren } from 'react';
import { createClient as createViemClient, http } from 'viem';
import { mainnet } from 'viem/chains';
import type { Config, CreateConnectorFn } from 'wagmi';
import { WagmiProvider, createConfig as createWagmiConfig } from 'wagmi';
import { injected } from 'wagmi/connectors';

// List of Wagmi connectors
const connectors: CreateConnectorFn[] = [injected()];

// Create Wagmi config with default chain and without connectors
const wagmiConfig: Config = createWagmiConfig({
  chains: [mainnet],
  client({ chain }) {
    return createViemClient({ chain, transport: http() });
  },
});

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

// Set up EVM provider using Wagmi actions and configuration
client.setProviders([
  EthereumProvider({
    getWalletClient: () => getWalletClient(wagmiConfig),
    switchChain: async (chainId) => {
      const chain = await switchChain(wagmiConfig, { chainId });
      return getWalletClient(wagmiConfig, { chainId: chain.id });
    },
  }),
]);

export const CustomWagmiProvider: FC<PropsWithChildren> = ({ children }) => {
  // Load EVM chains from LI.FI API using getChains action from LI.FI SDK
  const { data: chains } = useQuery({
    queryKey: ['chains'] as const,
    queryFn: async () => {
      const chains = await getChains(client, {
        chainTypes: [ChainType.EVM],
      });
      return chains;
    },
  });

  // Synchronize fetched chains with Wagmi config and update connectors
  useSyncWagmiConfig(wagmiConfig, connectors, chains);

  return (
    <WagmiProvider config={wagmiConfig} reconnectOnMount={false}>
      {children}
    </WagmiProvider>
  );
};
```

### Update provider configuration

Additionally, providers allow for dynamic updates to its initial configuration via the `setOptions` function.

Here's an example of how to modify the initial configuration for `EthereumProvider`:

```typescript theme={"system"}
import { createClient } from '@lifi/sdk';
import { EthereumProvider } from '@lifi/sdk-provider-ethereum';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { arbitrum, mainnet } from 'viem/chains';

const account = privateKeyToAccount('PRIVATE_KEY');

const mainnetClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

const evmProvider = EthereumProvider({
  getWalletClient: async () => mainnetClient,
});

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

client.setProviders([evmProvider]);

const arbitrumClient = createWalletClient({
  account,
  chain: arbitrum,
  transport: http(),
});

evmProvider.setOptions({
  getWalletClient: async () => arbitrumClient,
});
```

### Support for Ethers.js and other alternatives

Developers can still use Ethers.js or any other alternative Web3 library in their project and [convert](https://viem.sh/docs/ethers-migration) `Signer`/`Provider` objects to Viem's `WalletClient` before passing it to the EVM provider configuration.

## Setup Solana Provider

The Solana provider execution logic is built based on the [@solana/kit](https://github.com/solana-labs/solana-web3.js) library and the [Wallet Standard](https://github.com/wallet-standard/wallet-standard), using some of their types and terminology.

**Options available for configuring the Solana provider:**

* `getWallet`: A function that returns a [Wallet Standard](https://github.com/wallet-standard/wallet-standard) `Wallet` instance.
* `skipSimulation`: An optional boolean to skip transaction simulation before sending (default: `false`).

### Local Wallet

Standard Solana libraries do not offer a built-in method for creating a wallet-standard wallet directly from a private key. To address this limitation, we provide the `KeypairWalletAdapter`. This custom adapter enables users to create a wallet from a base58-encoded secret key.

It is worth noting that the `KeypairWalletAdapter` is designed specifically for backend or testing purposes and should not be used in user-facing code to prevent the risk of exposing your private key.

```typescript theme={"system"}
import { createClient } from '@lifi/sdk';
import { SolanaProvider, KeypairWalletAdapter } from '@lifi/sdk-provider-solana';

const wallet = new KeypairWalletAdapter('BASE58_SECRET_KEY');
await wallet.connect();

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

client.setProviders([
  SolanaProvider({
    getWallet: async () => wallet,
  }),
]);
```

### JSON-RPC Wallet

To interact with user wallets and pass a wallet-standard `Wallet` to the Solana provider, we recommend using the [@solana/wallet-adapter-react](https://github.com/anza-xyz/wallet-adapter) library. The `wallet.adapter` from `useWallet()` implements the wallet-standard `Wallet` interface. Unlike Wagmi, Solana configuration for React does not have global configurations. Therefore, we need to use React hooks to update the SDK configuration at runtime.

Below is a simplified example of how to set up the Solana provider.

<CodeGroup>
  ```typescript SDKProviders.tsx theme={"system"}
  import { createClient } from '@lifi/sdk';
  import { SolanaProvider } from '@lifi/sdk-provider-solana';
  import { useWallet } from '@solana/wallet-adapter-react';
  import type { Wallet } from '@wallet-standard/base';
  import { useEffect } from 'react';

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

  export const SDKProviders = () => {
    const { wallet } = useWallet();

    useEffect(() => {
      // Configure SDK Providers
      client.setProviders([
        SolanaProvider({
          async getWallet() {
            return wallet?.adapter as unknown as Wallet;
          },
        }),
      ]);
    }, [wallet?.adapter]);

    return null;
  };
  ```

  ```typescript SolanaProvider.tsx theme={"system"}
  import type { Adapter } from '@solana/wallet-adapter-base';
  import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
  import {
    ConnectionProvider,
    WalletProvider,
  } from '@solana/wallet-adapter-react';
  import { clusterApiUrl } from '@solana/web3.js';
  import { type FC, type PropsWithChildren } from 'react';
  import { SDKProviders } from './SDKProviders.js';

  const endpoint = clusterApiUrl(WalletAdapterNetwork.Mainnet);
  /**
   * Wallets that implement either of these standards will be available automatically.
   *
   *   - Solana Mobile Stack Mobile Wallet Adapter Protocol
   *     (https://github.com/solana-mobile/mobile-wallet-adapter)
   *   - Solana Wallet Standard
   *     (https://github.com/solana-labs/wallet-standard)
   *
   * If you wish to support a wallet that supports neither of those standards,
   * instantiate its legacy wallet adapter here. Common legacy adapters can be found
   * in the npm package `@solana/wallet-adapter-wallets`.
   */
  const wallets: Adapter[] = [];

  export const SVMBaseProvider: FC<PropsWithChildren> = ({ children }) => {
    return (
      <ConnectionProvider endpoint={endpoint}>
        <WalletProvider wallets={wallets} autoConnect>
          {/* Configure Solana SDK provider */}
          <SDKProviders />
          {children}
        </WalletProvider>
      </ConnectionProvider>
    );
  };
  ```
</CodeGroup>

## Setup Sui Provider

The Sui provider execution logic is built based on the [@mysten/sui](https://sdk.mystenlabs.com/typescript) v2 library, using some of its types and terminology.

**Options available for configuring the Sui provider:**

* `getClient`: A function that returns a `ClientWithCoreApi` instance (from `@mysten/sui/client`).
* `getSigner`: A function that returns a `Signer` instance (from `@mysten/sui/cryptography`).

### JSON-RPC Wallet

To interact with user wallets (like Sui Wallet, etc.) and pass a client and signer to the Sui provider, we recommend using the [@mysten/dapp-kit](https://sdk.mystenlabs.com/dapp-kit) library.

Below is a simplified example of how to set up the Sui provider with user wallets.

<CodeGroup>
  ```typescript SDKProviders.tsx theme={"system"}
  import { createClient } from '@lifi/sdk';
  import { SuiProvider } from '@lifi/sdk-provider-sui';
  import { useSuiClient, useCurrentAccount } from '@mysten/dapp-kit';
  import { useEffect } from 'react';

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

  export const SDKProviders = () => {
    const suiClient = useSuiClient();
    const currentAccount = useCurrentAccount();

    useEffect(() => {
      // Configure Sui SDK provider
      if (currentAccount) {
        client.setProviders([
          SuiProvider({
            async getClient() {
              return suiClient;
            },
            async getSigner() {
              // Return a Signer from @mysten/sui/cryptography
              // The implementation depends on your wallet integration
              return signer;
            },
          }),
        ]);
      }
    }, [suiClient, currentAccount]);

    return null;
  };
  ```

  ```typescript SuiProvider.tsx theme={"system"}
  import { SuiClientProvider, WalletProvider } from '@mysten/dapp-kit';
  import { getFullnodeUrl } from '@mysten/sui/client';
  import { createNetworkConfig } from '@mysten/dapp-kit';
  import { type FC, type PropsWithChildren } from 'react';
  import { SDKProviders } from './SDKProviders.js';

  const { networkConfig } = createNetworkConfig({
    mainnet: { url: getFullnodeUrl('mainnet') },
  });

  export const SuiBaseProvider: FC<PropsWithChildren> = ({ children }) => {
    return (
      <SuiClientProvider networks={networkConfig} defaultNetwork="mainnet">
        <WalletProvider autoConnect>
          {/* Configure Sui SDK provider */}
          <SDKProviders />
          {children}
        </WalletProvider>
      </SuiClientProvider>
    );
  };
  ```
</CodeGroup>

## Setup UTXO (Bitcoin) Provider

The Bitcoin provider execution logic is built based on the [Bigmi](https://github.com/lifinance/bigmi) library, using some of its types and terminology.

**Options available for configuring the UTXO provider:**

* `getWalletClient`: A function that returns a `Client` instance (from `@bigmi/core`).

### JSON-RPC Wallet

To interact with user wallets like Phantom, Xverse, use the `getConnectorClient` action to return the Bigmi Client object required by the SDK.

<CodeGroup>
  ```typescript SDKProvider.tsx theme={"system"}
  import { createClient } from '@lifi/sdk';
  import { BitcoinProvider } from '@lifi/sdk-provider-bitcoin';
  import { getConnectorClient } from '@bigmi/client';
  import { useConfig } from '@bigmi/react';
  import { useEffect } from 'react';

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

  export const SDKProviders = () => {
    const bigmiConfig = useConfig();

    useEffect(() => {
      // Configure SDK Provider
      client.setProviders([
        BitcoinProvider({
          async getWalletClient() {
            return getConnectorClient(bigmiConfig)
          },
        }),
      ]);
    }, [bigmiConfig]);

    return null;
  };
  ```

  ```typescript UTXOProvider.tsx theme={"system"}
  import { bitcoin, createClient, http } from '@bigmi/core'
  import { createConfig, phantom, type CreateConnectorFn, type Config } from '@bigmi/client' 
  import { BigmiProvider } from '@bigmi/react'
  import { type FC, type PropsWithChildren } from 'react'
  import { SDKProviders } from './SDKProviders.js'

  const connectors: CreateConnectorFn[] = [phantom()]

  const bigmiConfig = createConfig({
    chains: [bitcoin],
    connectors,
    client({ chain }) {
      return createClient({ chain, transport: http() })
    }
  }) as Config

  export const UTXOProvider: FC<PropsWithChildren> = ({ children }) => {
    return (
      <BigmiProvider config={bigmiConfig} reconnectOnMount>
        <SDKProviders />
        {children}
      </BigmiProvider>
    )
  }
  ```
</CodeGroup>

## Setup Tron Provider

The Tron provider execution logic is built based on the [TronWeb](https://tronweb.network/) library and the [@tronweb3/tronwallet-abstract-adapter](https://github.com/tronweb3/tronwallet-adapter) adapter interface.

**Options available for configuring the Tron provider:**

* `getWallet`: A function that returns an `Adapter` instance (from `@tronweb3/tronwallet-abstract-adapter`).
* `multicallBatchSize`: An optional number to configure the batch size for multicall balance requests.

### JSON-RPC Wallet

To interact with user wallets (like TronLink), pass an `Adapter` to the Tron provider using the [@tronweb3/tronwallet-adapter-react-hooks](https://github.com/tronweb3/tronwallet-adapter) library.

Below is a simplified example of how to set up the Tron provider.

```typescript SDKProviders.tsx theme={"system"}
import { createClient } from '@lifi/sdk';
import { TronProvider } from '@lifi/sdk-provider-tron';
import { useWallet } from '@tronweb3/tronwallet-adapter-react-hooks';
import { useEffect } from 'react';

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

export const SDKProviders = () => {
  const { wallet } = useWallet();

  useEffect(() => {
    if (wallet?.adapter) {
      client.setProviders([
        TronProvider({
          async getWallet() {
            return wallet.adapter;
          },
        }),
      ]);
    }
  }, [wallet?.adapter]);

  return null;
};
```
