> ## Documentation Index
> Fetch the complete documentation index at: https://docs.relayer.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Guide

> Integrate widgets using Passkey Signing (passkey) or Metadata Mode (bring your own wallet) — with examples for Swap, Transfer, and Crosschain

This guide covers two integration paths: **Passkey Signing** where the widget handles passkey-based signing for you, and **Metadata Mode** where you receive transaction metadata to sign with your own stack. Both modes use the same Widget component.

<Info>
  **Prerequisites:** wagmi providers configured per [Installation](/widget/installation). An understanding of your integration mode — see the [Overview](/widget/overview) for architecture details.
</Info>

## Passkey Signing Integration

In Passkey Signing, the widget manages the full transaction lifecycle: prepare, sign via passkey, and confirm. You provide a wallet adapter and an action URL or widget ID.

<Steps>
  <Step title="Create the adapter">
    Use the `useWagmiAdapter` hook and render a `Widget` with your action URL:

    ```tsx src/components/SwapWidget.tsx theme={null}
    'use client';
    import { useWagmiAdapter, Widget } from '@relayerfi/widget-kit-react';

    export function SwapWidget() {
      const adapter = useWagmiAdapter();
      return (
        <Widget
          adapter={adapter}
          url="https://api.relayer.fi/v1/action/{widgetId}/metadata"
        />
      );
    }
    ```

    The Widget component handles the entire signing flow automatically. When a user initiates an action, the widget calls `POST /v1/transactions/prepare` to get an unsigned transaction, prompts the user with a passkey biometric challenge, and then calls `POST /v1/transactions/confirm` with the signed result.
  </Step>

  <Step title="User signs with passkey">
    The widget renders a biometric prompt (Face ID, fingerprint, or security key). Signing happens inside a secure enclave — the private key never leaves the hardware-protected environment. No additional code is needed on your side.
  </Step>

  <Step title="Transaction confirmation">
    After the user signs, the widget automatically submits the signed transaction to Relayer for broadcast. The widget shows a success state with the transaction hash.
  </Step>
</Steps>

<Tip>
  In Passkey Signing, the Widget component manages the full prepare → sign → confirm lifecycle. You only need to provide the adapter and the action URL.
</Tip>

## Metadata Mode Integration

In Metadata Mode, the widget handles UI and user input, but signing is delegated to your stack. You receive transaction metadata (routing, calldata, gas estimates) and handle signing and broadcast yourself.

<Steps>
  <Step title="Render the Widget">
    The Widget renders the same UI as Passkey Signing. Provide a wallet adapter and action URL:

    ```tsx src/components/SwapWidget.tsx theme={null}
    'use client';
    import { useWagmiAdapter, Widget } from '@relayerfi/widget-kit-react';

    export function SwapWidget() {
      const adapter = useWagmiAdapter();
      return (
        <Widget
          adapter={adapter}
          url="https://api.relayer.fi/v1/action/{widgetId}/metadata"
        />
      );
    }
    ```

    The Widget renders the same UI, but in Metadata Mode the signing step is delegated to your infrastructure.
  </Step>

  <Step title="Handle transaction metadata">
    When your integrator is configured for Metadata Mode, the Relayer API returns routing and calldata for your application to sign:

    ```typescript theme={null}
    const response = await fetch('https://api.relayer.fi/v1/action/execute/swap/quote', {
      method: 'GET',
      headers: {
        'Authorization': `ApiKey ${apiKey}`,
      },
    });
    const { routing, calldata, gasEstimate } = await response.json();

    // Build and sign with your own wallet infrastructure
    const tx = buildTransaction(routing, calldata, gasEstimate);
    const signedTx = await yourSigner.signTransaction(tx);
    const txHash = await yourProvider.sendTransaction(signedTx);
    ```
  </Step>

  <Step title="Broadcast">
    You are responsible for broadcasting the signed transaction to the blockchain. Use your own RPC provider or infrastructure.
  </Step>
</Steps>

<Note>
  In Metadata Mode, the widget UI still renders action cards and handles user input. The difference is in how signing is handled — your backend receives the transaction parameters instead of completing the flow inside the widget.
</Note>

## Widget Examples

Widget Kit ships first-party widgets for the canonical protocols Relayer supports. All examples use the same Widget component pattern — only the action URL differs.

<Tabs>
  <Tab title="Swap">
    ```tsx theme={null}
    import { useWagmiAdapter, Widget } from '@relayerfi/widget-kit-react';

    export function SwapWidget() {
      const adapter = useWagmiAdapter();
      return (
        <Widget
          adapter={adapter}
          url="https://api.relayer.fi/v1/action/{widgetId}/metadata"
        />
      );
    }
    ```

    Swap widget renders a token-to-token swap card. Backed by `POST /v1/action/builders/swap` and executed via `/v1/action/execute/swap/*`.
  </Tab>

  <Tab title="Transfer">
    ```tsx theme={null}
    import { useWagmiAdapter, Widget } from '@relayerfi/widget-kit-react';

    export function TransferWidget() {
      const adapter = useWagmiAdapter();
      return (
        <Widget
          adapter={adapter}
          url="https://api.relayer.fi/v1/action/{widgetId}/metadata"
        />
      );
    }
    ```

    Transfer widget handles native token and ERC20 transfers. Backed by `POST /v1/action/builders/transfer-native`.
  </Tab>

  <Tab title="Crosschain Transfer">
    ```tsx theme={null}
    import { useWagmiAdapter, Widget } from '@relayerfi/widget-kit-react';

    export function CrosschainTransferWidget() {
      const adapter = useWagmiAdapter();
      return (
        <Widget
          adapter={adapter}
          url="https://api.relayer.fi/v1/action/{widgetId}/metadata"
        />
      );
    }
    ```

    Crosschain transfer widget moves the same asset across supported networks. Backed by `POST /v1/action/builders/crosschain-transfer`.
  </Tab>

  <Tab title="Crosschain Bridge">
    ```tsx theme={null}
    import { useWagmiAdapter, Widget } from '@relayerfi/widget-kit-react';

    export function BridgeWidget() {
      const adapter = useWagmiAdapter();
      return (
        <Widget
          adapter={adapter}
          url="https://api.relayer.fi/v1/action/{widgetId}/metadata"
        />
      );
    }
    ```

    Bridge widget moves assets between supported chains. Backed by `POST /v1/action/builders/crosschain-bridge`.
  </Tab>
</Tabs>

## Embedder: End-User Onboarding

For Embedder integrators using Passkey Signing, each end user gets their own wallet and passkey. The onboarding flow:

<Steps>
  <Step title="User registers passkey">
    When a new end user first interacts with a widget, they are prompted to create a passkey (biometric or security key). This registers a WebAuthn credential tied to your application's wallet workspace.
  </Step>

  <Step title="Wallet creation">
    A wallet is automatically created in the user's workspace. The private key is generated and stored inside a hardware-secured enclave — neither you nor Relayer can access it.
  </Step>

  <Step title="Subsequent transactions">
    For future transactions, the user simply approves with their passkey. No seed phrases, no browser extensions.
  </Step>
</Steps>

<Warning>
  Passkey recovery is available through Relayer's email recovery flow (`POST /v1/signing/recovery/initiate`). Ensure you communicate recovery options to your users during onboarding.
</Warning>

<Tip>
  For workspace-level integrations (not end-user facing), team members register passkeys through the Relayer dashboard. Policies define which team members can approve which transaction types.
</Tip>

## WidgetProps Reference

| Prop              | Type                  | Required              | Description                                                              |
| ----------------- | --------------------- | --------------------- | ------------------------------------------------------------------------ |
| `adapter`         | `WidgetAdapter`       | Yes                   | Wallet adapter — use `useWagmiAdapter()` or `createWagmiAdapter(config)` |
| `url`             | `string`              | Yes\*                 | URL to fetch widget metadata from                                        |
| `metadata`        | `ValidatedMetadata`   | Yes\*                 | Pass pre-validated metadata instead of `url`                             |
| `securityState`   | `WidgetSecurityState` | Yes (with `metadata`) | Security context for pre-validated flow                                  |
| `stylePreset`     | `'x' \| undefined`    | No                    | Apply Twitter/X visual preset                                            |
| `enableAnalytics` | `boolean`             | No                    | Track interaction events (default: `true`)                               |
| `player`          | `boolean`             | No                    | Enable player mode for embedded contexts                                 |
| `className`       | `string`              | No                    | Additional CSS class on the root element                                 |
| `startDisabled`   | `boolean`             | No                    | Render widget in disabled state                                          |

<Note>
  Either `url` or `metadata` + `securityState` must be provided, not both.
</Note>

## Theming

Widgets read `data-x-theme="dark|light"` from the document root to determine the active theme.

### Automatic Theme Detection (Twitter/X)

Call `applyXTheme()` once on mount to read the Twitter/X night mode cookie and set the theme attribute automatically:

```typescript theme={null}
import { applyXTheme } from '@relayerfi/widget-kit-react';

// Call once on mount
applyXTheme();
```

### React Hook

Use the `useTheme` hook to read the current theme in your components:

```typescript theme={null}
import { useTheme } from '@relayerfi/widget-kit-react';

function MyComponent() {
  const theme = useTheme(); // 'dark' | 'light'
  return <div data-theme={theme}><Widget ... /></div>;
}
```

### Manual Override

Set the attribute directly on `document.documentElement` for custom toggle UIs:

```typescript theme={null}
document.documentElement.setAttribute('data-x-theme', 'dark');
```

## Twitter/X stylePreset

Pass `stylePreset="x"` to apply the Twitter/X visual preset — rounded card, correct font sizing, consistent with the embedded appearance on social platforms:

```tsx theme={null}
<Widget adapter={adapter} url={url} stylePreset="x" />
```

## Platform Observers

The library ships observers for automatic widget detection on Twitter/X, YouTube, and Twitch. These observers scan the DOM for canonical action URLs and render Widget components inline. For custom embedding in your own app, use the `Widget` component directly as shown above. See the [Widget Kit Overview](/widget/overview) for architecture details.

## Next Steps

<CardGroup cols={2}>
  <Card title="SDK Reference" icon="code" href="/widget/sdk">
    The metadata schema for canonical protocols.
  </Card>

  <Card title="Widget Kit Overview" icon="layer-group" href="/widget/overview">
    Package ecosystem and architecture.
  </Card>
</CardGroup>
