npm package: @puul/react-native-sdk
Description: Official React Native SDK for the Puul Partner API — prediction markets for mobile apps
Latest version: 1.5.0

# @puul/react-native-sdk

Official React Native SDK for the [Puul Partner API](https://ivorypay.gitbook.io/puul-api-documentation) — add prediction markets to your mobile app.

## Installation

```bash
npm install @puul/react-native-sdk react-native-webview
```

## Quick Start — API Client

```tsx
import { PuulPartner } from '@puul/react-native-sdk';

const puul = new PuulPartner({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
});

// List live markets
const markets = await puul.markets.list();

// Place a prediction
const prediction = await puul.predictions.place({
  marketId: markets[0].id,
  outcomeId: markets[0].outcomes[0].id,
  stakeAmount: 100000,
  stakeCurrency: 'NGN',
  idempotencyKey: 'unique-key-001',
});
```

## Quick Start — Drop-in UI (PuulConnect)

For zero-UI-work integration, use the `PuulConnect` component:

```tsx
import { PuulConnect } from '@puul/react-native-sdk';

function PredictionScreen({ navigation }) {
  return (
    <PuulConnect
      partnerKey="your-client-id"
      marketId="optional-market-uuid"
      theme="dark"
      onPredictionPlaced={(result) => {
        console.log('Prediction placed:', result.prediction);
        navigation.goBack();
      }}
      onClose={() => navigation.goBack()}
    />
  );
}
```

The `PuulConnect` component opens a hosted WebView where users can:
1. Browse available markets
2. Select an outcome
3. Enter stake amount
4. Place a prediction

The result is communicated back via the `onPredictionPlaced` callback.

## API Reference

### `puul.sessions`

| Method | Description |
|---|---|
| `createLinkToken(params)` | Create a link token for user account linking |
| `create(linkToken)` | Exchange a link token for a user session |

### `puul.markets`

| Method | Description |
|---|---|
| `list(countries?)` | List all live markets |

### `puul.predictions`

| Method | Description |
|---|---|
| `createQuote(params)` | Get a binding quote |
| `place(params)` | Place a prediction |
| `get(predictionId)` | Get prediction details |
| `list(options?)` | List predictions |

### `puul.wallet`

| Method | Description |
|---|---|
| `getBalance()` | Get user wallet balance |
| `getOmnibusBalance()` | Get partner omnibus balance |
| `getDepositAccount()` | Get deposit account details |
| `deposit(params)` | Deposit funds |
| `withdraw(params)` | Withdraw from omnibus to bank/crypto |

> **Auto-Settlement:** If your `payout_method` is configured (via the admin dashboard),
> revenue share is automatically paid out after each market settlement.

## PuulConnect Props

| Prop | Type | Required | Description |
|---|---|---|---|
| `partnerKey` | `string` | ✅ | Partner client ID |
| `marketId` | `string` | | Pre-select a specific market |
| `theme` | `'dark' \| 'light'` | | UI theme (default: dark) |
| `onPredictionPlaced` | `(result) => void` | | Called when prediction is placed |
| `onClose` | `() => void` | | Called when user closes |
| `onError` | `(error) => void` | | Called on error |
| `style` | `ViewStyle` | | Container style |

## Error Handling

```tsx
import { PuulError } from '@puul/react-native-sdk';

try {
  await puul.predictions.place(params);
} catch (error) {
  if (error instanceof PuulError) {
    console.error(error.code);       // 'INSUFFICIENT_BALANCE'
    console.error(error.statusCode); // 400
    console.error(error.retryable);  // false
  }
}
```

## Links

- [Documentation](https://ivorypay.gitbook.io/puul-api-documentation)
- [TypeScript SDK](https://www.npmjs.com/package/@puul/typescript-sdk)
- [Flutter SDK](https://github.com/Puul-Market/puul/tree/main/sdk-flutter)