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.

Complete API reference for all exports from @lifi/widget-light.

<LiFiWidgetLight>

The main component that renders the widget inside an iframe and manages the postMessage bridge.
import { LiFiWidgetLight } from '@lifi/widget-light'

Props

PropTypeRequiredDefaultDescription
srcstringNo'https://widget.li.fi'URL of the hosted widget iframe
configWidgetLightConfigYesJSON-serializable widget configuration (reference)
handlersIframeEcosystemHandler[]No[]Ecosystem handlers for wallet/RPC bridging
iframeOriginstringNoDerived from srcRestrict postMessage to this origin
autoResizebooleanNofalseWhen true, iframe height auto-adjusts to match content
onConnect(args?: ConnectWalletArgs) => voidNoCalled when the widget requests a wallet connection
styleCSSPropertiesNoInline styles for the iframe element
classNamestringNoCSS class for the iframe element
titlestringNo'LI.FI Widget'Accessible title for the iframe

Example

<LiFiWidgetLight
  config={{ integrator: 'my-app', variant: 'wide' }}
  handlers={[ethHandler, solHandler]}
  autoResize
  style={{ width: 392, borderRadius: 16 }}
/>
Only one <LiFiWidgetLight> instance per page is supported. The event bus and guest bridge are module-level singletons.

useWidgetLightHost(options)

Low-level hook that manages the host side of the postMessage bridge. Use this if you need to render your own <iframe> element instead of using the <LiFiWidgetLight> component.
import { useWidgetLightHost } from '@lifi/widget-light'

Options

OptionTypeRequiredDefaultDescription
configWidgetLightConfigYesWidget configuration
handlersIframeEcosystemHandler[]No[]Ecosystem handlers
iframeOriginstringNo'*'Expected iframe origin for message filtering
autoResizebooleanNofalseEnable auto-resize via RESIZE messages
onConnect(args?: ConnectWalletArgs) => voidNoExternal wallet connect callback

Return Value

FieldTypeDescription
iframeRefRefObject<HTMLIFrameElement | null>Ref to attach to your <iframe> element

Example

import { useWidgetLightHost } from '@lifi/widget-light'
import { useEthereumIframeHandler } from '@lifi/widget-light/ethereum'
import { useMemo } from 'react'

function CustomIframeSetup() {
  const ethHandler = useEthereumIframeHandler()
  const handlers = useMemo(() => [ethHandler], [ethHandler])

  const { iframeRef } = useWidgetLightHost({
    config: { integrator: 'my-app', fromChain: 1, toChain: 137 },
    handlers,
    iframeOrigin: 'https://widget.li.fi',
    autoResize: true,
  })

  return (
    <iframe
      ref={iframeRef}
      src="https://widget.li.fi"
      title="LI.FI Widget"
      style={{ border: 'none', width: 392, height: 640 }}
      allow="clipboard-write"
    />
  )
}

useWidgetLightEvents()

Returns a typed event emitter for subscribing to widget events. Can be called from any component — no provider wrapping needed.
import { useWidgetLightEvents } from '@lifi/widget-light'

Return Value

interface WidgetLightEventEmitter {
  on<E extends keyof WidgetLightEvents>(
    event: E,
    handler: (data: WidgetLightEvents[E]) => void
  ): void
  off<E extends keyof WidgetLightEvents>(
    event: E,
    handler: (data: WidgetLightEvents[E]) => void
  ): void
}

Example

const events = useWidgetLightEvents()

useEffect(() => {
  const handler = (data: WidgetLightChainTokenSelected) => {
    console.log('Token selected:', data.chainId, data.tokenAddress)
  }
  events.on(WidgetLightEvent.SourceChainTokenSelected, handler)
  return () => events.off(WidgetLightEvent.SourceChainTokenSelected, handler)
}, [events])
See Widget Light Events for the full event reference.

Types

WidgetLightChainType vs WidgetChainType: Both unions describe ecosystem discriminators and include TVM for Tron. Use WidgetLightChainType for the iframe postMessage protocol (for example IframeEcosystemHandler.chainType). Use WidgetChainType on host-facing config types such as ConnectWalletArgs.chainType, where the hosted widget tells your app which ecosystem to connect. The names differ because protocol-level types and configuration-level types are defined separately in the package.

WidgetLightConfig

The primary configuration type. Must be JSON-serializable. See Configure Widget Light for the full reference.
import type { WidgetLightConfig } from '@lifi/widget-light'
Required field: integrator: string

ConnectWalletArgs

Arguments passed to the onConnect callback when the widget requests a wallet connection:
import type { ConnectWalletArgs } from '@lifi/widget-light'
FieldTypeDescription
chainIdnumber | undefinedTarget chain ID
chainTypeWidgetChainType | undefinedTarget chain type ('EVM', 'SVM', 'UTXO', 'MVM', 'TVM')

IframeEcosystemHandler

Interface implemented by all ecosystem handlers:
import type { IframeEcosystemHandler } from '@lifi/widget-light'
MethodTypeDescription
chainTypeWidgetLightChainType'EVM' | 'SVM' | 'UTXO' | 'MVM' | 'TVM'
getInitState()EcosystemInitState | nullReturns initial wallet state for the INIT handshake
handleRequest(id, method, params?)Promise<unknown>Handles an RPC request from the iframe
subscribe(emit)() => voidSubscribes to wallet state changes; returns unsubscribe function

WidgetLightEvent

Enum of all event names. See Widget Light Events for values and payload types.
import { WidgetLightEvent } from '@lifi/widget-light'

WidgetLightChainType

Chain type discriminator used in the postMessage protocol:
type WidgetLightChainType = 'EVM' | 'SVM' | 'UTXO' | 'MVM' | 'TVM'

WidgetChainType

Extended chain type used in configuration (includes TVM):
type WidgetChainType = 'EVM' | 'SVM' | 'MVM' | 'UTXO' | 'TVM'

FAQ

Can I run multiple widgets on the same page?

No. @lifi/widget-light uses a module-level singleton for the event bus and guest bridge. Only one <LiFiWidgetLight> instance per page is supported.

What URL should I use for src?

The default (https://widget.li.fi) is the production-hosted widget. You do not need to set src at all for most use cases. For testing against a specific version or a self-hosted deployment, pass your custom URL as src.

Why must config be JSON-serializable?

Configuration is sent to the iframe via postMessage, which uses the structured clone algorithm. React nodes, functions, class instances, and MUI theme objects cannot be cloned. The WidgetLightConfig type only exposes serializable fields (no React nodes, callbacks, or MUI theme objects), so the type system rejects most non-serializable values at compile time. This is enforcement by omission rather than a general serializability check, so still ensure any values you pass are JSON-serializable at runtime.

How does auto-resize work?

When autoResize is true, the iframe content uses a ResizeObserver to detect height changes and posts them to the host. The host directly sets iframe.style.height for zero-flicker updates. Set autoResize={false} if you want to control iframe dimensions yourself via CSS.

Do I need to handle reconnection after page refresh?

Wallet state is sent from your app to the iframe on every mount via the INIT handshake. If your wagmi/wallet-adapter handles reconnection (which most do by default), the widget will automatically receive the reconnected state.

How is security handled?

The iframeOrigin is automatically derived from src (defaults to https://widget.li.fi), so postMessage communication is restricted to the correct origin. Messages from other origins are silently dropped. You only need to set iframeOrigin explicitly if you want to override the derived value.

Where can I find working examples?

The widget repository includes two examples:
  • vite-iframe-wagmi — Minimal EVM-only integration
  • vite-iframe — Full multi-ecosystem setup with events, config reactivity, and external wallet management
Run them locally:
# From the widget repository root
pnpm install
pnpm --filter vite-iframe-wagmi dev
# or
pnpm --filter vite-iframe dev