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

# Wallet Management

> Configure your widget for seamless wallet management

The widget has a built-in wallet management UI, so you can connect wallets and use the widget as a standalone dApp out of the box. However, when embedding the widget into an existing dApp, reusing the existing wallet management UI of that dApp often makes the most sense.

<Note>
  See wallet management modes in the [Widget Playground](https://playground.li.fi/) — open **Wallet management** in the sidebar.
</Note>

There are several ecosystems and types of chains supported by the widget:

* **EVM** (Ethereum Virtual Machine) - Ethereum, Polygon, Arbitrum, etc.
* **SVM** (Solana Virtual Machine) - Solana
* **UTXO** - Bitcoin
* **MVM** (Move Virtual Machine) - Sui
* **TVM** (Tron Virtual Machine) - Tron

Each ecosystem uses different libraries to manage wallet connections.

## Using Widget Providers

The simplest way to set up wallet management is using the built-in provider packages:

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

const widgetConfig: WidgetConfig = {
  providers: [
    EthereumProvider(),
    SolanaProvider(),
    BitcoinProvider(),
    SuiProvider(),
    TronProvider(),
  ],
};

export const WidgetPage = () => {
  return <LiFiWidget integrator="your-dapp-name" config={widgetConfig} />;
};
```

## EVM Wallet Connection

To manage wallet connections to EVM chains, the widget uses the [Wagmi](https://wagmi.sh/) library internally and provides first-class support for Wagmi-based libraries such as:

* [RainbowKit](https://www.rainbowkit.com/)
* [ConnectKit](https://docs.family.co/connectkit)
* [Reown AppKit](https://docs.reown.com/appkit/overview) (formerly WalletConnect)
* [Privy](https://www.privy.io/)
* [Dynamic](https://www.dynamic.xyz/)

### Automatic Detection

If you already manage wallets using Wagmi or a Wagmi-based library in your dApp and the Widget detects that it is wrapped in [WagmiProvider](https://wagmi.sh/react/api/WagmiProvider), it will automatically reuse your wallet management without any additional configuration.

### Basic Wagmi Setup

```typescript theme={"system"}
import { LiFiWidget } from '@lifi/widget';
import { createClient } from 'viem';
import { WagmiProvider, createConfig, http } from 'wagmi';
import { mainnet, arbitrum, optimism, scroll } from 'wagmi/chains';
import { injected } from 'wagmi/connectors';

const wagmiConfig = createConfig({
  // Provide the full list of chains you want to support
  chains: [mainnet, arbitrum, optimism, scroll],
  connectors: [injected()],
  client({ chain }) {
    return createClient({ chain, transport: http() });
  },
});

export const WidgetPage = () => {
  return (
    <WagmiProvider config={wagmiConfig} reconnectOnMount>
      <LiFiWidget integrator="wagmi-example" />
    </WagmiProvider>
  );
};
```

### Keep Chains in Sync

It's important to keep the Wagmi chains configuration in sync with the Widget chain list so all functionality, like switching chains, works correctly. There are two approaches:

1. **Manual**: Update both Widget and Wagmi chains configuration to specify all supported chains.
2. **Dynamic**: Get available chains from LI.FI API and dynamically update Wagmi configuration.

#### Dynamic Chain Sync

Use the `useSyncWagmiConfig` hook from `@lifi/widget-provider-ethereum` and `useWidgetChains` from `@lifi/widget`:

<CodeGroup>
  ```typescript WalletProvider.tsx theme={"system"}
  import { useSyncWagmiConfig } from '@lifi/widget-provider-ethereum';
  import { useWidgetChains } from '@lifi/widget';
  import type { WidgetConfig } from '@lifi/widget';
  import { injected } from '@wagmi/connectors';
  import { useRef, type FC, type PropsWithChildren } from 'react';
  import { createClient, http } from 'viem';
  import { mainnet } from 'viem/chains';
  import type { Config } from 'wagmi';
  import { createConfig, WagmiProvider } from 'wagmi';

  const connectors = [injected()];

  // useWidgetChains requires a WidgetConfig to fetch chains from the LI.FI API
  const widgetConfig: WidgetConfig = {
    integrator: 'your-dapp-name',
  };

  export const WalletProvider: FC<PropsWithChildren> = ({ children }) => {
    const { chains } = useWidgetChains(widgetConfig);
    const wagmi = useRef<Config>(null);

    if (!wagmi.current) {
      wagmi.current = createConfig({
        chains: [mainnet],
        client({ chain }) {
          return createClient({ chain, transport: http() });
        },
        ssr: true,
      });
    }

    useSyncWagmiConfig(wagmi.current, connectors, chains);

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

  ```typescript WidgetPage.tsx theme={"system"}
  import { LiFiWidget } from '@lifi/widget';
  import { WalletProvider } from '../providers/WalletProvider';

  export const WidgetPage = () => {
    return (
      <WalletProvider>
        <LiFiWidget integrator="wagmi-example" />
      </WalletProvider>
    );
  };
  ```
</CodeGroup>

Please check out our complete examples in the widget repository:

* [RainbowKit](https://github.com/lifinance/widget/tree/main/examples/rainbowkit)
* [ConnectKit](https://github.com/lifinance/widget/tree/main/examples/connectkit)
* [Reown AppKit](https://github.com/lifinance/widget/tree/main/examples/reown)
* [Privy](https://github.com/lifinance/widget/tree/main/examples/privy)
* [Dynamic](https://github.com/lifinance/widget/tree/main/examples/dynamic)

## SVM (Solana) Wallet Connection

To manage wallet connections to Solana, the widget uses the [Solana Wallet Standard](https://github.com/wallet-standard/wallet-standard) via the `@lifi/widget-provider-solana` package.

The Solana provider automatically discovers wallets that implement the Wallet Standard. To use it, simply include `SolanaProvider()` in your widget's `providers` array:

```typescript theme={"system"}
import { LiFiWidget, WidgetConfig } from '@lifi/widget';
import { SolanaProvider } from '@lifi/widget-provider-solana';

const widgetConfig: WidgetConfig = {
  providers: [SolanaProvider()],
};

export const WidgetPage = () => {
  return <LiFiWidget integrator="solana-example" config={widgetConfig} />;
};
```

The `@lifi/widget-provider-solana` package requires `bs58` (>=4.0.1) as a peer dependency.

## MVM (Sui) Wallet Connection

To manage wallet connections to Sui, the widget uses [@mysten/dapp-kit-react](https://sdk.mystenlabs.com/dapp-kit) (^2.0.0).

<Note>
  In Widget v4, the Sui peer dependency changed from `@mysten/dapp-kit` to `@mysten/dapp-kit-react`.
</Note>

If the Widget detects it's wrapped in a Sui `DAppKitContext`, it will reuse your wallet management automatically.

To use the built-in Sui wallet management, include `SuiProvider()` in the `providers` array:

```typescript theme={"system"}
import { LiFiWidget, WidgetConfig } from '@lifi/widget';
import { SuiProvider } from '@lifi/widget-provider-sui';

const widgetConfig: WidgetConfig = {
  providers: [SuiProvider()],
};

export const WidgetPage = () => {
  return <LiFiWidget integrator="sui-example" config={widgetConfig} />;
};
```

If you already have a Sui wallet context in your app using `@mysten/dapp-kit-react`, the widget will detect it and reuse your existing connection:

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

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

  export const SuiWalletProvider: FC<PropsWithChildren> = ({ children }) => {
    return (
      <SuiClientProvider networks={networkConfig} defaultNetwork="mainnet">
        <WalletProvider autoConnect>{children}</WalletProvider>
      </SuiClientProvider>
    );
  };
  ```

  ```typescript WidgetPage.tsx theme={"system"}
  import { LiFiWidget } from '@lifi/widget';
  import { SuiProvider } from '@lifi/widget-provider-sui';
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
  import { SuiWalletProvider } from '../providers/SuiWalletProvider';

  const queryClient = new QueryClient();

  export const WidgetPage = () => {
    return (
      <QueryClientProvider client={queryClient}>
        <SuiWalletProvider>
          <LiFiWidget
            integrator="sui-example"
            config={{ providers: [SuiProvider()] }}
          />
        </SuiWalletProvider>
      </QueryClientProvider>
    );
  };
  ```
</CodeGroup>

## UTXO (Bitcoin) Wallet Connection

To manage wallet connections to Bitcoin, the widget uses [Bigmi](https://github.com/lifinance/bigmi).

To use the built-in Bitcoin wallet management, include `BitcoinProvider()` in the `providers` array:

```typescript theme={"system"}
import { LiFiWidget, WidgetConfig } from '@lifi/widget';
import { BitcoinProvider } from '@lifi/widget-provider-bitcoin';

const widgetConfig: WidgetConfig = {
  providers: [BitcoinProvider()],
};

export const WidgetPage = () => {
  return <LiFiWidget integrator="bitcoin-example" config={widgetConfig} />;
};
```

The `@lifi/widget-provider-bitcoin` package requires `@bigmi/react` (^0.8.0) as a peer dependency.

If the Widget detects it's wrapped in `BigmiProvider`, it will reuse your wallet management automatically:

<CodeGroup>
  ```typescript WidgetPage.tsx theme={"system"}
  import type { Config, CreateConnectorFn } from '@bigmi/client';
  import { createConfig, phantom, unisat, xverse } from '@bigmi/client';
  import { bitcoin, createClient, http } from '@bigmi/core';
  import { BigmiProvider } from '@bigmi/react';
  import { LiFiWidget } from '@lifi/widget';

  const connectors: CreateConnectorFn[] = [phantom(), unisat(), xverse()];

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

  export const WidgetPage = () => {
    return (
      <BigmiProvider config={config} reconnectOnMount>
        <LiFiWidget integrator="bigmi-example" />
      </BigmiProvider>
    );
  };
  ```
</CodeGroup>

## TVM (Tron) Wallet Connection

To manage wallet connections to Tron, the widget uses [@tronweb3/tronwallet-adapter-react-hooks](https://github.com/tronweb3/tronwallet-adapter) (^1.1.11).

To use the built-in Tron wallet management, include `TronProvider()` in the `providers` array:

```typescript theme={"system"}
import { LiFiWidget, WidgetConfig } from '@lifi/widget';
import { TronProvider } from '@lifi/widget-provider-tron';

const widgetConfig: WidgetConfig = {
  providers: [TronProvider()],
};

export const WidgetPage = () => {
  return <LiFiWidget integrator="tron-example" config={widgetConfig} />;
};
```

The `@lifi/widget-provider-tron` package requires `@tronweb3/tronwallet-adapter-react-hooks` (^1.1.11) as a peer dependency.

The `TronProvider` accepts an optional configuration object with a `walletConnect` option to enable WalletConnect support for Tron wallets:

```typescript theme={"system"}
import { TronProvider } from '@lifi/widget-provider-tron';

const widgetConfig: WidgetConfig = {
  providers: [
    TronProvider({
      walletConnect: {
        network: 'Mainnet',
        options: {
          projectId: 'your-walletconnect-project-id',
        },
      },
    }),
  ],
};
```

The `walletConnect` option accepts a `WalletConnectAdapterConfig` from `@tronweb3/tronwallet-adapters` with required `network` (`'Mainnet'`, `'Shasta'`, `'Nile'`, or a chain ID) and `options` (WalletConnect `SignClientTypes.Options` including your `projectId`) fields. Set `walletConnect` to `true` to use default settings.

## Configuration

### WidgetWalletConfig Interface

```typescript theme={"system"}
interface WidgetWalletConfig {
  // Callback when "Connect wallet" button is clicked
  onConnect?(args?: WalletMenuOpenArgs): void;
  
  // Define ecosystem order for multichain wallets
  walletEcosystemsOrder?: Record<string, ChainType[]>;
  
  // Enable hybrid external/internal wallet management
  // @default false
  usePartialWalletManagement?: boolean;
  
  // Force internal wallet management, ignoring external contexts
  // @default false
  forceInternalWalletManagement?: boolean;
}
```

### Connect Wallet Button

When using external wallet management, use the `onConnect` callback to open your wallet modal:

```typescript theme={"system"}
import { LiFiWidget, WidgetConfig } from '@lifi/widget';
import { useConnectModal } from '@rainbow-me/rainbowkit';

export const WidgetPage = () => {
  const { openConnectModal } = useConnectModal();
  
  return (
    <LiFiWidget
      integrator="your-dapp"
      config={{
        walletConfig: {
          onConnect() {
            openConnectModal?.();
          },
        },
      }}
    />
  );
};
```

### Ethereum Provider Configuration

When using the built-in wallet management via `EthereumProvider`, you can configure wallet connectors:

```typescript theme={"system"}
import { LiFiWidget, WidgetConfig } from '@lifi/widget';
import { EthereumProvider } from '@lifi/widget-provider-ethereum';

const widgetConfig: WidgetConfig = {
  providers: [
    EthereumProvider({
      walletConnect: {
        projectId: 'your-walletconnect-project-id',
      },
      coinbase: {
        appName: 'Your App Name',
      },
      metaMask: {
        // MetaMask SDK options
      },
      porto: {
        // Porto connector options (EIP-7702)
      },
      baseAccount: {
        // Base Account options
      },
    }),
  ],
};

export const WidgetPage = () => {
  return <LiFiWidget integrator="your-dapp" config={widgetConfig} />;
};
```

Each connector option can also be set to `true` to use default settings, or omitted to disable that connector:

```typescript theme={"system"}
EthereumProvider({
  walletConnect: true,   // Use defaults (no projectId required for basic discovery)
  coinbase: true,        // Use defaults
  metaMask: false,       // Explicitly disabled (same as omitting)
})
```

#### EthereumProviderConfig Interface

```typescript theme={"system"}
interface EthereumProviderConfig {
  walletConnect?: WalletConnectParameters | boolean
  coinbase?: CoinbaseWalletParameters | boolean
  metaMask?: MetaMaskParameters | boolean
  baseAccount?: BaseAccountParameters | boolean
  porto?: Partial<PortoParameters> | boolean
  disableMessageSigning?: boolean
  sdkProvider?: SDKProvider | SDKProviderFactory<EthereumProviderDeps>
}
```

The `disableMessageSigning` option disables permit-based (EIP-2612) gasless approvals, falling back to standard token approval transactions. This is useful for smart account compatibility. See [Smart Accounts Compatibility](#smart-accounts-compatibility) below.

The `sdkProvider` option lets you supply a custom SDK provider. See [Custom SDK Providers](#custom-sdk-providers) for details.

### Partial Wallet Management

If your external wallet management doesn't support all ecosystems, enable partial wallet management to use a hybrid approach:

```typescript theme={"system"}
const widgetConfig: WidgetConfig = {
  walletConfig: {
    usePartialWalletManagement: true,
  },
};
```

In partial mode:

* External wallet management handles "opt-out" ecosystems
* Internal wallet management handles remaining ecosystems
* Both wallet menus can operate together

This is useful when migrating to a new setup or when your wallet library only supports certain chains (e.g., RainbowKit for EVM, while internal handles Solana and Bitcoin).

### Force Internal Wallet Management

The widget automatically detects existing wallet contexts (e.g., WagmiContext for EVM). To override this and force internal management for all ecosystems:

```typescript theme={"system"}
const widgetConfig: WidgetConfig = {
  walletConfig: {
    forceInternalWalletManagement: true,
  },
};
```

### Ecosystem Order for Wallets

Define the preferred ecosystem order for multichain wallets:

```typescript theme={"system"}
import { ChainType } from '@lifi/widget';

const widgetConfig: WidgetConfig = {
  walletConfig: {
    walletEcosystemsOrder: {
      MetaMask: [ChainType.EVM, ChainType.SVM],
      Phantom: [ChainType.SVM, ChainType.EVM],
    },
  },
};
```

The keys must match wallet names as labeled in the Widget UI. This only affects display order, not actual ecosystem support.

### Custom SDK Providers

Every provider config accepts an `sdkProvider` option that lets you replace the built-in SDK provider with a custom implementation for signing, chain switching, or other low-level operations.

You can pass either an `SDKProvider` object directly or a factory function that receives ecosystem-specific dependencies and returns an `SDKProvider`.

Each ecosystem exposes different dependencies to the factory:

```typescript theme={"system"}
// EVM
interface EthereumProviderDeps {
  getWalletClient: () => Promise<Client>
  switchChain: (chainId: number) => Promise<Client | undefined>
  disableMessageSigning?: boolean
}

// Solana
interface SolanaProviderDeps {
  getWallet: () => Promise<Wallet>
}

// Bitcoin
interface BitcoinProviderDeps {
  getWalletClient: () => Promise<Client>
}

// Sui
interface SuiProviderDeps {
  getClient: () => Promise<ClientWithCoreApi>
  getSigner: () => Promise<Signer>
}

// Tron
interface TronProviderDeps {
  getWallet: () => Promise<Adapter>
}
```

Example using a factory function with the Ethereum provider:

```typescript theme={"system"}
import { EthereumProvider } from '@lifi/widget-provider-ethereum';
import type { EthereumProviderDeps } from '@lifi/widget-provider-ethereum';
import type { SDKProvider } from '@lifi/sdk';

const widgetConfig: WidgetConfig = {
  providers: [
    EthereumProvider({
      sdkProvider: (deps: EthereumProviderDeps): SDKProvider => {
        return {
          // Custom SDKProvider implementation using deps.getWalletClient,
          // deps.switchChain, etc.
        };
      },
    }),
  ],
};
```

When omitted, each provider uses its built-in SDK provider implementation.

## Smart Accounts Compatibility

When using the Widget with smart accounts (Privy, Dynamic, ZeroDev, etc.), you may encounter signature compatibility issues.

### The Problem

* **EOAs** use ECDSA signatures for standard transactions
* **Smart Accounts** may use ERC-1271 or other signature validation methods

This can cause incompatibility with native permit functionality (EIP-2612) used for gasless token approvals.

<Note>
  EIP-7702 delegated smart wallets, such as delegated MetaMask accounts,
  currently require source-chain native gas because gasless or relayer routes
  are not offered for this wallet type. See [EIP-7702 delegated wallet troubleshooting](/faqs/troubleshooting#eip-7702-delegated-smart-wallets).
</Note>

#### EIP-5792 Transaction Batching Support

If your smart account provider supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792) (Wallet Function Call API), there should be no compatibility issues. The widget will automatically use batch transactions instead of individual permit signatures.

### Disabling Message Signing

For smart accounts without EIP-5792 support, disable message signing to use standard approval transactions. In v4, this option is configured on the `EthereumProvider`:

```typescript theme={"system"}
import { EthereumProvider } from '@lifi/widget-provider-ethereum';

const widgetConfig: WidgetConfig = {
  providers: [
    EthereumProvider({
      disableMessageSigning: true,
    }),
  ],
};
```

<Note>
  Disabling message signing will fallback to standard token approval
  transactions, which may require additional gas fees but ensures compatibility
  with all smart account implementations.
</Note>

### updateTransactionRequestHook

For advanced use cases, you can modify transaction requests before they're sent:

```typescript theme={"system"}
const widgetConfig: WidgetConfig = {
  sdkConfig: {
    executionOptions: {
      updateTransactionRequestHook: async (txRequest) => {
        // Modify the transaction request
        return {
          ...txRequest,
          // Your modifications
        };
      },
    },
  },
};
```

## Wallet Management Events

The `@lifi/wallet-management` package provides its own event emitter for wallet connection and disconnection events. These are separate from the [Widget Events](/widget/widget-events).

```typescript theme={"system"}
import {
  useWalletManagementEvents,
  WalletManagementEvent,
} from '@lifi/wallet-management';
import type {
  WalletConnected,
  WalletDisconnected,
} from '@lifi/wallet-management';
import { useEffect } from 'react';

export const WalletEventsExample = () => {
  const walletEvents = useWalletManagementEvents();

  useEffect(() => {
    const onWalletConnected = (data: WalletConnected) => {
      console.log('Wallet connected:', data.address, data.connectorName);
    };
    const onWalletDisconnected = (data: WalletDisconnected) => {
      console.log('Wallet disconnected:', data.chainType);
    };

    walletEvents.on(
      WalletManagementEvent.WalletConnected,
      onWalletConnected
    );
    walletEvents.on(
      WalletManagementEvent.WalletDisconnected,
      onWalletDisconnected
    );

    return () => walletEvents.removeAllListeners();
  }, [walletEvents]);

  return null;
};
```

### WalletConnected

Fires when a wallet is connected via the widget's internal wallet management UI.

```typescript theme={"system"}
interface WalletConnected {
  address: string
  chainId: number
  chainType: ChainType
  connectorId: string
  connectorName: string
}
```

### WalletDisconnected

Fires when a wallet is disconnected.

```typescript theme={"system"}
interface WalletDisconnected {
  address?: string
  chainId?: number
  chainType: ChainType
  connectorId?: string
  connectorName?: string
}
```
