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

solana-reliable-sdk

v0.1.0

Published

SDK that improves RPC and transaction reliability for Solana dApps — failover pool, circuit breaker, auto retry, priority fees

Readme

solana-reliable-sdk

A TypeScript SDK that solves three common pain points in Solana dApp development:

  1. RPC instability — one endpoint goes down → your app crashes
  2. Dropped transactions — network congestion causes silent failures
  3. Retry boilerplate — every project reimplements the same retry logic

Quick Start

npm install solana-reliable-sdk @solana/web3.js
import { Keypair, SystemProgram, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js';
import { ReliableClient } from 'solana-reliable-sdk';

const client = new ReliableClient({
  endpoints: [
    'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY',
    'https://api.mainnet-beta.solana.com',
  ],
  commitment: 'confirmed',
  tx: {
    priorityFee: 'auto',   // fetches dynamic fee estimate
    computeUnits: 'auto',  // simulates transaction first
  },
});

const tx = new Transaction().add(
  SystemProgram.transfer({
    fromPubkey: payer.publicKey,
    toPubkey: recipient.publicKey,
    lamports: 0.1 * LAMPORTS_PER_SOL,
  }),
);

const { signature } = await client.sendAndConfirm(tx, [payer]);
console.log('Confirmed:', signature);

client.destroy();

How It Works

ReliableClient
├── RpcPool          — round-robin / priority failover across multiple endpoints
│   ├── HealthChecker   — pings getSlot every 30 s, marks dead endpoints
│   └── CircuitBreaker  — CLOSED → OPEN (3 fails) → HALF_OPEN → CLOSED
├── BlockhashManager — caches blockhash, tracks lastValidBlockHeight expiry
├── FeeEstimator     — Helius getPriorityFeeEstimate or getRecentPrioritizationFees percentile
├── ComputeUnits     — simulateTransaction → setComputeUnitLimit with 10 % buffer
├── TransactionSender
│   ├── Retry loop every 2 s (configurable)
│   ├── Re-sign when blockhash expires (safe from duplicates)
│   └── Exponential backoff on HTTP 429
├── TransactionConfirmer — polls getSignatureStatuses, distinguishes permanent vs. transient errors
├── JitoSender       — routes transactions through Jito block engine for MEV protection
├── MetricsCollector — records RPC latency, failures, circuit state; exports Prometheus + OTLP
└── WsManager        — auto-reconnect WebSocket subscriptions with exponential backoff

API Reference

ReliableClient

const client = new ReliableClient(options: ReliableClientOptions);

| Option | Type | Default | Description | |---|---|---|---| | endpoints | string[] | required | RPC endpoint URLs. First = highest priority. | | commitment | Commitment | 'confirmed' | Default commitment level. | | wsEndpoint | string | undefined | WebSocket URL. Required for client.ws. | | pool | Partial<RpcPoolOptions> | {} | RpcPool configuration. | | tx | Partial<TransactionSenderOptions> | {} | TransactionSender configuration. | | confirm | Partial<ConfirmOptions> | {} | TransactionConfirmer configuration. | | ws | Partial<WsManagerOptions> | {} | WsManager configuration. | | jito | JitoSenderOptions | undefined | Enable Jito/MEV routing. | | metrics | MetricsCollector | undefined | Attach a metrics collector. |

client.sendAndConfirm(tx, signers)

Sends a transaction and waits for confirmation. Handles:

  • Dynamic priority fees and compute budget
  • Automatic retry every retryIntervalMs
  • Re-signing on blockhash expiry
  • Immediate throw on permanent on-chain errors (e.g., InstructionError)
  • Routes through Jito block engine if jito option is set

Returns { signature: string }.

client.destroy()

Stops the health checker and WebSocket reconnect loop. Always call this on shutdown.


RpcPool

const pool = new RpcPool(endpoints, {
  strategy: 'round-robin',       // or 'priority'
  healthCheckInterval: 30_000,   // ms between getSlot pings
  circuitBreaker: {
    threshold: 3,                // failures before opening circuit
    timeout: 60_000,             // ms before trying HALF_OPEN
  },
  metrics,                       // optional MetricsCollector
});

Exposes getConnection(), reportSuccess(conn), reportFailure(conn), destroy().


TransactionSender

const sender = new TransactionSender(pool, blockhashManager, feeEstimator, computeUnits, {
  retryIntervalMs: 2_000,    // ms between send attempts
  maxDurationMs: 90_000,     // total timeout
  skipPreflight: false,
  priorityFee: 'auto',       // 'auto' | number (microLamports)
  priorityLevel: 'medium',   // 'low' | 'medium' | 'high'
  computeUnits: 'auto',      // 'auto' | number
});

TransactionConfirmer

const confirmer = new TransactionConfirmer(pool, {
  commitment: 'confirmed',   // 'processed' | 'confirmed' | 'finalized'
  pollIntervalMs: 2_000,
  timeoutMs: 90_000,
});

await confirmer.confirm(signature, lastValidBlockHeight);
// Throws PermanentTransactionError on InstructionError
// Throws TransactionExpiredError when blockHeight > lastValidBlockHeight

JitoSender — MEV Protection

Route transactions through Jito block engine to prevent frontrunning and enable atomic bundles.

import { ReliableClient } from 'solana-reliable-sdk';

const client = new ReliableClient({
  endpoints: ['https://mainnet.helius-rpc.com/?api-key=YOUR_KEY'],
  jito: {
    region: 'ny',          // 'mainnet' | 'amsterdam' | 'frankfurt' | 'ny' | 'tokyo'
    tipLamports: 10_000,   // tip to Jito validators (default 1_000)
    fallbackOnError: true, // fall back to standard RPC if Jito fails
  },
});

// sendAndConfirm automatically routes through Jito when configured
const { signature } = await client.sendAndConfirm(tx, [payer]);

For atomic bundles (multiple transactions in the same slot):

import { JitoSender } from 'solana-reliable-sdk';

const jito = new JitoSender(pool, blockhashManager, { region: 'frankfurt' });

// Submit up to 5 transactions atomically
const bundleId = await jito.sendBundle([tx1, tx2], signers);
const status = await jito.getBundleStatus(bundleId);
// { bundleId, status: 'Landed' | 'Pending' | 'Failed' | 'Finalizing', landedSlot? }

MetricsCollector — Observability

Track RPC latency, failure rates, circuit breaker state, and transaction outcomes. Exports Prometheus text format and OTLP JSON (compatible with OpenTelemetry Collector and Datadog Agent).

import { ReliableClient, MetricsCollector } from 'solana-reliable-sdk';

const metrics = new MetricsCollector();

const client = new ReliableClient({
  endpoints: ['https://mainnet.helius-rpc.com/?api-key=YOUR_KEY'],
  metrics,
});

// Prometheus format (for Grafana / alertmanager scrape)
const prometheusText = metrics.exportPrometheus();

// OTLP JSON (for OpenTelemetry Collector or Datadog Agent)
const otlpPayload = metrics.exportOtlpJson();

// Raw snapshot
const snap = metrics.getSnapshot();
// snap.rpc['helius-rpc.com'] → { totalRequests, failures, avgLatencyMs, p95LatencyMs, circuitState }
// snap.transactions → { total, succeeded, failed, avgRetries, avgDurationMs }

Exposed Prometheus metrics:

| Metric | Type | Description | |---|---|---| | solana_rpc_requests_total | counter | Total requests per endpoint | | solana_rpc_failures_total | counter | Total failures per endpoint | | solana_rpc_latency_avg_ms | gauge | Average latency (ms) per endpoint | | solana_rpc_latency_p95_ms | gauge | P95 latency (ms) per endpoint | | solana_circuit_breaker_state | gauge | 0=CLOSED, 1=HALF_OPEN, 2=OPEN | | solana_tx_total | counter | Total transactions sent | | solana_tx_succeeded_total | counter | Successful transactions | | solana_tx_failed_total | counter | Failed transactions | | solana_tx_avg_retries | gauge | Average retries per transaction |


ReliableWalletAdapter — Wallet Integration

Wrap any wallet-adapter-compatible wallet (Phantom, Solflare, Backpack, etc.) to add RPC failover, priority fee estimation, and retry on top of the standard signing flow.

import { ReliableClient, ReliableWalletAdapter } from 'solana-reliable-sdk';

const client = new ReliableClient({ endpoints: ['https://...'] });

// phantomWallet — any object implementing WalletLike (publicKey, connected, signTransaction)
const adapter = new ReliableWalletAdapter(phantomWallet, client);

// Drop-in replacement for wallet.sendTransaction:
const signature = await adapter.sendTransaction(tx);

// Send multiple transactions sequentially with retry on each:
const signatures = await adapter.sendAllTransactions([tx1, tx2, tx3]);

Compatible with any wallet implementing @solana/wallet-adapter-base SignerWalletAdapter interface (v0.15+).


WsManager

const ws = new WsManager(wsEndpoint, {
  commitment: 'processed',
  healthCheckIntervalMs: 10_000,
  healthFailureThreshold: 3,
  initialReconnectDelayMs: 1_000,
  maxReconnectDelayMs: 30_000,
});

ws.addSubscription(
  'myKey',
  (conn) => conn.onAccountChange(pubkey, callback),
  (conn, id) => conn.removeAccountChangeListener(id),
);

ws.removeSubscription('myKey');
ws.destroy();

ReliableRpcV2 — web3.js v2.0 Support

Use the new functional @solana/rpc API with the same failover and circuit-breaker guarantees.

import { createReliableRpcV2 } from 'solana-reliable-sdk';

const rpc = createReliableRpcV2({
  endpoints: [
    'https://mainnet.helius-rpc.com/?api-key=YOUR_KEY',
    'https://api.mainnet-beta.solana.com',
  ],
  strategy: 'round-robin',
  commitment: 'confirmed',
});

const { blockhash, lastValidBlockHeight } = await rpc.getLatestBlockhash();
const slot = await rpc.getSlot();                    // returns bigint
const balance = await rpc.getBalance(address);       // Address from @solana/addresses
const sig = await rpc.sendTransaction(encodedTx);

All methods automatically fail over to the next healthy endpoint and track circuit breaker state — same semantics as RpcPool but exposed through the v2.0 functional interface.


Diagnostics CLI

Check health of your RPC endpoints before deployment or during incidents:

npx tsx bin/diagnose.ts https://api.mainnet-beta.solana.com https://rpc.helius.xyz/?api-key=KEY

# Output:
# solana-reliable-sdk — RPC Diagnostics
#
# Endpoint                                  |  Status  |       Slot  |  getSlot     |  getLatestBlockhash
# ────────────────────────────────────────────────────────────────────────────────
# https://api.mainnet-beta.solana.com       |  ✓ OK    |  312847291  |  183ms       |  201ms
# https://rpc.helius.xyz/?api-key=***       |  ✓ OK    |  312847291  |  48ms        |  51ms
# ────────────────────────────────────────────────────────────────────────────────
# Summary: 2 healthy / 0 failed

Exits with code 0 if all endpoints are healthy, 1 if any failed. API keys in query params are automatically redacted in output.


Examples

Run on devnet (no API key needed):

# SOL transfer
npx tsx examples/transfer-sol.ts

# SPL token transfer (requires @solana/spl-token)
npm install @solana/spl-token
npx tsx examples/spl-token-transfer.ts

Why Not Just Use @solana/web3.js Directly?

| Scenario | web3.js alone | solana-reliable-sdk | |---|---|---| | RPC endpoint goes down | App crashes | Automatically fails over to next endpoint | | Transaction dropped by congested network | Silent failure | Retried every 2 s for up to 90 s | | Blockhash expires during retry | Duplicate transaction risk | Re-signed only after confirmed expiry | | Priority fees during congestion | Must implement manually | Auto-estimated from network data | | Compute unit budget | Hardcoded 200 000 or guessed | Simulated before send | | MEV / frontrunning | No protection | Jito block engine routing with tip | | Observability | None | Prometheus + OTLP export out of the box | | Wallet adapter | Standard send only | Adds failover + retry on top | | WebSocket disconnect | Subscriptions lost silently | Auto-reconnected with backoff | | web3.js v2.0 (@solana/rpc) | No reliability layer | ReliableRpcV2 with full failover |


Running Tests

npm test
# 120 tests, 14 test files — including network failure and congestion simulations

License

MIT