npm package: @peerlytics/sdk
Description: Lightweight TypeScript SDK for the Peerlytics v1 API - ZKP2P P2P protocol analytics
Author: Galleon Labs
Latest version: 0.4.1

# @peerlytics/sdk

TypeScript SDK for the [Peerlytics](https://peerlytics.xyz) v1 API -- analytics, explorer, and trading data for the ZKP2P P2P protocol on Base. Works in Node.js and browsers.

## Install

```bash
npm install @peerlytics/sdk
# or
bun add @peerlytics/sdk
# or
pnpm add @peerlytics/sdk
```

## Quick Start

```ts
import { Peerlytics } from "@peerlytics/sdk";

const client = new Peerlytics({ apiKey: "pk_live_..." });

// protocol summary
const summary = await client.getProtocolSummary();

// investor diligence view
const overview = await client.getProtocolOverview("all");

// live orderbook
const orderbook = await client.getOrderbook({ currency: "GBP" });

// deposit detail
const deposit = await client.getDeposit("8453_0x777...Ef_42");

// search (supports addresses, tx hashes, deposit IDs, ENS, .peer names)
const results = await client.search("vitalik.eth");
```

## Response shapes

A few gotchas worth knowing up front — especially if you've been hitting the
HTTP API directly:

- **`{ success, data }` envelope.** Most v1 endpoints wrap the payload in
  `{ success: true, data: <payload> }`. The SDK unwraps this for you — every
  method returns the inner `data` directly. If you're calling the raw API
  (e.g. via `fetch`), remember to read `response.data`, not `response`.
  Exceptions: `/account/*` endpoints and `/analytics/summary|overview|leaderboard`
  return data directly with no envelope.

- **`getDeposits` requires at least one filter.** The API rejects empty queries
  with a 400 `missing_filter`. Provide at least one of `depositor`, `delegate`,
  `platform`, or `currency`. The SDK throws a `ValidationError` before hitting
  the network so you get a clearer stack trace.

- **`getIntents` also requires at least one filter.** Provide at least one of
  `owner`, `recipient`, `verifier`, `depositId`, or `status`. Same client-side
  `ValidationError` behavior.

- **`getActivity` returns an envelope, not a raw array.** The response is
  `{ events, count, hasMore, limit, offset, filters }` — iterate over
  `response.events`, not `response` itself.

- **Currency codes vs hashes.** On-chain, currencies are stored as `bytes32`
  (either a keccak256 of the ISO code or an ASCII-padded encoding).
  Every `DepositMarket` exposes both: `currency` (resolved, e.g. `"GBP"`) and
  `currencyCode` (raw hash). Entries inside `deposit.currencies[]` also carry
  a resolved `currency` field alongside the raw `currencyCode`. If you need to
  build your own mapping, call `getCurrencies()` — each entry includes the
  `code`, `label`, `flag`, and all hash forms.

## Configuration

```ts
const client = new Peerlytics({
  baseUrl: "https://peerlytics.xyz", // default
  apiKey: "pk_live_...", // API key for authenticated access
  headers: { "X-Trace": "abc" }, // custom headers
  fetch: customFetch, // custom fetch implementation
});
```

## API Reference

### Analytics

| Method                       | Description                                                          |
| ---------------------------- | -------------------------------------------------------------------- |
| `getProtocolSummary()`       | Investor-facing protocol summary buckets for mtd, qtd, ytd, all-time |
| `getProtocolOverview(range)` | Investor diligence payload for `mtd`, `3mtd`, `ytd`, or `all`        |
| `getLeaderboard(params?)`    | Maker and taker leaderboards (by volume, APR, profit, lock score)    |

### Deposits

| Method                    | Description                                                       |
| ------------------------- | ----------------------------------------------------------------- |
| `getDeposits(filters)`    | Query deposits by depositor, delegate, platform, currency, status |
| `getDeposit(id, params?)` | Deposit detail with intents, payment methods, and linked data     |

### Intents

| Method                | Description                                                    |
| --------------------- | -------------------------------------------------------------- |
| `getIntents(filters)` | Query intents by owner, recipient, verifier, depositId, status |
| `getIntent(hash)`     | Intent detail with deposit and related intents                 |

### Explorer

| Method                          | Description                                                       |
| ------------------------------- | ----------------------------------------------------------------- |
| `getAddress(address, params?)`  | Address profile: intents, deposits, activity, stats               |
| `getMaker(address)`             | Maker portfolio: deposits, allocations, profit, APR               |
| `getVerifier(address, params?)` | Verifier stats: intents, breakdown by currency/taker/maker        |
| `search(query, opts?)`          | Multi-type search (address, tx hash, deposit ID, ENS, .peer name) |

### Orderbook & Market

| Method                    | Description                                       |
| ------------------------- | ------------------------------------------------- |
| `getOrderbook(opts?)`     | Live orderbook grouped by currency and rate level |
| `getMarketSummary(opts?)` | Rate statistics per (platform, currency) pair     |

The orderbook API now prefers the indexer's denormalized `OrderbookEntry` projection when available, which keeps platform filters canonicalized (for example, `zelle-*` variants collapse into one `Zelle` surface) while preserving the same response shape for SDK consumers.

### Vaults & Delegation

| Method                  | Description                                                   |
| ----------------------- | ------------------------------------------------------------- |
| `getVaultsOverview()`   | All vaults: AUM, fees, adoption rate, daily snapshots         |
| `getVault(id, params?)` | Vault detail: rate manager, delegations, oracle/floor configs |

### Activity

| Method                  | Description                                                        |
| ----------------------- | ------------------------------------------------------------------ |
| `getActivity(filters?)` | Live blockchain events (signals, fulfills, deposits, rate updates) |

### History

| Method                     | Description                                                           |
| -------------------------- | --------------------------------------------------------------------- |
| `getMakerHistory(address)` | Maker historical stats, platform/currency breakdowns, recent activity |
| `getTakerHistory(address)` | Taker historical stats, lock score, tier progression                  |

### Metadata

| Method            | Description                                                 |
| ----------------- | ----------------------------------------------------------- |
| `getCurrencies()` | Supported fiat currencies with codes, labels, flags, hashes |
| `getPlatforms()`  | Supported payment platforms with IDs, labels, method hashes |

### Account Management

| Method                | Description                                              |
| --------------------- | -------------------------------------------------------- |
| `listKeys()`          | List API keys                                            |
| `createKey(label?)`   | Create a new API key                                     |
| `rotateKey(oldKey)`   | Rotate an existing key                                   |
| `deleteKey(key)`      | Delete a key                                             |
| `getCredits()`        | Credit balance and purchase history                      |
| `createCheckout(pkg)` | Create a checkout session (`starter`, `growth`, `scale`) |

## Error Handling

```ts
import { PeerlyticsError, RateLimitError, NotFoundError, ValidationError } from "@peerlytics/sdk";

try {
  await client.getDeposit("missing");
} catch (err) {
  if (err instanceof RateLimitError) {
    console.log(`Retry after ${err.retryAfter}s`);
  } else if (err instanceof NotFoundError) {
    console.log("Not found");
  } else if (err instanceof ValidationError) {
    console.log(`Bad request: ${err.code} - ${err.message}`);
  } else if (err instanceof PeerlyticsError) {
    console.log(`HTTP ${err.status}: ${err.message}`);
  }
}
```

All errors extend `PeerlyticsError` with `status`, `code`, `message`, and `details` properties.

## Filter Arrays

Array filter values are comma-joined automatically:

```ts
// deposits on revolut or wise, in GBP or EUR
await client.getDeposits({
  platform: ["revolut", "wise"],
  currency: ["GBP", "EUR"],
});

// activity for multiple deposit IDs
await client.getActivity({
  depositId: ["42", "43", "44"],
  type: ["intent_signaled", "intent_fulfilled"],
});
```

## Related

- Dashboard: <https://peerlytics.xyz>
- Developer docs: <https://peerlytics.xyz/developers>
- Agent docs: <https://peerlytics.xyz/agents>
- LLM docs: <https://peerlytics.xyz/llms.txt>
- Orderbook: <https://network.peerlytics.xyz>
- Trading: <https://usdctofiat.xyz>

## License

MIT