> ## 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.

# TypeScript / Node.js SDK

> Complete guide for @yativo/crypto-sdk — installation, authentication, all resources, card widget, webhooks, and error handling

# TypeScript / Node.js SDK

The `@yativo/crypto-sdk` package is the official TypeScript SDK for the Yativo Crypto API. It ships with full TypeScript typings, automatic token refresh, rate-limit handling, and an embeddable card widget.

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

## Installation

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

**Package:** [`@yativo/crypto-sdk`](https://www.npmjs.com/package/@yativo/crypto-sdk) · **Latest:** `1.0.3` · **Requirements:** Node.js 16+ or a modern browser bundler (Webpack, Vite, esbuild).

***

## Quick Start

<Tabs>
  <Tab title="Passwordless Auth">
    ```typescript theme={null}
    import { YativoSDK } from "@yativo/crypto-sdk";

    const sdk = new YativoSDK({
      baseURL: "https://crypto-api.yativo.com/api/v1/",
    });

    // Register a new user
    await sdk.auth.register({
      email: "user@example.com",
      password: "SecurePass123!",
      firstName: "Ada",
      lastName: "Lovelace",
    });

    // Step 1 — Send OTP to the user's email
    await sdk.auth.login("user@example.com");

    // Step 2 — Verify the OTP to complete login
    // The SDK stores and auto-refreshes the token
    const session = await sdk.auth.verifyOTP("123456", "user@example.com");

    console.log("Logged in:", session.user.email);
    ```
  </Tab>

  <Tab title="API Key Auth">
    ```typescript theme={null}
    import { YativoSDK } from "@yativo/crypto-sdk";

    const sdk = new YativoSDK({
      apiKey: process.env.YATIVO_API_KEY,
      apiSecret: process.env.YATIVO_API_SECRET,
      baseURL: "https://crypto-api.yativo.com/api/v1/",
    });

    // No login needed — the SDK signs every request automatically
    const wallets = await sdk.assets.list();
    console.log("Wallets:", wallets);
    ```
  </Tab>
</Tabs>

***

## Constructor Options

```typescript theme={null}
interface YativoSDKOptions {
  /** API key for key-based authentication */
  apiKey?: string;
  /** API secret for key-based authentication */
  apiSecret?: string;
  /** Override the base URL (default: https://crypto-api.yativo.com/api/v1/) */
  baseURL?: string;
  /** Request timeout in milliseconds (default: 30000) */
  timeout?: number;
  /** Enable the IBAN feature (must be true to use sdk.standaloneIban) */
  standaloneIbanEnabled?: boolean;
}
```

***

## Authentication (`sdk.auth`)

### Register

```typescript theme={null}
const user = await sdk.auth.register({
  email: "user@example.com",
  password: "SecurePass123!",
  firstName: "Ada",
  lastName: "Lovelace",
  phoneNumber: "+14155552671",  // optional
});
```

### Login (Passwordless)

Login is passwordless. Call `login(email)` to send an OTP to the user, then call `verifyOTP(otp, email)` to complete authentication. The SDK stores the token internally and auto-refreshes on 401.

```typescript theme={null}
// Step 1 — Send OTP
await sdk.auth.login("user@example.com");

// Step 2 — Verify OTP to complete auth
const session = await sdk.auth.verifyOTP("123456", "user@example.com");
// session.accessToken is stored internally; auto-refreshed on 401
```

### 2FA Setup (Google Authenticator)

```typescript theme={null}
// Get QR code and secret for Google Authenticator setup
const details = await sdk.auth.get2faDetails();
// details.qrCode — display this as a QR image
// details.secret — manual entry fallback

// Activate 2FA on the account
await sdk.auth.enable2fa();

// Verify a TOTP code (use instead of verifyOTP when 2FA is enabled)
const session = await sdk.auth.verify2FA("654321", "user@example.com");
```

### Passkey (WebAuthn) Auth

```typescript theme={null}
// Get WebAuthn challenge
const options = await sdk.auth.passkeyAuthOptions("user@example.com");

// Verify WebAuthn credential (pass the result from navigator.credentials.get)
const session = await sdk.auth.passkeyAuthVerify(credential);
```

### Exchange API Key for Bearer Token

```typescript theme={null}
// Exchange API key + secret for a Bearer token (POST /auth/token)
const { token } = await sdk.auth.getToken(
  process.env.YATIVO_API_KEY!,
  process.env.YATIVO_API_SECRET!
);
```

***

## Accounts (`sdk.accounts`)

```typescript theme={null}
// Create a new account
const account = await sdk.accounts.create({
  name: "Main Treasury",
  currency: "USD",
});

// List all accounts
const { accounts, total } = await sdk.accounts.list({ page: 1, limit: 20 });

// Get a single account
const account = await sdk.accounts.get("acct_abc123");
```

***

## Assets / Wallets (`sdk.assets`)

### Create a Wallet

```typescript theme={null}
const wallet = await sdk.assets.createWallet({
  accountId: "acct_abc123",
  asset: "USDC",
  network: "SOLANA",
});
console.log("Deposit address:", wallet.address);
```

### Batch Create Wallets

```typescript theme={null}
const wallets = await sdk.assets.batchCreate({
  accountId: "acct_abc123",
  assets: [
    { asset: "USDC", network: "SOLANA" },
    { asset: "XDC",  network: "XDC" },
    { asset: "ETH",  network: "ETHEREUM" },
  ],
});
```

### List Wallets

```typescript theme={null}
const wallets = await sdk.assets.list({ accountId: "acct_abc123" });
```

### Check Balance

```typescript theme={null}
const balance = await sdk.assets.getBalance({
  walletId: "wallet_xyz789",
});
console.log(`Balance: ${balance.amount} ${balance.asset}`);
```

***

## Transactions (`sdk.transactions`)

### Send Funds (with Idempotency)

```typescript theme={null}
const tx = await sdk.transactions.send({
  fromWalletId: "wallet_xyz789",
  toAddress: "BjhiXKt...",
  amount: "100.00",
  asset: "USDC",
  network: "SOLANA",
  idempotencyKey: crypto.randomUUID(), // prevents double-sends on retry
  memo: "Invoice #INV-2026-001",
});
console.log("Transaction ID:", tx.id, "Status:", tx.status);
```

### Estimate Gas Fee

```typescript theme={null}
const fee = await sdk.transactions.estimateGas({
  fromWalletId: "wallet_xyz789",
  toAddress: "BjhiXKt...",
  amount: "100.00",
  asset: "USDC",
  network: "SOLANA",
});
console.log(`Estimated fee: ${fee.fee} ${fee.feeAsset}`);
```

### List Transactions

```typescript theme={null}
const { transactions, total } = await sdk.transactions.list({
  accountId: "acct_abc123",
  page: 1,
  limit: 25,
  status: "COMPLETED",        // optional filter
  startDate: "2026-01-01",    // optional
  endDate:   "2026-03-31",    // optional
});
```

### Get a Transaction

```typescript theme={null}
const tx = await sdk.transactions.get("txn_def456");
```

***

## Swap (`sdk.swap`)

```typescript theme={null}
// Get a swap quote
const quote = await sdk.swap.getQuote({
  fromAsset: "USDC",
  toAsset:   "XDC",
  amount:    "500.00",
  network:   "SOLANA",
});
console.log(`You receive: ${quote.toAmount} XDC, rate: ${quote.rate}`);

// Execute the swap (quote expires after ~30 seconds)
const result = await sdk.swap.execute({
  quoteId:      quote.id,
  fromWalletId: "wallet_xyz789",
  toWalletId:   "wallet_xdc001",
});
console.log("Swap status:", result.status);
```

***

## Cards (`sdk.cards`)

### Onboard a Cardholder

```typescript theme={null}
const cardholder = await sdk.cards.onboard({
  customerId:  "cust_111",
  firstName:   "Ada",
  lastName:    "Lovelace",
  dateOfBirth: "1990-05-15",
  address: {
    line1:   "1 Infinite Loop",
    city:    "Cupertino",
    state:   "CA",
    zip:     "95014",
    country: "US",
  },
});
```

### Create a Virtual Card

```typescript theme={null}
const card = await sdk.cards.create({
  cardholderId: cardholder.id,
  currency:     "USD",
  label:        "Engineering expenses",
});
console.log("Card ID:", card.id, "Last 4:", card.last4);
```

### Get Card Funding Address

```typescript theme={null}
const funding = await sdk.cards.getFundingAddress({ cardId: card.id });
console.log("Fund this card at:", funding.address, "on", funding.network);
```

### Get Card Transactions

```typescript theme={null}
const { transactions } = await sdk.cards.getTransactions({
  cardId: card.id,
  page:   1,
  limit:  20,
});
```

***

## Webhooks (`sdk.webhooks`)

### Create a Webhook

```typescript theme={null}
const webhook = await sdk.webhooks.create({
  url:    "https://your-app.com/webhooks/yativo",
  events: ["transaction.completed", "deposit.received", "card.transaction"],
  secret: "whsec_your_generated_secret",
});
console.log("Webhook ID:", webhook.id);
```

### Verify a Webhook Signature

Use this in your webhook receiver to confirm the payload came from Yativo:

```typescript theme={null}
import { Webhooks } from "@yativo/crypto-sdk";
import express from "express";

const app = express();

app.post(
  "/webhooks/yativo",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.headers["x-yativo-signature"] as string;
    const isValid = Webhooks.verifySignature(
      req.body,          // raw Buffer
      signature,
      process.env.YATIVO_WEBHOOK_SECRET!
    );

    if (!isValid) {
      return res.status(401).send("Invalid signature");
    }

    const event = JSON.parse(req.body.toString());
    console.log("Received event:", event.type, event.data);
    res.sendStatus(200);
  }
);
```

### List / Delete Webhooks

```typescript theme={null}
const webhooks = await sdk.webhooks.list();
await sdk.webhooks.delete("wh_ghi789");
```

***

## API Keys (`sdk.apiKeys`)

```typescript theme={null}
// Create an API key
const key = await sdk.apiKeys.create({
  key_name:        "Production Server",
  scopes:          ["transactions:read", "transactions:write", "wallets:read"],
  expires_in_days: 90,          // optional
  allowed_ips:     ["203.0.113.10"], // optional
});
// Store key.secret securely — it is shown only once
console.log("API Key:", key.key);
console.log("API Secret:", key.secret);

// List API keys
const { keys } = await sdk.apiKeys.list();

// Revoke a key (simple DELETE — no 2FA token required)
await sdk.apiKeys.revoke("key_jkl012");
```

***

## Auto-Forwarding (`sdk.autoForwarding`)

Auto-forwarding rules automatically sweep incoming deposits to a destination address.

```typescript theme={null}
// List all auto-forwarding rules
const { rules } = await sdk.autoForwarding.list();

// Create a rule
const rule = await sdk.autoForwarding.create({
  sourceWalletId:     "wallet_xyz789",
  destinationAddress: "BjhiXKt...",
  asset:              "USDC",
  network:            "SOLANA",
  minAmount:          "10.00",  // optional — only forward if amount >= this
});
console.log("Rule ID:", rule.id);

// Update a rule
await sdk.autoForwarding.update(rule.id, { minAmount: "25.00" });

// Delete a rule
await sdk.autoForwarding.delete(rule.id);
```

***

## Customers (`sdk.customers`)

```typescript theme={null}
const customer = await sdk.customers.create({
  externalId: "usr_from_your_db",
  email:      "customer@example.com",
  firstName:  "Charles",
  lastName:   "Babbage",
  kycLevel:   "BASIC",
});

const { customers } = await sdk.customers.list({ page: 1, limit: 50 });
const customer      = await sdk.customers.get("cust_abc");
await sdk.customers.update("cust_abc", { kycLevel: "FULL" });
```

***

## Analytics (`sdk.analytics`)

```typescript theme={null}
const report = await sdk.analytics.getSummary({
  accountId: "acct_abc123",
  startDate: "2026-01-01",
  endDate:   "2026-03-31",
});
console.log("Total volume:", report.totalVolume);
console.log("Total fees:",   report.totalFees);
```

***

## IBAN (`sdk.standaloneIban`)

<Warning>
  You must set `standaloneIbanEnabled: true` in the constructor to use this resource. Attempting to call these methods without the feature flag will throw a `FeatureNotEnabledError`.
</Warning>

```typescript theme={null}
const sdk = new YativoSDK({
  apiKey:                process.env.YATIVO_API_KEY,
  apiSecret:             process.env.YATIVO_API_SECRET,
  standaloneIbanEnabled: true,
});

const iban = await sdk.standaloneIban.create({
  customerId: "cust_111",
  currency:   "EUR",
  label:      "EU Collections",
});
console.log("IBAN:", iban.iban, "BIC:", iban.bic);

const ibans = await sdk.standaloneIban.list({ customerId: "cust_111" });
```

***

## Card Widget — `YativoCardEmbed`

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

Card data is displayed via a **Yativo-hosted secure page** — your backend requests a URL, your frontend opens it. No SDK widget to mount, no sensitive token to handle client-side.

**Step 1 — Request a secure view URL on your server:**

```typescript theme={null}
// Server-side only (Node.js / backend route)
const view = await sdk.cards.getCardViewToken({
  yativoCardId: "yc_abc123",
  cardId:       "card_mno345",
  enabledViews: ["data", "pin"],
  theme: {
    accentColor: "#6366f1",
    logoUrl:     "https://yourapp.com/logo.png",
  },
});
// Send view.secureViewUrl to your frontend
```

**Step 2 — Open the URL for the cardholder:**

```typescript theme={null}
// In your frontend — open in iframe, WebView, or new tab
const iframe = document.createElement("iframe");
iframe.src    = secureViewUrlFromServer;
iframe.width  = "420";
iframe.height = "740";
iframe.style.border = "0";
document.getElementById("card-container").appendChild(iframe);
```

```html theme={null}
<!-- Or directly in HTML -->
<iframe
  src="SECURE_VIEW_URL_FROM_YOUR_BACKEND"
  width="420" height="740"
  style="border:0;border-radius:16px;"
  allow="clipboard-read; clipboard-write">
</iframe>
```

<Warning>
  Always request a fresh URL immediately before showing it. Never cache or reuse a previous `secure_view_url`. See [Get Secure Card View URL](/api-reference/cards/customer-secure-view).
</Warning>

***

## Error Handling

```typescript theme={null}
import {
  YativoError,
  AuthenticationError,
  ValidationError,
  RateLimitError,
  NotFoundError,
} from "@yativo/crypto-sdk";

try {
  await sdk.transactions.send({ /* ... */ });
} catch (err) {
  if (err instanceof AuthenticationError) {
    // Token expired and could not be refreshed, or API key invalid
    console.error("Auth failed:", err.message);
  } else if (err instanceof ValidationError) {
    // Request body failed server-side validation
    console.error("Validation errors:", err.errors);
  } else if (err instanceof RateLimitError) {
    // 60 req/min per endpoint limit exceeded
    const retryAfter = err.retryAfter; // seconds until the window resets
    console.warn(`Rate limited. Retry after ${retryAfter}s`);
  } else if (err instanceof NotFoundError) {
    console.error("Resource not found:", err.resourceId);
  } else if (err instanceof YativoError) {
    // Catch-all for other API errors
    console.error(`API error ${err.statusCode}:`, err.message);
  } else {
    throw err; // unexpected — re-throw
  }
}
```

***

## Rate Limiting

The Yativo Crypto API allows **60 requests per minute per endpoint**. The SDK:

1. Throws `RateLimitError` when a `429` response is received.
2. Exposes `err.retryAfter` (seconds) so you can implement exponential back-off.

```typescript theme={null}
import { RateLimitError } from "@yativo/crypto-sdk";

async function sendWithRetry(payload, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await sdk.transactions.send(payload);
    } catch (err) {
      if (err instanceof RateLimitError && attempt < maxRetries) {
        const delay = (err.retryAfter ?? Math.pow(2, attempt)) * 1000;
        await new Promise((r) => setTimeout(r, delay));
      } else {
        throw err;
      }
    }
  }
}
```

***

## TypeScript Interfaces

Key types exported from the SDK:

```typescript theme={null}
interface Wallet {
  id:        string;
  accountId: string;
  asset:     string;
  network:   string;
  address:   string;
  balance:   string;
  createdAt: string;
}

interface Transaction {
  id:            string;
  fromWalletId:  string;
  toAddress:     string;
  amount:        string;
  asset:         string;
  network:       string;
  status:        "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED";
  hash?:         string;
  fee?:          string;
  idempotencyKey?: string;
  createdAt:     string;
  updatedAt:     string;
}

interface SwapQuote {
  id:         string;
  fromAsset:  string;
  toAsset:    string;
  fromAmount: string;
  toAmount:   string;
  rate:       string;
  fee:        string;
  expiresAt:  string;
}

interface Card {
  id:           string;
  cardholderId: string;
  last4:        string;
  expiry:       string;
  currency:     string;
  status:       "ACTIVE" | "FROZEN" | "TERMINATED";
  label?:       string;
  createdAt:    string;
}
```
