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

# Widget Light API 参考

> @lifi/widget-light 的组件和钩子 API 参考

`@lifi/widget-light` 所有导出项的完整 API 参考。

## `<LiFiWidgetLight>`

在 iframe 内渲染 widget 并管理 postMessage 桥接的主组件。

```tsx theme={"system"}
import { LiFiWidgetLight } from '@lifi/widget-light'
```

### Props

| Prop           | 类型                                   | 是否必填 | 默认值                      | 说明                                                              |
| -------------- | ------------------------------------ | ---- | ------------------------ | --------------------------------------------------------------- |
| `src`          | `string`                             | 否    | `'https://widget.li.fi'` | 托管的 widget iframe 的 URL                                         |
| `config`       | `WidgetLightConfig`                  | 是    | --                       | 可 JSON 序列化的 widget 配置（[参考](/widget/widget-light-configuration)） |
| `handlers`     | `IframeEcosystemHandler[]`           | 否    | `[]`                     | 用于钱包/RPC 桥接的生态系统处理器                                             |
| `iframeOrigin` | `string`                             | 否    | 从 `src` 派生               | 将 `postMessage` 限制到此来源                                          |
| `autoResize`   | `boolean`                            | 否    | `false`                  | 当为 `true` 时，iframe 高度自动调整以匹配内容                                  |
| `onConnect`    | `(args?: ConnectWalletArgs) => void` | 否    | --                       | 当 widget 请求连接钱包时调用                                              |
| `style`        | `CSSProperties`                      | 否    | --                       | iframe 元素的内联样式                                                  |
| `className`    | `string`                             | 否    | --                       | iframe 元素的 CSS 类                                                |
| `title`        | `string`                             | 否    | `'LI.FI Widget'`         | iframe 的无障碍标题                                                   |

### 示例

```tsx theme={"system"}
<LiFiWidgetLight
  config={{ integrator: 'my-app', variant: 'wide' }}
  handlers={[ethHandler, solHandler]}
  autoResize
  style={{ width: 392, borderRadius: 16 }}
/>
```

<Note>
  每个页面仅支持一个 `<LiFiWidgetLight>` 实例。事件总线和 guest bridge 是模块级单例。
</Note>

## `useWidgetLightHost(options)`

管理 postMessage 桥接主机端的底层钩子。如果你需要渲染自己的 `<iframe>` 元素而非使用 `<LiFiWidgetLight>` 组件，请使用它。

```tsx theme={"system"}
import { useWidgetLightHost } from '@lifi/widget-light'
```

### Options

| Option         | 类型                                   | 是否必填 | 默认值     | 说明                   |
| -------------- | ------------------------------------ | ---- | ------- | -------------------- |
| `config`       | `WidgetLightConfig`                  | 是    | --      | widget 配置            |
| `handlers`     | `IframeEcosystemHandler[]`           | 否    | `[]`    | 生态系统处理器              |
| `iframeOrigin` | `string`                             | 否    | `'*'`   | 用于消息过滤的预期 iframe 来源  |
| `autoResize`   | `boolean`                            | 否    | `false` | 通过 RESIZE 消息启用自动调整大小 |
| `onConnect`    | `(args?: ConnectWalletArgs) => void` | 否    | --      | 外部钱包连接回调             |

### 返回值

| 字段          | 类型                                     | 说明                       |
| ----------- | -------------------------------------- | ------------------------ |
| `iframeRef` | `RefObject<HTMLIFrameElement \| null>` | 附加到你的 `<iframe>` 元素的 ref |

### 示例

```tsx theme={"system"}
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()`

返回一个类型化的事件发射器，用于订阅 widget 事件。可以从任何组件调用 -- 无需 provider 包裹。

```tsx theme={"system"}
import { useWidgetLightEvents } from '@lifi/widget-light'
```

### 返回值

```tsx theme={"system"}
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
}
```

### 示例

```tsx theme={"system"}
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])
```

完整的事件参考请见 [Widget Light 事件](/widget/widget-light-events)。

## 类型

**`WidgetLightChainType` 与 `WidgetChainType`：** 这两个联合类型都描述生态系统的判别标识，并包含用于 Tron 的 TVM。在 iframe 的 **postMessage** 协议中使用 **`WidgetLightChainType`**（例如 `IframeEcosystemHandler.chainType`）。在**面向主机的配置类型**（例如 `ConnectWalletArgs.chainType`，即托管的 widget 告知你的应用要连接哪个生态系统）中使用 **`WidgetChainType`**。这两个名称之所以不同，是因为协议层级的类型和配置层级的类型在包中是分开定义的。

### `WidgetLightConfig`

主配置类型。必须可 JSON 序列化。完整参考请见 [配置 Widget Light](/widget/widget-light-configuration)。

```tsx theme={"system"}
import type { WidgetLightConfig } from '@lifi/widget-light'
```

必填字段：`integrator: string`

### `ConnectWalletArgs`

当 widget 请求连接钱包时传递给 `onConnect` 回调的参数：

```tsx theme={"system"}
import type { ConnectWalletArgs } from '@lifi/widget-light'
```

| 字段          | 类型                             | 说明                                              |
| ----------- | ------------------------------ | ----------------------------------------------- |
| `chainId`   | `number \| undefined`          | 目标链 ID                                          |
| `chainType` | `WidgetChainType \| undefined` | 目标链类型（`'EVM'`、`'SVM'`、`'UTXO'`、`'MVM'`、`'TVM'`） |

### `IframeEcosystemHandler`

由所有生态系统处理器实现的接口：

```tsx theme={"system"}
import type { IframeEcosystemHandler } from '@lifi/widget-light'
```

| 方法                                   | 类型                           | 说明                                           |
| ------------------------------------ | ---------------------------- | -------------------------------------------- |
| `chainType`                          | `WidgetLightChainType`       | `'EVM' \| 'SVM' \| 'UTXO' \| 'MVM' \| 'TVM'` |
| `getInitState()`                     | `EcosystemInitState \| null` | 返回用于 INIT 握手的初始钱包状态                          |
| `handleRequest(id, method, params?)` | `Promise<unknown>`           | 处理来自 iframe 的 RPC 请求                         |
| `subscribe(emit)`                    | `() => void`                 | 订阅钱包状态变化；返回取消订阅函数                            |

### `WidgetLightEvent`

所有事件名称的枚举。其取值和 payload 类型请见 [Widget Light 事件](/widget/widget-light-events)。

```tsx theme={"system"}
import { WidgetLightEvent } from '@lifi/widget-light'
```

### `WidgetLightChainType`

用于 postMessage 协议的链类型判别标识：

```tsx theme={"system"}
type WidgetLightChainType = 'EVM' | 'SVM' | 'UTXO' | 'MVM' | 'TVM'
```

### `WidgetChainType`

用于配置的扩展链类型（包含 TVM）：

```tsx theme={"system"}
type WidgetChainType = 'EVM' | 'SVM' | 'MVM' | 'UTXO' | 'TVM'
```

## FAQ

### 我可以在同一页面上运行多个 widget 吗？

不可以。`@lifi/widget-light` 对事件总线和 guest bridge 使用模块级单例。每个页面仅支持一个 `<LiFiWidgetLight>` 实例。

### `src` 应该使用什么 URL？

默认值（`https://widget.li.fi`）是生产环境托管的 widget。在大多数用例中，你完全不需要设置 `src`。若要针对特定版本或自托管的部署进行测试，请将你的自定义 URL 作为 `src` 传入。

### 为什么 config 必须可 JSON 序列化？

配置通过 `postMessage` 发送到 iframe，而 `postMessage` 使用结构化克隆算法。React 节点、函数、类实例和 MUI 主题对象无法被克隆。`WidgetLightConfig` 类型只暴露可序列化的字段（不含 React 节点、回调或 MUI 主题对象），因此类型系统会在编译时拒绝大多数不可序列化的值。这是通过省略字段来实现约束，而非一种通用的可序列化性检查，因此仍要确保你传入的任何值在运行时都是可 JSON 序列化的。

### 自动调整大小是如何工作的？

当 `autoResize` 为 `true` 时，iframe 内容使用 `ResizeObserver` 检测高度变化并将其发布到主机。主机直接设置 `iframe.style.height` 以实现零闪烁的更新。如果你想自行通过 CSS 控制 iframe 尺寸，请设置 `autoResize={false}`。

### 页面刷新后我需要处理重新连接吗？

在每次挂载时，钱包状态会通过 `INIT` 握手从你的应用发送到 iframe。如果你的 wagmi/wallet-adapter 处理重新连接（大多数默认情况下都会），widget 将自动接收到重新连接后的状态。

### 安全性是如何处理的？

`iframeOrigin` 会自动从 `src` 派生（默认为 `https://widget.li.fi`），因此 `postMessage` 通信被限制到正确的来源。来自其他来源的消息会被静默丢弃。只有当你想覆盖派生出的值时，才需要显式设置 `iframeOrigin`。

### 我在哪里可以找到可运行的示例？

widget 仓库包含两个示例：

* **vite-iframe-wagmi** -- 最小化的仅 EVM 集成
* **vite-iframe** -- 完整的多生态系统设置，包含事件、配置响应式和外部钱包管理

在本地运行它们：

```bash theme={"system"}
# From the widget repository root
pnpm install
pnpm --filter vite-iframe-wagmi dev
# or
pnpm --filter vite-iframe dev
```
