npm package: @pear-protocol/exchanges-sdk
Description: Pear Protocol Exchanges SDK
Latest version: 0.0.13

# @pear-protocol/exchanges-sdk

Unified SDK for connecting to cryptocurrency derivative exchanges. Provides real-time account state tracking including balances, positions, and leverage management through a single, exchange-agnostic interface with automatic WebSocket streaming and credential resolution.

## Supported Exchanges

| Exchange | Connector Name | Market Type |
|----------|---------------|-------------|
| Binance | `binance` | USDM Futures |
| Bybit | `bybit` | Linear Perpetuals |
| Hyperliquid | `hyperliquid` | Perpetuals |

## Installation

```bash
npm install @pear-protocol/exchanges-sdk
```

## Quick Start

```typescript
import PearSDK from '@pear-protocol/core-sdk';
import { ExchangesSDK } from '@pear-protocol/exchanges-sdk';

const sdk = new PearSDK({ /* ... */ });
const exchanges = new ExchangesSDK({ sdk });

await exchanges.account.connect(tradeAccountId, 'binanceusdm');

// Track balance and positions
const balanceTracker = exchanges.account.trackBalance((balance) => {
  console.log(balance.totalEquity, balance.unrealizedPnl);
});

const positionsTracker = exchanges.account.trackPositions((positions) => {
  for (const pos of positions) {
    console.log(pos.symbol, pos.side, pos.size, pos.entryPrice);
  }
});

// Cleanup
balanceTracker.untrack();
positionsTracker.untrack();
exchanges.destroy();
```

## Usage

### Initialization

```typescript
// Production
const exchanges = new ExchangesSDK({ sdk });

// Testnet / demo
const exchanges = new ExchangesSDK({ sdk, demo: true });
```

The `ExchangesSDK` exposes three top-level modules:

| Module | Description |
|--------|-------------|
| `exchanges.account` | Account connection, balance/position tracking, leverage management |
| `exchanges.credentials` | Exchange API credential fetching and caching |
| `exchanges.sdk` | Reference to the underlying `PearSDK` instance |

### Connecting to an Exchange

Credentials are fetched automatically from the backend when you call `connect`. One exchange connection is active at a time.

```typescript
await exchanges.account.connect(tradeAccountId, 'binance');
await exchanges.account.connect(tradeAccountId, 'bybit');
await exchanges.account.connect(tradeAccountId, 'hyperliquid');
```

Check connection status:

```typescript
exchanges.account.isConnected;    // WebSocket is active
exchanges.account.isInitialized;  // first state snapshot received
```

### Tracking Balance

Subscribe to real-time balance updates. The callback fires on every balance change from the exchange.

```typescript
const tracker = exchanges.account.trackBalance((balance) => {
  balance.totalEquity;       // total account equity
  balance.walletBalance;     // wallet balance excluding unrealized PnL
  balance.unrealizedPnl;     // total unrealized PnL
  balance.availableToTrade;  // available margin for new trades
  balance.initialMarginUsed; // margin used by open positions
  balance.maintenanceMargin; // maintenance margin requirement
  balance.marginRatio;       // current margin ratio

  // Per-asset breakdown
  for (const asset of balance.assets) {
    asset.asset;          // "USDT", "BTC", etc.
    asset.free;           // available amount
    asset.used;           // amount in use
    asset.total;          // total amount
    asset.walletBalance;  // wallet balance
    asset.usdValue;       // USD equivalent
  }
});

// Read the latest value without waiting for a callback
const current = tracker.get();

// Stop receiving updates
tracker.untrack();
```

### Tracking Positions

Subscribe to real-time position updates. The callback fires with the full list of open positions on every change.

```typescript
const tracker = exchanges.account.trackPositions((positions) => {
  for (const pos of positions) {
    pos.symbol;           // "BTCUSDT"
    pos.side;             // "long" | "short" | "both"
    pos.size;             // "0.5"
    pos.entryPrice;       // "65000.00"
    pos.unrealizedPnl;    // "120.50"
    pos.leverage;         // "10"
    pos.marginType;       // "cross" | "isolated"
    pos.liquidationPrice; // "58000.00" or null
  }
});

const current = tracker.get();
tracker.untrack();
```

Positions with a size of `"0"` are automatically removed from the tracked state.

### Tracking a Specific Asset

Retrieve leverage, margin type, and trade size constraints for a specific coin. Useful when preparing to place a trade.

```typescript
const tracker = exchanges.account.trackAsset('ETH', (info) => {
  info.coin;        // "ETH"
  info.leverage;    // "20"
  info.marginType;  // "cross" | "isolated"
});

const current = tracker.get();
tracker.untrack();
```

### Managing Leverage

```typescript
// Read cached leverage (returns null if not yet fetched)
const leverage = exchanges.account.getLeverage('BTCUSDT');
```

### Reading Full State

Access a read-only snapshot of the complete account state at any time.

```typescript
const state = exchanges.account.getState();
if (state) {
  state.balance;          // latest AccountBalance or null
  state.positions;        // Map<"SYMBOL:side", AccountPosition>
  state.leverageSettings; // Map<symbol, leverage>
  state.trackedAssets;    // Map<coin, TrackedAssetInfo>
  state.lastUpdated;      // timestamp of last update
  state.initialized;      // true after first snapshot
}
```

### Credential Management

Credentials are resolved automatically on `connect`, but you can manage them directly:

```typescript
// Fetch credentials from the backend
const creds = await exchanges.credentials.fetch(tradeAccountId);

// Get cached credentials (null if not fetched)
const cached = exchanges.credentials.get(tradeAccountId);

// Get from cache or fetch if missing
const creds = await exchanges.credentials.getOrFetch(tradeAccountId);

// Clear cached credentials
exchanges.credentials.clear(tradeAccountId); // specific account
exchanges.credentials.clear();               // all accounts
```

### Cleanup

```typescript
// Disconnect but keep credentials cached for reconnection
exchanges.account.disconnect();

// Full teardown: disconnect and clear all credentials
exchanges.destroy();
```