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/surfpool

v1.6.1

Published

Embed a Surfpool Solana runtime in your Node.js tests

Readme

@solana/surfpool

Node.js bindings for the Surfpool SDK, built with napi-rs.

Usage

import { Surfnet } from "@solana/surfpool";

const surfnet = Surfnet.start();
console.log(surfnet.rpcUrl); // http://127.0.0.1:xxxxx

// ... run tests / interact with the local validator ...

// Graceful shutdown: closes HTTP + WebSocket RPC servers and frees ports.
surfnet.stop();

stop() is idempotent and synchronous; it blocks briefly while servers close. Wire it into test teardown (e.g. afterAll) to avoid connection reset / broken pipe warnings caused by the OS yanking sockets at process exit.

Kit plugin (@solana/surfpool/kit)

The @solana/surfpool/kit entry provides an @solana/kit plugin that is a drop-in replacement for solanaLocalRpc() or litesvm(), plus a typed RPC client for every surfnet_* cheatcode.

The kit dependencies are optional peers — install them alongside this package:

npm install --save-dev @solana/surfpool @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer

Embedded mode boots an in-process Surfnet, installs a pre-funded payer, the full local RPC stack (rpc, rpcSubscriptions, airdrop, sendTransactions, …), the native handle as client.surfnet, and a typed cheatcodes RPC as client.cheatcodes:

import { createClient } from "@solana/kit";
import { surfpool } from "@solana/surfpool/kit";

const client = await createClient().use(surfpool());

await client.cheatcodes.timeTravel({ absoluteSlot: 1_000_000 }).send();
client.surfnet.fundSol(client.payer.address, 1_000_000_000);
const slot = await client.rpc.getSlot().send();

client.surfnet.stop();

The embedded client is Disposable: disposing it stops the Surfnet, so you can use using instead of calling stop() yourself and a recreated client boots a fresh instance.

using client = await createClient().use(surfpool());
// Surfnet stops automatically when `client` goes out of scope.

Surfnet startup options go under the surfnet key; everything else is forwarded to the standard local RPC plugin:

const client = await createClient().use(
  surfpool({ surfnet: { offline: true }, skipPreflight: true }),
);

Attach mode connects to an already-running Surfpool (e.g. surfpool start) instead of booting one — no native module is loaded and the client must already have a payer:

import { createClient } from "@solana/kit";
import { payer } from "@solana/kit-plugin-signer";
import { surfpool } from "@solana/surfpool/kit";

const client = await createClient()
  .use(payer(myPayer))
  .use(surfpool({ rpcUrl: "http://127.0.0.1:8899" }));

That payer is usually unfunded on the running Surfnet. airdropAddresses credits each listed address or signer while the client is composed, so no separate cheatcode call is needed before sending a transaction:

const client = await createClient()
  .use(payer(myPayer))
  .use(
    surfpool({
      airdropAddresses: [myPayer, someRecipient],
      airdropAmount: 5_000_000_000n, // lamports, defaults to 10 SOL
      rpcUrl: "http://127.0.0.1:8899",
    }),
  );

Funding is additive, like a real airdrop: airdropAmount is added to whatever the address already holds, and only the lamport balance is written, so existing account data and owner survive. A failure to fund throws, naming the address. The option works in embedded mode too, alongside the pre-funded payer.

For one-off use without a client, createSurfnetCheatcodesRpc(url) returns a standalone Rpc<SurfnetCheatcodesApi>, and surfnetCheatcodes() installs client.cheatcodes on any existing client.

Note on integers: cheatcode responses arrive with bigint integers (the cheatcodes transport parses all JSON integers as bigint so u64 values like rentEpoch survive above 2^53); request payloads accept number | bigint.

Development

npm ci
npm run build
npm test

The TypeScript types for the surfnet_* cheatcodes under surfpool-sdk/kit/generated/ are generated from the Rust wire types in crates/types (ts-rs, behind the ts-bindings feature) and committed. After changing those Rust types, refresh them with:

npm run generate:kit-types

CI regenerates the bindings and fails on any diff.

Publishing

The npm package is released from crates/sdk-node using prebuilt native artifacts for:

  • x86_64-apple-darwin
  • aarch64-apple-darwin
  • x86_64-unknown-linux-gnu

The GitHub Actions release workflow builds those artifacts first, assembles the per-platform npm package directories, and then publishes each package with npm trusted publishing over GitHub OIDC.