Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@
"docs/guides/warp-routes/evm-svm-warp-route-guide",
"docs/guides/warp-routes/evm-cosmos-warp-route-guide",
"docs/guides/warp-routes/cosmos-svm-warp-route-guide",
"docs/guides/warp-routes/bridge-ui-guide"
"docs/guides/warp-routes/bridge-ui-guide",
"docs/guides/warp-routes/embed-widget"
]
},
{
Expand Down
3 changes: 2 additions & 1 deletion docs/guides/warp-routes/bridge-ui-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
title: "Deploying a Bridge UI for your HWR"
---

After you've successfully [deployed a Hyperlane Warp Route (HWR)](/docs/guides/quickstart/deploy-warp-route), you have two out-of-the-box options for setting up a frontend UI to support interchain token transfers:
After you've successfully [deployed a Hyperlane Warp Route (HWR)](/docs/guides/quickstart/deploy-warp-route), you have three out-of-the-box options for setting up a frontend UI to support interchain token transfers:

1. **[Fork, customize, and deploy the Hyperlane Warp UI template](#fork--customize-the-ui)**
2. **[Use a managed Superbridge instance](#superbridge)**
3. **[Embed the bridge widget in your existing site](/docs/guides/warp-routes/embed-widget)** — drop a React component or iframe into your app

## 1. Hyperlane Warp UI Template

Expand Down
211 changes: 211 additions & 0 deletions docs/guides/warp-routes/embed-widget.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
title: "Embedding the Bridge Widget"
description: "Embed Hyperlane's bridge widget in your app using the @hyperlane-xyz/warp-widget SDK or a plain iframe"
---
Comment thread
paulbalaji marked this conversation as resolved.

You can add Hyperlane bridging directly into your site so users never have to leave your app. The [`@hyperlane-xyz/warp-widget`](https://www.npmjs.com/package/@hyperlane-xyz/warp-widget) SDK handles iframe creation, theming, and event listening.

## Install

```bash
pnpm add @hyperlane-xyz/warp-widget
Comment thread
paulbalaji marked this conversation as resolved.
# or
npm install @hyperlane-xyz/warp-widget
# or
yarn add @hyperlane-xyz/warp-widget
```

## React

```tsx
import { HyperlaneWarpWidget } from '@hyperlane-xyz/warp-widget/react';

function BridgePage() {
return (
<HyperlaneWarpWidget
config={{
theme: { accent: '3b82f6', mode: 'dark' },
defaults: { origin: 'ethereum', destination: 'arbitrum' },
routes: ['USDC/eclipsemainnet'],
}}
onEvent={(event) => console.log('Widget event:', event)}
width="420px"
height="600px"
/>
);
}
```

| Prop | Type | Default | Description |
| ----------- | ------------------ | ----------- | --------------------------- |
| `config` | `WarpWidgetConfig` | `undefined` | Theme, defaults, and routes |
| `onEvent` | `(event) => void` | `undefined` | Event callback |
| `width` | `string` | `'100%'` | Iframe width |
| `height` | `string` | `'600px'` | Iframe height |
| `className` | `string` | `undefined` | CSS class for the container |
| `style` | `CSSProperties` | `undefined` | Inline styles |

## Vanilla JS

Works with Vue, Angular, Svelte, or plain HTML — anything that can give you a DOM element.

```ts
import { createWarpWidget } from '@hyperlane-xyz/warp-widget';

const container = document.getElementById('widget-root');
if (!container) throw new Error('Missing #widget-root element');

const widget = createWarpWidget({
container,
config: {
Comment thread
coderabbitai[bot] marked this conversation as resolved.
theme: { accent: '3b82f6', mode: 'dark' },
defaults: { origin: 'ethereum', destination: 'base' },
},
});

widget.on('ready', (payload) => {
console.log('Widget ready at', payload?.timestamp);
});

// When you're done:
widget.destroy();
```

| Option | Type | Default | Description |
| ----------- | ------------------ | ----------- | --------------------------- |
| `container` | `HTMLElement` | required | DOM element to mount into |
| `config` | `WarpWidgetConfig` | `undefined` | Theme, defaults, and routes |
| `width` | `string` | `'100%'` | Iframe width |
| `height` | `string` | `'600px'` | Iframe height |

Returns `{ iframe, destroy, on }` — `iframe` is the raw `HTMLIFrameElement`, `destroy()` removes it and cleans up listeners, `on(event, callback)` subscribes to events and returns an unsubscribe function.

## Theme Colors

Control the widget's look by passing a `theme` object. All color values are hex strings **without the `#` prefix**.

```ts
config: {
theme: {
accent: '3b82f6',
bg: '0f172a',
card: '1e293b',
text: 'e2e8f0',
buttonText: 'ffffff',
border: '334155',
error: 'ef4444',
mode: 'dark',
},
}
```

| Property | Description | Default |
Comment thread
paulbalaji marked this conversation as resolved.
| ------------ | ----------------------------------------------- | ----------- |
| `accent` | Primary color for buttons, headers, and links | `9a0dff` |
| `bg` | Page background | transparent |
| `card` | Card and surface backgrounds | `ffffff` |
| `text` | Main text color | `010101` |
| `buttonText` | Text color inside buttons | `ffffff` |
| `border` | Border color | `bfbfbf40` |
| `error` | Error state color | `dc2626` |
| `mode` | `'dark'` or `'light'` — sets preset defaults | `light` |

Setting `mode: 'dark'` applies a full dark color scheme. You can still override individual colors on top — for example, `mode: 'dark'` with `accent: '22c55e'` gives a dark widget with green accents.

## Transfer Defaults

Pre-fill the transfer form so users land on a ready-to-go state instead of picking chains and tokens themselves.

```ts
config: {
defaults: {
origin: 'ethereum',
destination: 'arbitrum',
originToken: 'USDC',
destinationToken: 'USDC',
},
}
```

| Property | Description |
| ------------------ | ------------------------------------------ |
| `origin` | Origin chain name (e.g. `'ethereum'`) |
| `destination` | Destination chain name (e.g. `'arbitrum'`) |
| `originToken` | Origin token symbol (e.g. `'USDC'`) |
| `destinationToken` | Destination token symbol |

## Route Filtering

By default the widget shows all routes from the Hyperlane registry. To limit which routes your users see, pass their IDs:

```ts
config: {
routes: ['ETH/viction', 'USDC/eclipsemainnet'],
}
```

Route IDs are derived from the [Hyperlane Registry deployments](https://github.com/hyperlane-xyz/hyperlane-registry/tree/main/deployments/warp_routes) — the folder name is the symbol and the config file name is the route identifier. For example, `deployments/warp_routes/USDC/eclipsemainnet-config.yaml` becomes `USDC/eclipsemainnet`. Only specified routes will appear in the token selector.

## Events

The widget sends events to your app. Use `onEvent` in React or `widget.on()` in vanilla JS.

| Event | Payload | Description |
| ------- | --------------- | -------------------------------- |
| `ready` | `{ timestamp }` | Fires when the widget has loaded |
Comment thread
paulbalaji marked this conversation as resolved.

## Self-Hosting

The widget points to the Hyperlane-hosted Warp UI by default. If you [fork and deploy the Warp UI template](https://github.com/hyperlane-xyz/hyperlane-warp-ui-template) yourself, the `/embed` route is included automatically.

To restrict which sites can embed your instance, set the `NEXT_PUBLIC_EMBED_ALLOWED_ORIGINS` environment variable:

```text
NEXT_PUBLIC_EMBED_ALLOWED_ORIGINS=https://app-a.com https://app-b.com
```

If not set, any site can embed the widget (default: `*`). Set this in production to prevent unauthorized sites from embedding your instance.

## Alternative: No-Code Embed

If you can't install npm packages (e.g. WordPress, Shopify, Webflow), you can embed the widget with a plain iframe:

```html
<iframe
src="https://nexus.hyperlane.xyz/embed?accent=3b82f6&mode=dark&origin=ethereum&destination=arbitrum&routes=ETH/viction,USDC/eclipsemainnet"
width="420"
height="600"
style="border: none; border-radius: 12px;"
sandbox="allow-scripts allow-forms allow-same-origin allow-popups"
Comment thread
Xaroz marked this conversation as resolved.
allow="clipboard-write"
></iframe>
```

All [theme properties](#theme-colors) work as URL params, plus `origin`, `destination`, `originToken`, `destinationToken`, and `routes` (comma-separated).
Comment thread
Xaroz marked this conversation as resolved.

## Troubleshooting

### Widget doesn't load

Your site's Content Security Policy might be blocking the iframe. Add the Warp UI origin to your CSP `frame-src`:

```text
Content-Security-Policy: frame-src https://nexus.hyperlane.xyz;
```

### Wallet popups don't open

The iframe needs `allow-popups` in its sandbox for wallet extensions like MetaMask. The SDK sets this automatically — if using a raw iframe, make sure your `sandbox` attribute includes it.

## Examples

Working examples in the [hyperlane-monorepo](https://github.com/hyperlane-xyz/hyperlane-monorepo/tree/main/typescript/warp-widget/examples):
Comment thread
paulbalaji marked this conversation as resolved.

- **`vanilla/`** — Single HTML file, no build tools. Open in a browser.
- **`react-app/`** — Vite + React app showing both the React component and imperative API.

```bash
cd typescript/warp-widget/examples/react-app
pnpm install
pnpm dev
```
Loading