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

# React SDK

> Complete guide for @yativo/crypto-sdk-react — provider setup, hooks, pre-built components, widgets, and theme customization

# React SDK

The `@yativo/crypto-sdk-react` package wraps the TypeScript SDK with React hooks and pre-built components, giving you managed authentication state, data-fetching hooks, and drop-in UI widgets.

[![npm version](https://img.shields.io/npm/v/@yativo/crypto-sdk-react?label=npm\&color=CB3837)](https://www.npmjs.com/package/@yativo/crypto-sdk-react)
[![npm weekly downloads](https://img.shields.io/npm/dw/@yativo/crypto-sdk-react?color=CB3837)](https://www.npmjs.com/package/@yativo/crypto-sdk-react)

## Installation

```bash theme={null}
npm install @yativo/crypto-sdk-react
# or
yarn add @yativo/crypto-sdk-react
```

**Package:** [`@yativo/crypto-sdk-react`](https://www.npmjs.com/package/@yativo/crypto-sdk-react) · **Latest:** `1.0.2` · **Requirements:** React 17 or higher. The TypeScript SDK (`@yativo/crypto-sdk`) is installed automatically as a peer dependency.

***

## Provider Setup

Wrap your application (or the relevant subtree) with `YativoProvider`. This creates the SDK instance and makes it available to all hooks and components below.

<Warning>
  Never expose `apiSecret` in client-side code. Do not use `NEXT_PUBLIC_YATIVO_API_SECRET` or any environment variable that gets bundled into the browser. For React apps, use passwordless login (`sdk.auth.login` + `sdk.auth.verifyOTP`) for client-side auth — or have your backend exchange API key credentials and return a short-lived access token to the frontend.
</Warning>

```tsx theme={null}
// app.tsx (or _app.tsx in Next.js)
import { YativoProvider } from "@yativo/crypto-sdk-react";

export default function App({ children }: { children: React.ReactNode }) {
  return (
    <YativoProvider
      config={{
        baseURL: "https://crypto-api.yativo.com/api/v1/",
        // Use passwordless login (sdk.auth.login + sdk.auth.verifyOTP) for client-side auth.
        // Do NOT pass apiSecret here — it would be exposed in the browser bundle.
      }}
    >
      {children}
    </YativoProvider>
  );
}
```

***

## `useYativo()` — Authentication & SDK Access

Login is passwordless and happens in two steps: send an OTP with `login(email)`, then verify it with `verifyOTP(otp, email)`.

```tsx theme={null}
import { useYativo } from "@yativo/crypto-sdk-react";

function LoginForm() {
  const { sdk, user, logout } = useYativo();
  const [email, setEmail]     = React.useState("");
  const [otp, setOtp]         = React.useState("");
  const [step, setStep]       = React.useState<"email" | "otp">("email");
  const [error, setError]     = React.useState<string | null>(null);

  async function handleSendOtp(e: React.FormEvent) {
    e.preventDefault();
    try {
      await sdk.auth.login(email);
      setStep("otp");
    } catch (err: any) {
      setError(err.message);
    }
  }

  async function handleVerifyOtp(e: React.FormEvent) {
    e.preventDefault();
    try {
      await sdk.auth.verifyOTP(otp, email);
    } catch (err: any) {
      setError(err.message);
    }
  }

  if (user) {
    return (
      <div>
        <p>Welcome, {user.email}</p>
        <button onClick={logout}>Log out</button>
      </div>
    );
  }

  if (step === "otp") {
    return (
      <form onSubmit={handleVerifyOtp}>
        {error && <p style={{ color: "red" }}>{error}</p>}
        <p>Enter the OTP sent to {email}</p>
        <input
          type="text"
          value={otp}
          onChange={(e) => setOtp(e.target.value)}
          placeholder="6-digit OTP"
        />
        <button type="submit">Verify</button>
      </form>
    );
  }

  return (
    <form onSubmit={handleSendOtp}>
      {error && <p style={{ color: "red" }}>{error}</p>}
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
      <button type="submit">Send OTP</button>
    </form>
  );
}
```

### Hook Return Values

| Property | Type           | Description                             |
| -------- | -------------- | --------------------------------------- |
| `sdk`    | `YativoSDK`    | The underlying TypeScript SDK instance  |
| `client` | `YativoSDK`    | Alias for `sdk`                         |
| `user`   | `User \| null` | Currently authenticated user, or `null` |
| `logout` | `() => void`   | Clear session                           |

***

## `useWallets()` — Create and List Wallets

```tsx theme={null}
import { useWallets } from "@yativo/crypto-sdk-react";

function WalletManager({ accountId }: { accountId: string }) {
  const { wallets, loading, error, createWallet, refresh } = useWallets(accountId);

  async function handleCreate() {
    await createWallet({ asset: "USDC", network: "SOLANA" });
  }

  if (loading) return <p>Loading wallets...</p>;
  if (error)   return <p>Error: {error.message}</p>;

  return (
    <div>
      <button onClick={handleCreate}>+ Create USDC Wallet</button>
      <button onClick={refresh}>Refresh</button>
      <ul>
        {wallets.map((w) => (
          <li key={w.id}>
            {w.asset} ({w.network}): {w.address}
          </li>
        ))}
      </ul>
    </div>
  );
}
```

***

## `useTransactions()` — Send and List Transactions

```tsx theme={null}
import { useTransactions } from "@yativo/crypto-sdk-react";

function TransactionHistory({ accountId }: { accountId: string }) {
  const { transactions, total, loading, error, sendFunds, refresh } =
    useTransactions({ accountId, limit: 20 });

  async function handleSend() {
    await sendFunds({
      fromWalletId: "wallet_xyz789",
      toAddress:    "BjhiXKt...",
      amount:       "50.00",
      asset:        "USDC",
      network:      "SOLANA",
    });
    refresh();
  }

  if (loading) return <p>Loading transactions...</p>;

  return (
    <div>
      <button onClick={handleSend}>Send 50 USDC</button>
      <p>Total transactions: {total}</p>
      <ul>
        {transactions.map((tx) => (
          <li key={tx.id}>
            {tx.amount} {tx.asset} — {tx.status} — {tx.createdAt}
          </li>
        ))}
      </ul>
    </div>
  );
}
```

***

## `useBalance()` — Auto-Refreshing Balance Display

```tsx theme={null}
import { useBalance } from "@yativo/crypto-sdk-react";

function BalanceDisplay({ assetId }: { assetId: string }) {
  // Auto-refresh every 30 seconds
  const { balance, asset, loading, error } = useBalance(
    assetId,
    true,   // autoRefresh
    30000   // interval in ms
  );

  if (loading) return <span>...</span>;
  if (error)   return <span>Error loading balance</span>;

  return (
    <div className="balance-card">
      <span className="amount">{balance}</span>
      <span className="asset">{asset}</span>
    </div>
  );
}
```

***

## `useCards()` — Card Management

```tsx theme={null}
import { useCards } from "@yativo/crypto-sdk-react";

function CardDashboard({ cardholderId }: { cardholderId: string }) {
  const { cards, loading, createCard, freezeCard, unfreezeCard } =
    useCards();

  async function handleCreateCard() {
    await createCard({
      cardholderId,
      currency: "USD",
      label:    "Travel expenses",
    });
  }

  if (loading) return <p>Loading cards...</p>;

  return (
    <div>
      <button onClick={handleCreateCard}>Issue New Card</button>
      {cards.map((card) => (
        <div key={card.id} className="card-item">
          <p>•••• {card.last4}</p>
          <p>Expires: {card.expiry}</p>
          <p>Status: {card.status}</p>
          {card.status === "ACTIVE" ? (
            <button onClick={() => freezeCard(card.id)}>Freeze</button>
          ) : (
            <button onClick={() => unfreezeCard(card.id)}>Unfreeze</button>
          )}
        </div>
      ))}
    </div>
  );
}
```

***

## `useSwap()` — Swap Functionality

```tsx theme={null}
import { useSwap } from "@yativo/crypto-sdk-react";

function SwapForm() {
  const { getQuote, executeSwap, loading, quote, result } = useSwap();
  const [amount, setAmount] = React.useState("100");

  async function handleQuote() {
    await getQuote({
      fromAsset: "USDC",
      toAsset:   "XDC",
      amount,
      network:   "SOLANA",
    });
  }

  async function handleExecute() {
    if (!quote) return;
    await executeSwap({
      quoteId:      quote.id,
      fromWalletId: "wallet_xyz789",
      toWalletId:   "wallet_xdc001",
    });
  }

  return (
    <div>
      <input
        value={amount}
        onChange={(e) => setAmount(e.target.value)}
        placeholder="Amount USDC"
      />
      <button onClick={handleQuote} disabled={loading}>
        Get Quote
      </button>

      {quote && (
        <div className="quote-box">
          <p>You receive: {quote.toAmount} XDC</p>
          <p>Rate: {quote.rate}</p>
          <p>Fee: {quote.fee} USDC</p>
          <button onClick={handleExecute} disabled={loading}>
            Execute Swap
          </button>
        </div>
      )}

      {result && <p>Swap complete! Status: {result.status}</p>}
    </div>
  );
}
```

***

## `useStandaloneIban()` — IBAN Management

```tsx theme={null}
import { useStandaloneIban } from "@yativo/crypto-sdk-react";

function IbanManager({ customerId }: { customerId: string }) {
  const { ibans, loading, createIban } = useStandaloneIban();

  async function handleCreate() {
    await createIban({
      customerId,
      currency: "EUR",
      label:    "EU Collections",
    });
  }

  return (
    <div>
      <button onClick={handleCreate}>Create EUR IBAN</button>
      {ibans.map((iban) => (
        <div key={iban.id}>
          <p>IBAN: {iban.iban}</p>
          <p>BIC: {iban.bic}</p>
        </div>
      ))}
    </div>
  );
}
```

***

## `useGasStations()` — Gas Station Management

```tsx theme={null}
import { useGasStations } from "@yativo/crypto-sdk-react";

function GasStationDashboard() {
  const { stations, loading, createStation } = useGasStations();

  async function handleCreate() {
    await createStation({
      network:     "SOLANA",
      sponsorType: "ALL_WALLETS",
    });
  }

  return (
    <div>
      <button onClick={handleCreate}>Create Gas Station</button>
      {stations.map((s) => (
        <div key={s.id}>
          <p>Network: {s.network}</p>
          <p>Balance: {s.balance}</p>
          <p>Status: {s.status}</p>
        </div>
      ))}
    </div>
  );
}
```

***

## `useAutoForwarding()` — Auto-Forwarding Rules

```tsx theme={null}
import { useAutoForwarding } from "@yativo/crypto-sdk-react";

function AutoForwardingManager() {
  const { rules, loading, createRule, updateRule, deleteRule } =
    useAutoForwarding();

  async function handleCreate() {
    await createRule({
      sourceWalletId:    "wallet_xyz789",
      destinationAddress: "BjhiXKt...",
      asset:             "USDC",
      network:           "SOLANA",
      minAmount:         "10.00",
    });
  }

  if (loading) return <p>Loading rules...</p>;

  return (
    <div>
      <button onClick={handleCreate}>Add Forwarding Rule</button>
      {rules.map((rule) => (
        <div key={rule.id}>
          <p>
            {rule.asset} on {rule.network} → {rule.destinationAddress}
          </p>
          <button onClick={() => updateRule(rule.id, { minAmount: "25.00" })}>
            Update Min
          </button>
          <button onClick={() => deleteRule(rule.id)}>Delete</button>
        </div>
      ))}
    </div>
  );
}
```

***

## `DepositWidget` — Embedded Deposit UI

The `DepositWidget` renders a complete deposit flow: it displays a QR code, network selector, and deposit address — with real-time confirmation updates.

```tsx theme={null}
import { DepositWidget } from "@yativo/crypto-sdk-react";

function DepositPage({ walletId }: { walletId: string }) {
  return (
    <DepositWidget
      walletId={walletId}
      supportedAssets={["USDC", "XDC", "ETH"]}
      onDepositConfirmed={(deposit) => {
        console.log("Deposit confirmed:", deposit.amount, deposit.asset);
      }}
      theme={{
        primaryColor:   "#6366f1",
        backgroundColor: "#ffffff",
        borderRadius:   "12px",
      }}
    />
  );
}
```

***

## `YativoCardWidget` — Embedded Card Display

The card widget renders sensitive card details (PAN, CVV, expiry) inside a secure sandboxed iframe. Card data never touches your JavaScript.

Your backend requests a `secure_view_url` and passes it to the client — never pass API credentials to client-side components.

```tsx theme={null}
import { YativoCardWidget } from "@yativo/crypto-sdk-react";

// secureViewUrl must come from your backend:
// const { secure_view_url } = await sdk.cards.getCardViewToken({ yativoCardId, cardId })
function CardViewer({ secureViewUrl }: { secureViewUrl: string }) {
  return (
    <div style={{ width: 380, height: 240 }}>
      <YativoCardWidget
        secureViewUrl={secureViewUrl}
        theme={{
          background:  "#1a1a2e",
          textColor:   "#ffffff",
          fontFamily:  "Inter, sans-serif",
          borderRadius: "16px",
        }}
        onReady={() => console.log("Card widget ready")}
        onError={(err) => console.error("Widget error:", err)}
      />
    </div>
  );
}
```

***

## Pre-Built UI Components

The React SDK ships utility components styled to match the Yativo design system:

```tsx theme={null}
import {
  YativoButton,
  YativoCard,
  YativoInput,
  YativoLogo,
} from "@yativo/crypto-sdk-react";

function ExamplePage() {
  return (
    <YativoCard padding="24px">
      <YativoLogo size={48} />
      <YativoInput
        label="Recipient Address"
        placeholder="Enter wallet address"
        type="text"
      />
      <YativoButton variant="primary" onClick={() => {}}>
        Send Funds
      </YativoButton>
      <YativoButton variant="secondary" onClick={() => {}}>
        Cancel
      </YativoButton>
    </YativoCard>
  );
}
```

***

## Theme Customization

Pass a `theme` object to `YativoProvider` to apply a global theme to all SDK components and widgets:

```tsx theme={null}
<YativoProvider
  config={{ baseURL: "https://crypto-api.yativo.com/api/v1/" }}
  theme={{
    primaryColor:    "#6366f1",   // indigo
    secondaryColor:  "#8b5cf6",   // violet
    backgroundColor: "#0f172a",   // dark slate
    surfaceColor:    "#1e293b",
    textColor:       "#f1f5f9",
    errorColor:      "#ef4444",
    successColor:    "#22c55e",
    borderRadius:    "12px",
    fontFamily:      "'Inter', sans-serif",
  }}
>
  {children}
</YativoProvider>
```

Individual components and widgets accept their own `theme` prop which merges with (and overrides) the global theme.

***

## Complete Example — Next.js Dashboard Page

```tsx theme={null}
// pages/dashboard.tsx
import {
  useYativo,
  useWallets,
  useBalance,
  useTransactions,
  DepositWidget,
  YativoCardWidget,
} from "@yativo/crypto-sdk-react";

const ACCOUNT_ID = "acct_abc123";
const WALLET_ID  = "wallet_xyz789";
const CARD_ID    = "card_mno345";

export default function Dashboard() {
  const { user, logout }           = useYativo();
  const { wallets, loading: wLoad } = useWallets(ACCOUNT_ID);
  const { balance }                 = useBalance(WALLET_ID, true, 15000);
  const { transactions }            = useTransactions({ accountId: ACCOUNT_ID, limit: 5 });

  if (!user) return <p>Please log in.</p>;

  return (
    <main>
      <header>
        <h1>Hello, {user.firstName}</h1>
        <button onClick={logout}>Log out</button>
      </header>

      <section>
        <h2>USDC Balance: {balance}</h2>
      </section>

      <section>
        <h2>Wallets ({wallets.length})</h2>
        {wLoad ? (
          <p>Loading...</p>
        ) : (
          wallets.map((w) => (
            <p key={w.id}>{w.asset} — {w.address}</p>
          ))
        )}
      </section>

      <section>
        <h2>Deposit</h2>
        <DepositWidget
          walletId={WALLET_ID}
          supportedAssets={["USDC"]}
          onDepositConfirmed={(d) => alert(`Received ${d.amount} ${d.asset}`)}
        />
      </section>

      <section>
        <h2>My Card</h2>
        <YativoCardWidget cardId={CARD_ID} />
      </section>

      <section>
        <h2>Recent Transactions</h2>
        <ul>
          {transactions.map((tx) => (
            <li key={tx.id}>
              {tx.amount} {tx.asset} — {tx.status}
            </li>
          ))}
        </ul>
      </section>
    </main>
  );
}
```
