> For the complete documentation index, see [llms.txt](https://docs.swapper.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.swapper.finance/tracking-deposits/widget-events.md).

# Widget Events

The widget emits structured events via `window.postMessage()` from inside the iframe to your parent page. This lets you react to what the user does — most importantly, a completed deposit — in real time, with no polling.

Widget events are for **in-browser UX**. For reliable server-side accounting, pair them with [webhooks](/tracking-deposits/webhooks.md).

## The event envelope

Every event posted from the widget has this shape:

```typescript
interface SwapperWidgetEvent {
  type: "SWAPPER_EVENT";       // discriminator — filter on this
  version: "1.0";              // protocol version
  name: WidgetEventName;       // e.g. "transaction_success"
  timestamp: string;           // ISO 8601
  payload: WidgetEventPayload; // event-specific data
}
```

| Field       | Description                                                         |
| ----------- | ------------------------------------------------------------------- |
| `type`      | Always `"SWAPPER_EVENT"` — use it to ignore unrelated postMessages. |
| `version`   | Protocol version (currently `"1.0"`).                               |
| `name`      | Event name (see [below](#event-types)).                             |
| `timestamp` | When it was emitted (ISO 8601).                                     |
| `payload`   | Event-specific data.                                                |

## Three ways to listen

### `onEvent` (recommended)

Pass a callback in the config — it receives every event:

```typescript
import { SwapperIframe, WidgetEventName } from "@swapper-finance/deposit-sdk";
import type { TransactionSuccessPayload } from "@swapper-finance/deposit-sdk";

const swapper = new SwapperIframe({
  // ...required config
  onEvent: (event) => {
    if (event.type === WidgetEventName.TRANSACTION_SUCCESS) {
      const payload = event.data as TransactionSuccessPayload;
      console.log("Deposit complete:", payload.txHash);
    }
  },
});
```

Works with `openSwapperModal` too.

### `on()` / `off()`

Register handlers on the instance; `"*"` catches everything:

```typescript
swapper.on(WidgetEventName.TRANSACTION_SUCCESS, (event) => { /* … */ });
swapper.on("*", (event) => console.log(event.type, event.data));
swapper.off(WidgetEventName.TRANSACTION_SUCCESS, handler);
```

### Raw `window.addEventListener`

If you're not using the SDK's listeners (or you embed the widget directly), read the messages yourself:

```typescript
import { WIDGET_EVENT_PROTOCOL_VERSION, WidgetEventName } from "@swapper-finance/deposit-sdk";
import type { SwapperWidgetEvent, TransactionSuccessPayload } from "@swapper-finance/deposit-sdk";

window.addEventListener("message", (event: MessageEvent) => {
  if (event.data?.type !== "SWAPPER_EVENT") return;
  const message = event.data as SwapperWidgetEvent;
  if (message.version !== WIDGET_EVENT_PROTOCOL_VERSION) return;

  if (message.name === WidgetEventName.TRANSACTION_SUCCESS) {
    const payload = message.payload as TransactionSuccessPayload;
    console.log("Tx:", payload.txHash, "Explorer:", payload.explorerUrl);
  }
});
```

## Event types

`WidgetEventName` currently defines:

| Name                  | Value                   | Meaning                                                 |
| --------------------- | ----------------------- | ------------------------------------------------------- |
| `TRANSACTION_SUCCESS` | `"transaction_success"` | A deposit completed successfully.                       |
| `RESIZE`              | `"resize"`              | The widget's required height changed (flexible height). |
| `CLOSE_REQUEST`       | `"close_request"`       | The widget is asking the host to close it.              |

### `transaction_success`

Emitted when a deposit completes.

| Field            | Type      | Description                                                               |
| ---------------- | --------- | ------------------------------------------------------------------------- |
| `depositOption`  | `string`  | Flow used: `"walletDeposit"`, `"transferCrypto"`, or `"depositWithCash"`. |
| `txHash`         | `string?` | On-chain transaction hash, when available.                                |
| `explorerUrl`    | `string?` | Block-explorer link for the transaction.                                  |
| `tokenSymbol`    | `string?` | Symbol of the received token (e.g. `"USDC"`).                             |
| `tokenAddress`   | `string?` | Contract address of the received token.                                   |
| `chainId`        | `string?` | Chain id where the token was received.                                    |
| `amountReceived` | `string?` | Human-readable amount received.                                           |

### `resize`

Emitted when [flexible height](/widget-integration/modal-and-embed.md#flexible-height) is on and the home page's content height changes. Payload: `{ height: number }` (CSS pixels). The modal/embed animates to this automatically; if you host the iframe yourself, resize it to match.

### `close_request`

The widget requests to be dismissed (e.g. a close affordance was tapped). Handle it by closing your modal/container.

## Extensibility

New event names will be added to `WidgetEventName` over time. **Filter by the `name` string** and ignore names you don't recognize — new events can ship without an SDK bump, and old integrations keep working.

## Events vs. webhooks

|             | Widget event           | [Webhook](/tracking-deposits/webhooks.md) |
| ----------- | ---------------------- | ----------------------------------------- |
| Channel     | Browser `postMessage`  | Server-to-server HTTP                     |
| Latency     | Instant                | Seconds                                   |
| Reliability | Lost if the tab closes | Retried, signed                           |
| Use for     | Live UI updates        | Crediting accounts (source of truth)      |

Use both.
