# React Integration

# React integration

There are two layers, and most apps use both:

- **The web components.** Drop `<frak-button-share>`, `<frak-banner>`, and `<frak-post-purchase>` straight into your JSX. No provider, no hooks. Start here.
- **`@frak-labs/react-sdk`.** Providers and hooks for custom flows: wallet status, modals, referrals, SSO, transactions.

## Prerequisites

1. A React 18 or 19 project.
2. A merchant account on the [Frak business dashboard](https://business.frak.id/) with your domain registered. The main domain is registered at sign-up; add subdomains under **Allowed Domains**.

If you have not done that yet, start with the [Get started guide](/guides/).

## The components in JSX

Install `@frak-labs/components`, set the config in its own module, and function App() {
  return (
    <FrakProvider>
      {/* Your app content */}
    </FrakProvider>
  );
}

export default App;
```

**domain is filled in for you:** `FrakConfigProvider` defaults `domain` to `window.location.host`. Set it explicitly if you render server-side, otherwise it falls back to `not-found` during SSR.

The config takes the same fields as everywhere else. See [FrakSetup](/developers/components/frak-setup/) and [Configuration](/developers/concepts/configuration/).

**Targeting the dev stage:** `env` states both origins the SDK talks to: `"prod"` (the default), `"dev"`, or an explicit `{ wallet, backend }` pair for local development. It replaces `walletUrl` and lands in the next major of the SDK, so on the version published today use `walletUrl` instead. See [Configuration](/developers/concepts/configuration/).

### 3. Read the wallet status

```tsx twoslash title="WalletStatus.tsx"
// @noErrors
// [!include ~/snippets/integration/react-app.tsx:wallet-status]
```

### 4. Open a modal

```tsx twoslash title="LoginButton.tsx"
// @noErrors
// [!include ~/snippets/integration/react-app.tsx:login-button]
```

### 5. Put it together

```tsx twoslash
// @noErrors
// [!include ~/snippets/integration/react-app.tsx:app]
```

```tsx twoslash
// @noErrors
// [!include ~/snippets/integration/react-app.tsx]
```

```tsx twoslash
// @noErrors
// [!include ~/snippets/integration/FrakProvider.tsx]
```

## Every hook

| Hook | Returns | What it does |
| --- | --- | --- |
| `useWalletStatus()` | query | Current wallet status, kept in sync |
| `useDisplayModal()` | mutation | Open a modal from steps, with an optional `placement` |
| `useDisplaySharingPage()` | mutation | Open the sharing page |
| `useReferralInteraction()` | value | Processes an inbound referral once the client is ready, returns the state or an error |
| `useSetupReferral()` | side effect | Wires referral handling, emits `frak:referral-success` |
| `useGetMerchantInformation()` | query | Your merchant data as resolved by the backend |
| `useGetUserReferralStatus()` | query | The user's referral state |
| `useGetMergeToken()` | query | Token used to merge a wallet |
| `useSiweAuthenticate()` | mutation | Sign-In with Ethereum |
| `useSendTransactionAction()` | mutation | Ask the wallet to send a transaction |
| `useOpenSso()` | mutation | Open the SSO flow |
| `usePrepareSso(params)` | query | Prepare an SSO session |
| `usePrepareSsoUrl(params)` | query | Build the SSO URL ahead of time, so the open is a direct user gesture and dodges popup blockers |
| `useFrakClient()` | value | The raw client, or `undefined` before it is ready |
| `useFrakConfig()` | value | The resolved config. Throws outside a `FrakConfigProvider` |

Most mutation hooks take an optional `{ mutations }` object of React Query options, and most query hooks take `{ query }`. Two exceptions: `useWalletStatus()` takes no argument, and `usePrepareSso(params)` takes the SSO parameters directly.

Full signatures live in the [generated SDK reference](/developers/references/readme/).

## Handle an inbound referral

One hook is enough on the page a referred visitor lands on:

```tsx
export function ReferralHandler() {
  const state = useReferralInteraction();
  // "idle" | "processing" | a referral state | an Error
  return null;
}
```

## Track a purchase

Purchase tracking has no hook: call the action, which needs no client.

```tsx
await trackPurchaseStatus({
  customerId: "cust_123",
  orderId: "order_456",
  token: "a-unique-order-token",
});
```

Rewards are only released once your backend confirms the order with a signed webhook. See [Validate purchases from your backend](/guides/platforms/custom/backend/).

## Next steps

[Components reference](/developers/components/)
  [SDK reference](/developers/references/readme/)
  [Interactions](/developers/concepts/interactions/)
  [Backend validation](/guides/platforms/custom/backend/)