> ## 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.setupBuyButton()

> Render the MoonPay-hosted buy button and run the buy pipeline on tap.

<Callout icon="triangle-exclamation" iconType="regular">
  `client.setupBuyButton()` is deprecated. Use the
  [`<MoonPayBuyButton>`](/platform/sdk-reference/react-native/components/moonpay-buy-button)
  component instead — it renders the buy button inline exactly where you place
  it in your layout. The imperative method presents the frame in a full-screen
  modal, which is rarely the right UX for a payment button.
</Callout>

Render the [Buy button frame](/platform/frames/buy) in your app. The provider
presents the frame in a full-screen native modal showing a payment button —
card, Apple Pay, or Google Pay, depending on what's available — and runs the
buy pipeline on tap. Use it when you want a single payment button instead of
orchestrating individual payment-method frames yourself.

<Callout icon="circle-info" iconType="regular">
  Like the headless [Buy frame](/platform/sdk-reference/react-native/setup-buy),
  the buy button can emit a `challenge` event mid-pipeline. Render a separate
  challenge frame using
  [`client.setupChallenge()`](/platform/sdk-reference/react-native/setup-challenge)
  at the URL from the event payload.
</Callout>

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

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

  const start = async () => {
    const buyButtonResult = await client.setupBuyButton({
      quote: quoteSignature,
      onEvent: (event: BuyButtonEvent) => {
        switch (event.kind) {
          case "complete":
            // Inspect FrameTransaction before polling.
            if (event.payload.transaction.status !== "failed") {
              pollTransaction(event.payload.transaction.id);
            }
            break;
          case "challenge":
            // Hand off to the challenge frame at the provided URL.
            handleChallenge(event.payload.url);
            break;
          case "error":
            console.error(event.payload.code, event.payload.message);
            break;
        }
      },
    });

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

    const buyButton = buyButtonResult.value;
  };

  // ...
}
```

***

## Parameters

| Property  | Type                              | Required | Description                                                                                       |
| --------- | --------------------------------- | -------- | ------------------------------------------------------------------------------------------------- |
| `quote`   | `string`                          | ✅        | The quote `signature` returned from [`getQuote`](/platform/sdk-reference/react-native/get-quote). |
| `onEvent` | `(event: BuyButtonEvent) => void` |          | Callback invoked for buy-button events. See [`BuyButtonEvent`](#buybuttonevent).                  |

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

### `BuyButtonEvent`

`onEvent` receives events as the buy pipeline progresses. Unlike `setupBuy()`, the buy-button frame does **not** emit a `ready` event — the button renders synchronously and there is nothing to wait for before showing it.

| kind          | Payload                                                      | When you receive it                                                                                                                                                    |
| ------------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `"complete"`  | `{ transaction:` [`FrameTransaction`](#frametransaction) `}` | The pipeline finished. Inspect the `FrameTransaction` to detect the failure variant.                                                                                   |
| `"challenge"` | `{ kind: string; url: string }`                              | Verification is required before the transaction can proceed. Render the [challenge frame](/platform/sdk-reference/react-native/setup-challenge) at the provided `url`. |
| `"error"`     | [`BuyButtonEventError`](#buybuttoneventerror)                | The flow encountered an error. Surface to logs and tear down the frame.                                                                                                |

#### `FrameTransaction`

`FrameTransaction` is a discriminated union — the failure variant carries `failureReason`, the non-failure variant always carries `id`. Pass `id` to [`client.getTransaction()`](/platform/sdk-reference/react-native/get-transaction) to poll for the final status.

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

#### `BuyButtonEventError`

| Field     | Type     | Required | Description                                                                                          |
| --------- | -------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `code`    | `string` | ✅        | The error category. Includes `configurationError`, `invalidQuote`, and backend-specific error codes. |
| `message` | `string` | ✅        | Developer-friendly details. Not intended to be rendered in UI.                                       |

## Result

`client.setupBuyButton()` returns a `Result<BuyButtonFrame, SetupBuyButtonError>`.

### Result envelope

`Result<BuyButtonFrame, SetupBuyButtonError>`

| Field   | Type                                          | Required | Description                      |
| ------- | --------------------------------------------- | -------- | -------------------------------- |
| `ok`    | `boolean`                                     | ✅        | Whether the operation succeeded. |
| `value` | [`BuyButtonFrame`](#buybuttonframe)           |          | Present when `ok` is `true`.     |
| `error` | [`SetupBuyButtonError`](#setupbuybuttonerror) |          | Present when `ok` is `false`.    |

### `BuyButtonFrame`

| Field      | Type                          | Required | Description                                                                                                                                                              |
| ---------- | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `setQuote` | `(signature: string) => void` | ✅        | Updates the quote signature used by the frame. Use this when the current quote expires before the customer taps the button — fetch a new quote and pass its `signature`. |
| `dispose`  | `() => void`                  | ✅        | Unmounts the frame. After you call this, no further events are dispatched to your `onEvent` callback.                                                                    |

### `SetupBuyButtonError`

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

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

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

  type BuyButtonEvent =
    | {
        kind: "complete";
        payload: { transaction: FrameTransaction };
      }
    | {
        kind: "challenge";
        payload: { kind: string; url: string };
      }
    | { kind: "error"; payload: BuyButtonEventError };

  type BuyButtonEventError = {
    code: string;
    message: string;
  };

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