Skip to content

Releases: solana-foundation/surfpool

v1.2.0

23 Apr 15:20
d279682

Choose a tag to compare

Surfpool v1.2.0 Release Notes

Introducing Surfpool SDK

Surfpool now ships surfpool-sdk for embedding a full Surfpool Surfnet directly
inside tests. You can start an isolated local Solana-compatible runtime without
shelling out to surfpool start, get dynamic HTTP and WebSocket endpoints, use a
pre-funded payer, and call cheatcode helpers for fast state setup.

The SDK is available as:

  • Rust crate: surfpool-sdk
  • Node.js package: surfpool-sdk, backed by napi-rs native bindings and
    prebuilt package artifacts for macOS x64, macOS arm64, and Linux x64 GNU

Rust Usage

Add the SDK to integration-test dependencies:

[dev-dependencies]
surfpool-sdk = "1.2.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Start a Surfnet and use the built-in RPC client:

use surfpool_sdk::{Signer, Surfnet};

#[tokio::test]
async fn starts_embedded_surfnet() {
    let surfnet = Surfnet::start().await.unwrap();

    let rpc = surfnet.rpc_client();
    let payer_balance = rpc.get_balance(&surfnet.payer().pubkey()).unwrap();

    assert!(payer_balance > 0);
}

Configure startup behavior when you need deterministic test setup:

use surfpool_sdk::{BlockProductionMode, Pubkey, Surfnet};

#[tokio::test]
async fn starts_with_custom_state() {
    let recipient = Pubkey::new_unique();

    let surfnet = Surfnet::builder()
        .offline(true)
        .block_production_mode(BlockProductionMode::Transaction)
        .airdrop_addresses(vec![recipient])
        .airdrop_sol(10_000_000_000)
        .start()
        .await
        .unwrap();

    surfnet.cheatcodes().fund_sol(&recipient, 5_000_000_000).unwrap();
}

Use cheatcodes for common integration-test setup:

use surfpool_sdk::{Pubkey, Surfnet};

#[tokio::test]
async fn seeds_accounts() {
    let surfnet = Surfnet::start().await.unwrap();
    let cheats = surfnet.cheatcodes();

    let owner = Pubkey::new_unique();
    let mint = Pubkey::new_unique();

    cheats.fund_sol(&owner, 1_000_000_000).unwrap();
    cheats.fund_token(&owner, &mint, 1_000, None).unwrap();
    cheats.time_travel_to_slot(1_000).unwrap();
}

Deploy a local Solana program from build artifacts:

use surfpool_sdk::Surfnet;

#[tokio::test]
async fn deploys_program() {
    let surfnet = Surfnet::start().await.unwrap();
    let cheats = surfnet.cheatcodes();

    // Looks for target/deploy/my_program.so,
    // target/deploy/my_program-keypair.json,
    // and target/idl/my_program.json when present.
    let program_id = cheats.deploy_program("my_program").unwrap();

    assert!(surfnet.rpc_client().get_account(&program_id).is_ok());
}

Use an explicit program id and artifact path when your build output is custom:

use surfpool_sdk::{cheatcodes::builders::DeployProgram, Pubkey, Surfnet};

#[tokio::test]
async fn deploys_from_explicit_artifacts() {
    let surfnet = Surfnet::start().await.unwrap();
    let program_id = Pubkey::new_unique();

    surfnet
        .cheatcodes()
        .deploy(
            DeployProgram::new(program_id)
                .so_path("fixtures/programs/my_program.so")
                .idl_path("fixtures/idls/my_program.json"),
        )
        .unwrap();
}

The Rust API also exposes typed cheatcode builders for setting accounts,
resetting accounts, streaming accounts, setting token-account fields, and
deploying local program artifacts.

Node.js Usage

Install the package in a Node.js 18+ test project:

npm install surfpool-sdk

Start Surfnet and seed state from a Node test:

const assert = require("node:assert/strict");
const test = require("node:test");
const { Surfnet } = require("surfpool-sdk");

test("uses embedded surfpool", async () => {
  const surfnet = Surfnet.start();
  const owner = Surfnet.newKeypair().publicKey;
  const mint = Surfnet.newKeypair().publicKey;

  surfnet.fundSol(owner, 1_000_000_000);
  surfnet.fundToken(owner, mint, 1_000);

  assert.match(surfnet.rpcUrl, /^http:\/\/127\.0\.0\.1:/);
});

For custom startup options, use startWithConfig:

const payer = Surfnet.newKeypair();

const surfnet = Surfnet.startWithConfig({
  offline: true,
  blockProductionMode: "manual",
  slotTimeMs: 1,
  airdropSol: 1_000_000_000,
  payerSecretKey: Uint8Array.from(payer.secretKey),
});

Deploy a local Solana program from build artifacts:

const surfnet = Surfnet.start();

// Looks for target/deploy/my_program.so,
// target/deploy/my_program-keypair.json,
// and target/idl/my_program.json when present.
const programId = surfnet.deployProgram("my_program");

console.log(`deployed ${programId} to ${surfnet.rpcUrl}`);

Use explicit deployment options when you already have the program id and .so
path:

const programId = Surfnet.newKeypair().publicKey;

surfnet.deploy({
  programId,
  soPath: "fixtures/programs/my_program.so",
  idlPath: "fixtures/idls/my_program.json",
});

The Node API includes helpers for SOL and token funding, arbitrary account
updates, token-account state, account reset, remote account streaming, time
travel, program deployment, ATA derivation, event draining, and keypair
generation.

New Features

New Cheatcodes

  • feat(rpc): add rpc methods to enable/disable other cheatcodes (#557) (by @0xzrf)

    Surfnet cheatcode access can now be changed at runtime with
    surfnet_enableCheatcode and surfnet_disableCheatcode. This lets tests or
    hosted environments narrow the mutable RPC surface after setup.

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "surfnet_disableCheatcode",
      "params": [["surfnet_setAccount", "surfnet_timeTravel"]]
    }
  • feat: add `surfnet_offlineAccount` RPC method (#566) (by @CanardMandarin)

    surfnet_offlineAccount prevents Surfpool from downloading a specific account
    from the configured remote RPC. Pass includeOwnedAccounts to also block
    accounts owned by that pubkey, which is useful when a test must prove behavior
    without remote fallback.

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "surfnet_offlineAccount",
      "params": ["<account-pubkey>", { "includeOwnedAccounts": true }]
    }
  • feat: add `surfnet_streamAccounts` RPC method (#598) (by @KABBOUCHI)

    Multiple remote accounts can now be registered for streaming in a single
    request. This complements surfnet_streamAccount and helps tests seed a set
    of account subscriptions before exercising transaction behavior.

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "surfnet_streamAccounts",
      "params": [[
        { "pubkey": "<account-a>", "includeOwnedAccounts": true },
        { "pubkey": "<account-b>" }
      ]]
    }

Jito sendBundle

  • feat(core): add Jito sendBundle RPC support (#480) (by @serejke)

    Surfpool now implements the Jito-compatible sendBundle RPC method for local
    bundle testing. This makes it possible to exercise bundle submission flows
    against Surfpool before pointing the same client code at a Jito block engine
    or bundle-aware infrastructure.

    sendBundle accepts up to five serialized transactions, matching Jito's
    bundle size limit. Surfpool processes them sequentially in the provided order
    and forces skip_preflight to match block-engine send behavior. On success,
    it returns a bundle ID calculated as the SHA-256 hash of the comma-separated
    transaction signatures.

    The first version is intentionally a local compatibility surface, not full
    block-engine semantics. If a later transaction in the bundle fails, Surfpool
    returns an error that includes the failing bundle index, but earlier
    successful transactions are not rolled back yet.

    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "sendBundle",
      "params": [["<base64-transaction-1>", "<base64-transaction-2>"], { "encoding": "base64" }]
    }

Additional Features

  • feat(cli): allow passing feature pubkey instead of name on startup (#577) (by @MicaiahReid)

    surfpool start --feature and surfpool start --disable-feature now accept
    base58 Agave feature-gate pubkeys. Named features still work for compatibility,
    but the CLI warns through help text that names are deprecated.

    surfpool start --feature <feature-pubkey> --disable-feature <feature-pubkey>
  • feat: enable register-tracing feature for litesvm by default (#574) (by @procdump)

    Default CLI builds now enable LiteSVM register tracing through Surfpool's
    register-tracing feature, making register-level execution data available to
    tracing-enabled builds without requiring a custom feature selection.

  • feat(cli): add --artifacts-path flag to override .so program location (#573) (by @procdump)

    surfpool start can now deploy program binaries from a custom artifacts
    directory instead of assuming target/deploy. This is useful for alternate
    build directories, debug artifacts, or CI layouts.

    surfpool start --artifacts-path ./target/deploy/debug
  • feat: add prometheus metrics (#586) (by @dvansari65)

    Builds compiled with the prometheus feature can expose a /metrics endpoint
    with counters and histograms for transaction outcomes, transaction latency, RPC
    requests, RPC latency, and remote account fetch latency.

cargo run -p surfpool-cli --features prometheus -- start --metrics-enabled --metrics-addr 127.0.0.1:9000
curl http://127.0.0.1:9000/metrics
  • feat: add option to skip blockhash validation for transactions (#632) (by @MicaiahReid)

    Surfpool can now disable transaction blockhash validation for workflo...

Read more

v1.1.2

02 Apr 21:50
3b2881e

Choose a tag to compare

v1.1.2

Introduces a bug fix for scaffolding IaC deployments. Previously, the name of the package in a program's Cargo.toml was converted to snake case. This case conversion was unnecessary and led to the program binary not being found in some edge cases.

v1.1.1

06 Mar 22:44
d58df4c

Choose a tag to compare

What's Changed

Full Changelog: v1.1.0...v1.1.1

v1.1.0

05 Mar 20:40

Choose a tag to compare

Notable Changes

We now build a docker image with every release! You can find tagged releases here: https://hub.docker.com/r/surfpool/surfpool

Features

  • feat(cli): add --skip-signature-verification flag by @bonlime in #533
  • feat(rpc): implement programSubscribe WS method by @MicaiahReid in #541

Fixes

  • fix(cli): error better with ls command when txtx.yaml file doesn't exist by @0xzrf in #535
  • fix(core): keep resetNetwork blockhash state consistent by @bonlime in #534
  • fix(cli): add panic unwinding error handling to give appropriate errors message by @0xzrf in #532
  • fix(rpc): return InvalidParams instead of panic in simulateTransaction by @bonlime in #528
  • fix: separate account fetching from loop to avoid rate limiting by @0xzrf in #542
  • fix(cli): update accounts initialization to use validator account from anchor.toml by @MicaiahReid in #545
  • fix: order signatures for getSignaturesForAddress by @MicaiahReid in #546
  • fix(core): implement transaction signature verification and reject duplicates by @MicaiahReid in #544

Misc

Shoutouts

Thank you so much to our external contributors!

Full Changelog: v1.0.1...v1.1.0

v1.0.1

16 Feb 20:23

Choose a tag to compare

chore(release): publish v1.0.1

v1.0.0

20 Jan 18:58

Choose a tag to compare

What's Changed

  • chore: update rmcp by @lgalabru in #411
  • feat: set_log_filter rpc and start_time rpc by @JkrishnaD in #410
  • feat: add list_plugins admin RPC and remove rpc_addr admin RPC method from trait by @0xsouravm in #408
  • chore: remove unused admin RPC methods and clean up imports by @MicaiahReid in #414
  • feat(scenarios): add native Jupiter v6 support & refactor registry by @tanmay4l in #413
  • feat(scenario): add raydium amm-v3 scenario by @JkrishnaD in #419
  • feat: svm feature handling in CLI by @lgalabru in #423
  • feat(scenario): add drift on-chain perp dex V2 scenario by @JkrishnaD in #427
  • fix: return non-zero exit code when runbook execution fails by @bytetwt in #415
  • feat(scenario): add kamino-lending scenario by @JkrishnaD in #422
  • Fix --watch flag not working on Linux. by @daedlock in #429
  • fix: make SURFPOOL_DATASOURCE_RPC_URL env var work and hide API keys in UI by @serejke in #426
  • feat(scenario): add meteora-dlmm scenario by @0xsouravm in #421
  • fix: block time in secs instead of ms by @lgalabru in #428
  • feat: Add Switchboard protocol support with SwitchboardQuote override template. by @tanmay4l in #424
  • fix: add account closure tracking to prevent mainnet refetch (#402) by @AvhiMaz in #409
  • feat: add whirlpool overrides by @0xsouravm in #432
  • feat: updated logic to now consider mentions while filtering by @NiravJoshi33 in #403
  • feat(cli): add --runbook-input flag to surfpool start by @shibu0x in #418
  • fix: add backward compatibility for older anchor versions in subgraph generation by @AvhiMaz in #430
  • fix(simnet): improve error handling and port availability checks by @Pawank06 in #439
  • fix(runbooks): bump txtx crate to allow providing is_writable to process_instructions in runbooks by @MicaiahReid in #443
  • tests: add comprehensive tests for Token-2022 by @Shubbu03 in #440
  • Scaffold fixes by @MicaiahReid in #446
  • attempt AWS upload by @MicaiahReid in #389
  • feat: Add transaction ingestion benchmarks using Criterion by @tanmay4l in #444
  • fix(style): correct typo for description text in cli by @qapquiz in #452
  • feat: Add skip_signature_verification option to SimnetConfig by @tanmay4l in #456
  • fix(core): validate durable nonce blockhashes by @MicaiahReid in #453
  • feat(core): add support for loading account snapshots at startup by @MicaiahReid in #464
  • fix: solana program close (stop or stuck surfpool) by @subhdotsol in #457
  • Fix/wsol by @MicaiahReid in #465
  • chore: rename wrong default value on cli by @BretasArthur1 in #470
  • fix: execute runbooks even if project framework isn't detected by @MicaiahReid in #468
  • fix memory leaks by @MicaiahReid in #467
  • feat: add new SVM feature gates for LiteSVM 0.9.0,Add 4 new features,… by @subhdotsol in #471
  • feat: snapshot events through ws by @lgalabru in #466
  • feat(core): enable persistent surfnets by @MicaiahReid in #458
  • ci: add postgres service to tests; test postgres db features by @MicaiahReid in #474
  • fix(cli/core): change db's surfnet_id to use string instead of i32 by @MicaiahReid in #477
  • fix: remove snap store ci and installation docs by @MicaiahReid in #486
  • fix(cli/simnet): improve responsiveness of termination flag no tui mode by @MicaiahReid in #483
  • fix(db): only store blocks with txs; reconstruct sysvars from db on restart by @MicaiahReid in #484
  • fix: implement consistent error handling in geyser runloop by @dvansari65 in #489
  • fix(core): implement missing geyser plugin updates by @MicaiahReid in #490
  • feat: polish tui design by @lgalabru in #488
  • fix : Surfpool not providing : TPU, gossip, QUIC etc information requ… by @subhdotsol in #473
  • fix(core): rpc simulateTransaction loadedAccountsDataSize is None (#475) by @pymongo in #476
  • chore: update litesvm by @lgalabru in #479
  • fix: tui tx ordering & db loading by @MicaiahReid in #493
  • fix: airdrop by @MicaiahReid in #494

New Contributors

Full Changelog: v0.12.0...v1.0.0

v1.0.0-rc1

12 Dec 18:27
611f149

Choose a tag to compare

What's Changed

  • chore: update rmcp by @lgalabru in #411
  • feat: set_log_filter rpc and start_time rpc by @JkrishnaD in #410
  • feat: add list_plugins admin RPC and remove rpc_addr admin RPC method from trait by @0xsouravm in #408
  • chore: remove unused admin RPC methods and clean up imports by @MicaiahReid in #414
  • feat(scenarios): add native Jupiter v6 support & refactor registry by @TanmayDhobale in #413
  • feat(scenario): add raydium amm-v3 scenario by @JkrishnaD in #419
  • feat: svm feature handling in CLI by @lgalabru in #423
  • feat(scenario): add drift on-chain perp dex V2 scenario by @JkrishnaD in #427
  • fix: return non-zero exit code when runbook execution fails by @bytehash69 in #415
  • feat(scenario): add kamino-lending scenario by @JkrishnaD in #422
  • Fix --watch flag not working on Linux. by @daedlock in #429
  • fix: make SURFPOOL_DATASOURCE_RPC_URL env var work and hide API keys in UI by @serejke in #426
  • feat(scenario): add meteora-dlmm scenario by @0xsouravm in #421
  • fix: block time in secs instead of ms by @lgalabru in #428
  • feat: Add Switchboard protocol support with SwitchboardQuote override template. by @TanmayDhobale in #424
  • fix: add account closure tracking to prevent mainnet refetch (#402) by @AvhiMaz in #409
  • feat: add whirlpool overrides by @0xsouravm in #432
  • feat: updated logic to now consider mentions while filtering by @NiravJoshi33 in #403
  • feat(cli): add --runbook-input flag to surfpool start by @shivendram16053 in #418
  • fix: add backward compatibility for older anchor versions in subgraph generation by @AvhiMaz in #430
  • fix(simnet): improve error handling and port availability checks by @Pawank06 in #439
  • fix(runbooks): bump txtx crate to allow providing is_writable to process_instructions in runbooks by @MicaiahReid in #443
  • tests: add comprehensive tests for Token-2022 by @Shubbu03 in #440
  • Scaffold fixes by @MicaiahReid in #446
  • attempt AWS upload by @MicaiahReid in #389
  • feat: Add transaction ingestion benchmarks using Criterion by @TanmayDhobale in #444

New Contributors

Full Changelog: v0.12.0...v1.0.0-rc1

v0.12.0

14 Nov 20:28
c9b633e

Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.11.2...v0.12.0

v0.11.2

24 Oct 02:33

Choose a tag to compare

chore(release): publish v0.11.2

v0.11.1

22 Oct 19:54

Choose a tag to compare

What's Changed

  • feat: add environment variables for public-facing URLs by @serejke in #381
  • feat(cli): solve the no studio flag by @zsh28 in #379
  • fix: sanitize subgraph request before sql insertion by @lgalabru in #377
  • feat: introduce the surfnet_exportSnapshot cheatcode by @Shradhesh71 in #364
  • fix: various fixes to better support anchor by @MicaiahReid in #383
  • feat: introduce cheatcode resetNetwork by @lgalabru in #382

New Contributors

Full Changelog: v0.11.0...v0.11.1