npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@percolatorct/sdk

v2.0.9

Published

TypeScript SDK for building clients, bots, and UIs on top of the [Percolator](https://github.com/dcccrypto/percolator) perpetual futures protocol on Solana.

Downloads

1,702

Readme

@percolator/sdk

TypeScript SDK for building clients, bots, and UIs on top of the Percolator perpetual futures protocol on Solana.

EXPERIMENTAL. NOT AUDITED. 2.0.5. v12.19 single-target. 792 tests passing. Do NOT use with real funds.

Target wrapper

The SDK targets the percolator v12.19 wrapper (PR #271, branch sync/v12.19-wrapper, commit d760fc4). All encoders emit v12.19 wire format. The dual-target target: 'v12.17' | 'v12.19' parameter present in 2.0.0-rc.0 has been removed. PERC-628 shared-vault encoders (InitSharedVault, AllocateMarket, QueueWithdrawalSV, ClaimEpochWithdrawal, AdvanceEpoch) are unconditionally enabled.

Slab parsers retain V12_1 / V12_15 / V12_17 layout descriptors for backward-compatible reads of older deployments. V12_19 layout descriptor is added for fresh v12.19 slabs.

npm License


Installation

pnpm add @percolator/sdk
# or
npm install @percolator/sdk

Peer dependency: @solana/web3.js ^1.95


Quick Start

import {
  getProgramId,
  deriveVaultAuthority,
  encodeInitUser,
  encodeDepositCollateral,
  encodeTradeNoCpi,
  parseHeader,
  parseConfig,
  parseAllAccounts,
  detectSlabLayout,
  computeMarkPnl,
  computeLiqPrice,
  simulateOrSend,
} from "@percolator/sdk";

// Get program ID (defaults to devnet)
const programId = getProgramId("devnet");

// Derive vault authority PDA
const [vaultAuth, bump] = deriveVaultAuthority(programId, slabPubkey);

// Read and parse on-chain slab account
const slabInfo = await connection.getAccountInfo(slabPubkey);
const slabData = new Uint8Array(slabInfo!.data);
const header = parseHeader(slabData);
const layout = detectSlabLayout(slabData.length);
const config = parseConfig(slabData, layout!);
const accounts = parseAllAccounts(slabData);

// Compute PnL for a position
const pnl = computeMarkPnl(positionSize, entryPrice, oraclePrice);
const liqPrice = computeLiqPrice(entryPrice, capital, positionSize, 500n);

Features

ABI Encoding & Decoding

Type-safe instruction builders matching the on-chain Rust layout byte-for-byte:

import { buildInitMarketIxData, buildTradeNoCpiIxData, IX_TAG } from "@percolator/sdk";

// Build InitMarket instruction data (256 bytes)
const data = buildInitMarketIxData({
  admin: adminPubkey,
  collateralMint: mintPubkey,
  indexFeedId: pythFeedId,
  maxStaleSecs: 60n,
  confFilterBps: 250,
  invert: false,
  unitScale: 1_000_000_000, // lamports per unit
  riskParams: { /* ... */ },
});

// Build trade instruction
const tradeData = buildTradeNoCpiIxData({
  userIdx: 0,
  lpIdx: 0,
  requestedSize: 1_000_000n, // positive = long, negative = short
  maxSlippage: 50,           // bps
});

Supported instructions: InitMarket, InitUser, InitLP, DepositCollateral, WithdrawCollateral, KeeperCrank, TradeNoCpi, TradeCpi, LiquidateAtOracle, CloseAccount, TopUpInsurance, SetRiskThreshold, UpdateAdmin, UpdateConfig, SetMaintenanceFee, PushOraclePrice, ResolveMarket, SetOiImbalanceHardBlock, SetOracleAuthority, and more.

Admin Instructions

SetOiImbalanceHardBlock (tag=71)

Prevents new trades from pushing the long/short OI skew above a configurable threshold. When triggered, the on-chain error OiImbalanceHardBlock (code 59) is returned.

import {
  encodeSetOiImbalanceHardBlock,
  ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK,
  buildAccountMetas,
  buildIx,
  simulateOrSend,
} from "@percolator/sdk";

// threshold_bps = 0         → hard block disabled (default)
// threshold_bps = 5_000     → block trades that push skew above 50%
// threshold_bps = 8_000     → block trades that push skew above 80%
// threshold_bps = 10_000    → lock dominant side once any OI exists

const data = encodeSetOiImbalanceHardBlock({ thresholdBps: 8_000 });
const keys = buildAccountMetas(ACCOUNTS_SET_OI_IMBALANCE_HARD_BLOCK, [
  adminPublicKey,  // [signer]
  slabPublicKey,   // [writable]
]);
const ix = buildIx({ programId, keys, data });

const result = await simulateOrSend({ connection, ix, signers: [admin] });
console.log("signature:", result.signature);

SetOracleAuthority (tag=16)

Delegates the PushOraclePrice right to a specific keypair (e.g. a crank bot). Pass PublicKey.default (all zeros) to revoke — the program then falls back to Pyth/Chainlink.

import { PublicKey } from "@solana/web3.js";
import {
  encodeSetOracleAuthority,
  ACCOUNTS_SET_ORACLE_AUTHORITY,
  buildAccountMetas,
  buildIx,
  simulateOrSend,
} from "@percolator/sdk";

// Delegate to a crank bot
const data = encodeSetOracleAuthority({ newAuthority: crankBot.publicKey });
const keys = buildAccountMetas(ACCOUNTS_SET_ORACLE_AUTHORITY, [
  adminPublicKey,  // [signer, writable]
  slabPublicKey,   // [writable]
]);
const ix = buildIx({ programId, keys, data });

await simulateOrSend({ connection, ix, signers: [admin] });

// Revoke — fall back to Pyth/Chainlink
const revokeData = encodeSetOracleAuthority({ newAuthority: PublicKey.default });

See examples/admin-instructions.ts for full end-to-end examples.

Account Deserialization

Parse the on-chain slab account into typed TypeScript objects:

import {
  parseHeader,
  parseConfig,
  parseAllAccounts,
  detectSlabLayout,
} from "@percolator/sdk";

const slabData = new Uint8Array(accountInfo.data);
const header = parseHeader(slabData);
const layout = detectSlabLayout(slabData.length)!;
const config = parseConfig(slabData, layout);
const accounts = parseAllAccounts(slabData);

// header.magic, header.version, header.admin, header.nonce
// header.resolved, header.paused

// config.collateralMint, config.vaultPubkey, config.indexFeedId
// config.maxStalenessSlots, config.confFilterBps
// config.fundingHorizonSlots, config.fundingKBps
// config.threshFloor, config.threshRiskBps

// accounts[i].account.owner, accounts[i].account.capital,
// accounts[i].account.pnl, accounts[i].account.positionSize

PDA Derivation

All program-derived addresses with correct seeds:

import {
  deriveVaultAuthority,
  deriveLpPda,
  deriveInsuranceLpMint,
} from "@percolator/sdk";

const [vaultAuth, bump] = deriveVaultAuthority(programId, slab);
const [lpPda, lpBump] = deriveLpPda(programId, slab, lpIndex);
const [insMint, insBump] = deriveInsuranceLpMint(programId, slab);

Trading Math

Coin-margined perpetual math utilities (all BigInt, no floating-point):

import {
  computeMarkPnl,
  computeLiqPrice,
  computeEntryPrice,
  computeEffectiveLeverage,
} from "@percolator/sdk";

// Mark-to-market PnL (in native token units)
const pnl = computeMarkPnl(positionSize, entryPriceE6, oraclePriceE6);

// Liquidation price given capital and maintenance margin
const liqPrice = computeLiqPrice(entryPriceE6, capital, positionSize, 500n);

// All values use e6 format: 1 USD = 1_000_000

Oracle Price Router

Automatic oracle discovery and ranking for any Solana token:

import { resolvePrice } from "@percolator/sdk";

const result = await resolvePrice(tokenMint);
// result.bestSource — highest-confidence price source
// result.allSources — all discovered sources ranked by liquidity

Supports Pyth, DexScreener (Raydium, Orca, Meteora), and Jupiter price feeds.

Program ID Configuration

Network-aware program ID resolution:

import { getProgramId, getMatcherProgramId } from "@percolator/sdk";

// Defaults to devnet
const programId = getProgramId();

// Explicit network selection
const mainnetId = getProgramId("mainnet");

// Environment variable override: PROGRAM_ID=<your-id>

Auto-Deleveraging (ADL)

ADL (Auto-Deleveraging) reduces the most-profitable opposing positions when the insurance fund is depleted. The SDK provides both on-chain and API-based ADL utilities.

Checking if ADL is triggered

import { isAdlTriggered } from "@percolator/sdk";

const accountInfo = await connection.getAccountInfo(slabKey);
if (isAdlTriggered(accountInfo!.data)) {
  console.log("Insurance fund depleted — ADL is active");
}

Ranking positions for ADL

import { fetchAdlRankedPositions } from "@percolator/sdk";

const { ranked, longs, shorts, isTriggered } = await fetchAdlRankedPositions(
  connection,
  slabKey,
);
// ranked  — all positions sorted by PnL% descending (ADL priority order)
// longs   — top-ranked long position (ADL target if insurance negative on short side)
// shorts  — top-ranked short position
// isTriggered — whether pnl_pos_tot exceeds max_pnl_cap on-chain

Building an ADL instruction

import { buildAdlInstruction, buildAdlTransaction, getProgramId } from "@percolator/sdk";

const programId = getProgramId("devnet");

// Build instruction directly (caller already has target index)
const ix = buildAdlInstruction(
  callerPublicKey,   // keeper / crank wallet
  slabPublicKey,
  oracleFeedPublicKey,
  programId,
  targetAccountIndex, // number — index of account to deleverage
);

// OR: fetch + rank + pick top target automatically
const ix2 = await buildAdlTransaction(
  connection,
  callerPublicKey,
  slabPublicKey,
  oracleFeedPublicKey,
  programId,
  "long", // side to deleverage ("long" | "short")
);

Decoding on-chain ADL events

import { parseAdlEvent } from "@percolator/sdk";

// After sending / confirming an ExecuteAdl transaction:
const tx = await connection.getTransaction(sig, { commitment: "confirmed" });
const event = parseAdlEvent(tx?.meta?.logMessages ?? []);
// event.tag          — 0xAD1E_0001 (2904424449)
// event.targetIdx    — account index that was deleveraged
// event.price        — oracle price at execution (e6)
// event.closedAbs    — absolute position size closed (i128)

Fetching ADL rankings via HTTP API

import { fetchAdlRankings } from "@percolator/sdk";

const result = await fetchAdlRankings(
  "https://percolatorlaunch.com/api",
  slabAddress,
);
// result.slabAddress              — slab public key (base58)
// result.adlNeeded                — true if ADL is triggered (capExceeded or utilizationTriggered)
// result.capExceeded              — true if pnlPosTot > maxPnlCap
// result.insuranceDepleted        — true if insurance fund balance == 0
// result.utilizationTriggered     — true if utilization BPS exceeds the configured ADL threshold
// result.pnlPosTot                — aggregate profitable PnL (decimal string)
// result.maxPnlCap                — max PnL cap from market config (decimal string, "0" if unconfigured)
// result.excess                   — excess PnL above cap (decimal string)
// result.insuranceFundBalance     — insurance fund balance (decimal string)
// result.insuranceFundFeeRevenue  — insurance fund lifetime fee revenue (decimal string)
// result.insuranceUtilizationBps  — insurance utilization in basis points (0–10000)
// result.rankings                 — AdlApiRanking[] sorted by rank (1 = first to deleverage)
//   .rank             — rank (1 = highest PnL%, deleveraged first)
//   .idx              — slab account index (pass as targetIdx to buildAdlInstruction)
//   .pnlAbs           — absolute PnL in lamports (decimal string)
//   .capital          — capital at entry in lamports (decimal string)
//   .pnlPctMillionths — pnl * 1_000_000 / capital (decimal string)

ADL error codes (61–65)

| Code | Name | Description | |------|------|-------------| | 61 | EngineSideBlocked | Trade blocked — this side is in DrainOnly or ResetPending mode | | 62 | EngineCorruptState | Slab state corrupt — critical internal error, please report | | 63 | InsuranceFundNotDepleted | ADL not triggered yet (insurance fund healthy) | | 64 | NoAdlCandidates | No eligible positions to deleverage | | 65 | BankruptPositionAlreadyClosed | Target position already closed |


Transaction Helpers

Build, simulate, and send transactions with error parsing:

import { buildIx, simulateOrSend } from "@percolator/sdk";

const ix = buildIx({ programId, keys: accountMetas, data: ixData });

const result = await simulateOrSend({
  connection,
  ix,
  signers: [payer],
  simulate: false,        // true = simulate only
  computeUnitLimit: 400_000,
});

// result.signature, result.slot, result.err, result.logs
// Errors are automatically parsed from logs into human-readable messages

Client-Side Validation

Validate parameters before submitting transactions:

import {
  validatePublicKey,
  validateAmount,
  validateBps,
  validateI128,
  validateIndex,
} from "@percolator/sdk";

// Validates a public key string (throws ValidationError on invalid input)
const slabKey = validatePublicKey(slabAddress, "slab");

// Validates a u64 amount (throws ValidationError if negative or > u64 max)
const amount = validateAmount("1000000000", "depositAmount");

// Validates basis points (0-10000)
const feeBps = validateBps("50", "tradingFee");

Mainnet vs Devnet

By default the SDK targets devnet (safety default — PERC-697). The NETWORK environment variable and the network parameter to getProgramId() / discoverMarkets() control which program IDs and RPC endpoints are used. Production deployments always set NETWORK=mainnet explicitly via Railway env vars.

import { getProgramId, discoverMarkets } from "@percolator/sdk";

// Devnet (default — safe fallback)
const programId = getProgramId("devnet");

// Mainnet — set env or pass explicitly
// NETWORK=mainnet
const mainnetProgramId = getProgramId("mainnet");

// Market discovery — uses network from NETWORK env by default
const markets = await discoverMarkets(connection);

Program Addresses

| Program | Network | Address | |---------|---------|---------| | Percolator | Mainnet | ESa89R5Es3rJ5mnwGybVRG1GrNt9etP11Z5V2QWD4edv | | Matcher | Mainnet | DHP6DtwXP1yJsz8YzfoeigRFPB979gzmumkmCxDLSkUX | | Stake | Mainnet | DC5fovFQD5SZYsetwvEqd4Wi4PFY1Yfnc669VMe6oa7F | | NFT | Mainnet | FqhKJT9gtScjrmfUuRMjeg7cXNpif1fqsy5Jh65tJmTS | | Percolator | Devnet | FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD | | Matcher | Devnet | GTRgyTDfrMvBubALAqtHuQwT8tbGyXid7svXZKtWfC9k |

Use PROGRAM_ID / MATCHER_PROGRAM_ID env vars to override for local test validators.


RPC Connection Pool, Retry, and Health Probes

The SDK provides a production-grade RPC connection pool with automatic retry, failover, and health probing. Use RpcPool for mainnet reliability.

RpcPool — Multi-endpoint with failover/round-robin

import { RpcPool } from "@percolator/sdk";

const pool = new RpcPool({
  endpoints: [
    { url: "https://mainnet.helius-rpc.com/?api-key=KEY", weight: 10, label: "helius" },
    { url: "https://api.mainnet-beta.solana.com", weight: 1, label: "public" },
  ],
  strategy: "failover",   // or "round-robin"
  retry: {
    maxRetries: 3,         // default: 3
    baseDelayMs: 500,      // default: 500 (exponential backoff)
    maxDelayMs: 10_000,    // default: 10s cap
    jitterFactor: 0.25,    // default: 0.25 (avoid thundering herd)
  },
  requestTimeoutMs: 30_000, // default: 30s per request
  commitment: "confirmed",  // default: confirmed
});

// Execute any async call through the pool — auto-retry + failover
const slot = await pool.call(conn => conn.getSlot());
const balance = await pool.call(conn => conn.getBalance(pubkey));

// Use with discoverMarkets
const markets = await pool.call(conn =>
  discoverMarkets(conn, programId, { apiBaseUrl: "https://percolatorlaunch.com/api" })
);

// Pool status & diagnostics
console.log(pool.status()); // [{ label, url, healthy, failures, lastLatencyMs }]
console.log(`${pool.healthyCount}/${pool.size} endpoints healthy`);

Standalone retry wrapper

import { withRetry } from "@percolator/sdk";
import { Connection } from "@solana/web3.js";

const conn = new Connection("https://api.mainnet-beta.solana.com");
const slot = await withRetry(
  () => conn.getSlot(),
  { maxRetries: 3, baseDelayMs: 1000 },
);

RPC health probes

import { checkRpcHealth } from "@percolator/sdk";

const health = await checkRpcHealth("https://api.mainnet-beta.solana.com", 5000);
console.log(`${health.endpoint}: ${health.healthy ? "UP" : "DOWN"} — ${health.latencyMs}ms, slot ${health.slot}`);

// Or check all pool endpoints at once
const results = await pool.healthCheck();

RPC Concurrency

discoverMarkets() fires one getProgramAccounts request per known slab tier size. There are ~15 known tier sizes. To avoid hitting rate limits on public or free-tier endpoints, the SDK caps parallel in-flight requests at 6 by default.

For production use a Helius paid-tier key. On the free tier, pass sequential: true to serialize requests with exponential backoff:

import { discoverMarkets } from "@percolator/sdk";

// Helius paid tier — parallel (default, fast)
const markets = await discoverMarkets(connection, { maxParallelTiers: 6 });

// Free-tier or public RPC — sequential with 429 backoff
const marketsSafe = await discoverMarkets(connection, { sequential: true });

// Custom concurrency
const marketsCustom = await discoverMarkets(connection, { maxParallelTiers: 3 });

Note: Public mainnet-beta RPC (api.mainnet-beta.solana.com) rejects getProgramAccounts calls entirely. Use the API fallback (below) or a Helius/QuickNode endpoint.

Market Discovery — 3-Tier Fallback Chain

Public mainnet RPCs reject getProgramAccounts, which blocks discoverMarkets(). The SDK provides a resilient 3-tier fallback chain that works on any RPC endpoint:

| Tier | Method | Requires | |------|--------|----------| | 1 | getProgramAccounts (RPC) | Helius/premium RPC key | | 2 | REST API (GET /markets) | Percolator API online | | 3 | Static bundle (bundled addresses) | Nothing — works offline |

All tiers verify data on-chain via getMultipleAccounts (works on all RPCs).

Recommended: Full 3-tier fallback

Pass both apiBaseUrl and network to enable all three tiers:

import { discoverMarkets, getProgramId } from "@percolator/sdk";
import { Connection } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const markets = await discoverMarkets(connection, getProgramId("mainnet"), {
  apiBaseUrl: "https://percolatorlaunch.com/api",
  network: "mainnet",  // enables tier-3 static fallback
});

API-only discovery via discoverMarketsViaApi()

Skip getProgramAccounts entirely — query the REST API for slab addresses, then fetch full on-chain data:

import { discoverMarketsViaApi, getProgramId } from "@percolator/sdk";
import { Connection } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const programId = getProgramId("mainnet");
const markets = await discoverMarketsViaApi(
  connection,
  programId,
  "https://percolatorlaunch.com/api",
);

Static-only discovery via discoverMarketsViaStaticBundle()

Use the bundled address list directly (no network calls except getMultipleAccounts):

import {
  discoverMarketsViaStaticBundle,
  getStaticMarkets,
  getProgramId,
} from "@percolator/sdk";
import { Connection } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const entries = getStaticMarkets("mainnet");
const markets = await discoverMarketsViaStaticBundle(
  connection,
  getProgramId("mainnet"),
  entries,
);

Extending the static registry at runtime

The static bundle can be augmented before calling discoverMarkets():

import { registerStaticMarkets, discoverMarkets, getProgramId } from "@percolator/sdk";
import { Connection } from "@solana/web3.js";

// Register known slab addresses before discovery
registerStaticMarkets("mainnet", [
  { slabAddress: "ABC123...", symbol: "SOL-PERP" },
  { slabAddress: "DEF456...", symbol: "ETH-PERP" },
]);

const connection = new Connection("https://api.mainnet-beta.solana.com");
const markets = await discoverMarkets(connection, getProgramId("mainnet"), {
  apiBaseUrl: "https://percolatorlaunch.com/api",
  network: "mainnet",
});

Known addresses via getMarketsByAddress()

If you already know your market slab addresses (e.g. from an indexer or hardcoded list), fetch them directly:

import { getMarketsByAddress, getProgramId } from "@percolator/sdk";
import { Connection, PublicKey } from "@solana/web3.js";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const markets = await getMarketsByAddress(
  connection,
  getProgramId("mainnet"),
  [new PublicKey("..."), new PublicKey("...")],
);

Architecture

@percolator/sdk
├── abi/                 # Binary encoding/decoding matching on-chain layout
│   ├── instructions.ts  # Instruction data builders (all 72 instructions)
│   ├── accounts.ts      # Account struct deserialization
│   ├── encode.ts        # Low-level binary encoding (u8/u16/u32/u64/i128/pubkey)
│   ├── errors.ts        # On-chain error code → human-readable parsing
│   └── index.ts
├── solana/              # Solana-specific helpers
│   ├── slab.ts          # Slab account parser (header + config + accounts)
│   ├── pda.ts           # PDA derivation (vault, LP, insurance mint)
│   ├── discovery.ts     # Market discovery (find all Percolator markets)
│   ├── rpc-pool.ts      # RPC connection pool, retry, failover, health probes
│   ├── dex-oracle.ts    # DEX oracle price integration
│   ├── token-program.ts # SPL Token helpers
│   ├── ata.ts           # Associated Token Account helpers
│   └── index.ts
├── runtime/             # Transaction building and submission
│   ├── tx.ts            # buildIx, simulateOrSend, error handling
│   └── index.ts
├── math/                # Trading math (all BigInt)
│   ├── trading.ts       # PnL, liquidation price, leverage, entry price
│   └── index.ts
├── oracle/              # Price feed integration
│   └── price-router.ts  # Multi-source oracle resolution (Pyth, DEX, Jupiter)
├── config/              # Configuration
│   └── program-ids.ts   # Network-aware program IDs
├── validation.ts        # Client-side parameter validation
└── index.ts             # Public API re-exports

Development

Prerequisites

  • Node.js 20+ and pnpm 9+

Commands

pnpm install              # Install dependencies
pnpm build                # Build with tsup (outputs to dist/)
pnpm test                 # Run all 742 tests (vitest)
pnpm lint                 # Type-check (tsc --noEmit)
pnpm verify-layout        # Verify ABI byte offsets against on-chain layout

Testing

Tests cover ABI encoding roundtrips, PDA derivation, slab parsing, validation, and trading math. 742 tests, 0 failures.

pnpm test                 # Run all tests
pnpm test -- --watch      # Watch mode

v12.17 Layout Support

The SDK supports the v12.17 slab layout natively via detectSlabLayout(). The layout detection function inspects account size to select the correct field offsets for header, config, and per-account data.

A key fix in this version corrects the SBF byte offsets for d1/d2 delta fields that were misaligned in earlier SDK versions. The parseAllAccounts() function applies the correct offsets for both devnet (legacy layout) and mainnet (v12.17 layout) slabs automatically.

Publishing

pnpm build
npm publish --access public

Configuration

| Environment Variable | Description | Default | |---------------------|-------------|---------| | PROGRAM_ID | Override Percolator program ID | Network default | | MATCHER_PROGRAM_ID | Override Matcher program ID | Network default | | NETWORK | Target network (devnet / mainnet) | devnet |

Devnet Program Addresses

| Program | Address | |---------|---------| | Percolator | FxfD37s1AZTeWfFQps9Zpebi2dNQ9QSSDtfMKdbsfKrD | | Matcher | 4HcGCsyjAqnFua5ccuXyt8KRRQzKFbGTJkVChpS7Yfzy |


Browser Compatibility

The SDK uses DataView for all binary reads (no Node.js Buffer dependency). Works in:

  • Node.js 20+
  • Modern browsers (Chrome, Firefox, Safari, Edge)
  • React Native (via @solana/web3.js)

Related Repositories

| Repository | Description | |-----------|-------------| | percolator | Core risk engine crate (Rust) | | percolator-prog | Solana on-chain program (wrapper) | | percolator-matcher | Reference matcher program for LP pricing | | percolator-stake | Insurance LP staking program | | percolator-ops | Operations dashboard | | percolator-mobile | Solana Seeker mobile trading app | | percolator-launch | Full-stack launch platform (monorepo) |

License

Apache 2.0 — see LICENSE.