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

# client.setupWidget()

> Render the MoonPay buy widget and start a transaction.

Render the MoonPay buy widget and initiate a transaction with a quote
signature. The quote must have `executable: true` — a non-executable quote will
not render. The provider presents the widget in a full-screen native modal and
handles the full purchase flow — including payment collection, verification,
and transaction confirmation.

```tsx Setup widget focus={5-30} theme={null}
import {
  useMoonPay,
  type WidgetEvent,
} from "@moonpay/platform-sdk-react-native";

export function WidgetScreen({ quoteSignature }: { quoteSignature: string }) {
  const { client } = useMoonPay();

  const start = async () => {
    const widgetResult = await client.setupWidget({
      quote: quoteSignature,
      onEvent: (event: WidgetEvent) => {
        switch (event.kind) {
          case "ready":
            break;
          case "transactionCreated":
            console.log(event.payload.transaction);
            break;
          case "complete":
            console.log(event.payload.transaction);
            break;
          case "close":
            // The customer closed the widget
            break;
          case "error":
            console.error(event.payload.code, event.payload.message);
            break;
        }
      },
    });

    if (!widgetResult.ok) {
      // Handle error
      console.error(widgetResult.error.kind, widgetResult.error.message);
      return;
    }

    const widget = widgetResult.value;
  };

  // ...
}
```

***

## Parameters

| Property | Type | Required | Description |
| - | - | - | - |
| `quote` | `string` | ✅ | The quote `signature` returned from [`getQuote`](/platform/sdk-reference/react-native/get-quote). |
| `externalTransactionId` | `string` | | Partner-assigned identifier for this transaction attempt. Useful for reconciliation. |
| `onEvent` | `(event: WidgetEvent) => void` | | Callback invoked for widget flow events. See [`WidgetEvent`](#widgetevent). |

This method does not require a separate auth token. The client uses stored credentials from an active connection.

### `WidgetEvent`

`onEvent` receives events as the widget flow progresses. Use `event.kind` to decide how to handle each event.

| kind | Payload | When you receive it |
| - | - | - |
| `"ready"` | — | The widget is loaded and ready to be shown. |
| `"transactionCreated"` | `{ transaction: { id: string; status: string } }` | A transaction has been created. The customer may still need to complete additional steps (for example, 3-D Secure). |
| `"complete"` | `{ transaction:` [`FrameTransaction`](#frametransaction) `}` | The widget flow finished. `FrameTransaction` is a discriminated union — handle the `"failed"` variant separately. |
| `"close"` | — | The customer closed the widget. |
| `"error"` | [`WidgetEventError`](#widgeteventerror) | The flow encountered an error. |

#### `FrameTransaction`

The transaction reported by the widget on `"complete"`. The shape depends on the outcome.

| Field | Type | Required | Description |
| - | - | - | - |
| `id` | `string` | | Present on the success variant. Required when `status !== "failed"`; optional when `status` is `"failed"`. |
| `status` | `string` | ✅ | The transaction status. On the failure variant this is `"failed"`. |
| `failureReason` | `string` | | Present only on the failure variant (`status === "failed"`). |

To track the final status after `"complete"`, pass `transaction.id` to [`client.getTransaction()`](/platform/sdk-reference/react-native/get-transaction).

#### `WidgetEventError`

| Field | Type | Required | Description |
| - | - | - | - |
| `code` | `"configurationError"` \| `"apiError"` \| `"generic"` | ✅ | The error category. |
| `message` | `string` | ✅ | Developer-friendly details. |

## Result

`client.setupWidget()` returns a `Result<WidgetFrame, SetupWidgetError>`.

### Result envelope

`Result<WidgetFrame, SetupWidgetError>`

| Field | Type | Required | Description |
| - | - | - | - |
| `ok` | `boolean` | ✅ | Whether the operation succeeded. |
| `value` | [`WidgetFrame`](#widgetframe) | | Present when `ok` is `true`. |
| `error` | [`SetupWidgetError`](#setupwidgeterror) | | Present when `ok` is `false`. |

### `WidgetFrame`

| Field | Type | Required | Description |
| - | - | - | - |
| `dispose` | `() => void` | ✅ | Unmounts the frame. After you call this, no further events are dispatched to your `onEvent` callback. |

### `SetupWidgetError`

| Field | Type | Required | Description |
| - | - | - | - |
| `kind` | `"configurationError"` \| `"apiError"` \| `"genericError"` | ✅ | The error category. |
| `message` | `string` | ✅ | Developer-friendly details. |

<Accordion title="TS Definitions">
  ```ts types.ts theme={null}
  type WidgetFrame = {
    dispose: () => void;
  };

  type FrameTransaction =
    | { id: string; status: string }
    | { id?: string; status: "failed"; failureReason: string };

  type WidgetEvent =
    | { kind: "ready" }
    | {
        kind: "transactionCreated";
        payload: { transaction: { id: string; status: string } };
      }
    | {
        kind: "complete";
        payload: { transaction: FrameTransaction };
      }
    | { kind: "close" }
    | { kind: "error"; payload: WidgetEventError };

  type WidgetEventError = {
    code: "configurationError" | "apiError" | "generic";
    message: string;
  };

  type SetupWidgetError = {
    kind: "configurationError" | "apiError" | "genericError";
    message: string;
  };
  ```
</Accordion>
