Skip to main content

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.

Installation

npm install @yativo/crypto-sdk-react
# or
yarn add @yativo/crypto-sdk-react
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.
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.
// 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/",
        // 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).
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

PropertyTypeDescription
sdkYativoSDKThe underlying TypeScript SDK instance
clientYativoSDKAlias for sdk
userUser | nullCurrently authenticated user, or null
logout() => voidClear session

useWallets() — Create and List Wallets

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

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

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

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

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

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

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

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.
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 (PSE)

The card widget renders sensitive card details (PAN, CVV, expiry) inside a secure sandboxed iframe. Card data never touches your JavaScript. The widget requires an ephemeral token from your backend — never pass API credentials to client-side components.
import { YativoCardWidget } from "@yativo/crypto-sdk-react";

// ephemeralToken must come from your backend:
// const { token } = await sdk.cards.getEphemeralToken({ yativoCardId, cardId })
function CardViewer({ ephemeralToken }: { ephemeralToken: string }) {
  return (
    <div style={{ width: 380, height: 240 }}>
      <YativoCardWidget
        ephemeralToken={ephemeralToken}
        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:
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:
<YativoProvider
  config={{ baseURL: "https://crypto-api.yativo.com/api/" }}
  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

// 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>
  );
}