Releases: solana-foundation/surfpool
v1.2.0
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 bynapi-rsnative 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-sdkStart 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_enableCheatcodeandsurfnet_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_offlineAccountprevents Surfpool from downloading a specific account
from the configured remote RPC. PassincludeOwnedAccountsto 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 complementssurfnet_streamAccountand 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
sendBundleRPC 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.sendBundleaccepts up to five serialized transactions, matching Jito's
bundle size limit. Surfpool processes them sequentially in the provided order
and forcesskip_preflightto 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 --featureandsurfpool start --disable-featurenow 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-tracingfeature, 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 startcan now deploy program binaries from a custom artifacts
directory instead of assumingtarget/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
prometheusfeature can expose a/metricsendpoint
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...
v1.1.2
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
What's Changed
- fix: correct bool logic in get_multiple_accounts from remote by @MicaiahReid in #559
- chore(release): publish v1.1.1 by @MicaiahReid in #560
Full Changelog: v1.1.0...v1.1.1
v1.1.0
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
- ci: remove upload of bins to aws by @MicaiahReid in #550
- chore: add installation script by @MicaiahReid in #549
- test: add regression test for token 2022 realloc by @MicaiahReid in #548
- ci: add workflow for building and pushing Docker images by @MicaiahReid in #551
- chore: update litesvm and litesvm-token versions to 0.10.0 by @MicaiahReid in #554
Shoutouts
Thank you so much to our external contributors!
Full Changelog: v1.0.1...v1.1.0
v1.0.1
chore(release): publish v1.0.1
v1.0.0
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
SwitchboardQuoteoverride 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_writableto 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_verificationoption toSimnetConfigby @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
- @JkrishnaD made their first contribution in #410
- @tanmay4l made their first contribution in #413
- @bytetwt made their first contribution in #415
- @daedlock made their first contribution in #429
- @AvhiMaz made their first contribution in #409
- @NiravJoshi33 made their first contribution in #403
- @shibu0x made their first contribution in #418
- @Pawank06 made their first contribution in #439
- @Shubbu03 made their first contribution in #440
- @qapquiz made their first contribution in #452
- @subhdotsol made their first contribution in #457
- @dvansari65 made their first contribution in #489
- @pymongo made their first contribution in #476
Full Changelog: v0.12.0...v1.0.0
v1.0.0-rc1
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
SwitchboardQuoteoverride 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_writableto 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
- @JkrishnaD made their first contribution in #410
- @TanmayDhobale made their first contribution in #413
- @bytehash69 made their first contribution in #415
- @daedlock made their first contribution in #429
- @AvhiMaz made their first contribution in #409
- @NiravJoshi33 made their first contribution in #403
- @shivendram16053 made their first contribution in #418
- @Pawank06 made their first contribution in #439
- @Shubbu03 made their first contribution in #440
Full Changelog: v0.12.0...v1.0.0-rc1
v0.12.0
What's Changed
- fix: allow None, object, and array types in graphql by @MicaiahReid in #393
- feat: scenarios by @lgalabru in #392
- add test_simulate_transaction_no_signers by @daog1 in #395
- feat: implement surfnet_writeProgram cheatcode (#319) by @29deepanshutyagi in #396
- feat: update geyser replica messages by @sonicfromnewyoke in #398
- fix: representation of timestamp in getTransaction rpc method by @sonicfromnewyoke in #401
- chore: update issue templates by @MicaiahReid in #404
- docs: add scenarios README by @MicaiahReid in #405
- fix: capture context slot consistently in
getSignatureStatusesRPC by @serejke in #406 - feat: add reload_plugin and unload_plugin admin RPCs by @0xsouravm in #369
- feat: add surfnet_registerScenario RPC method for scenario registration with account overrides by @MicaiahReid in #407
New Contributors
- @29deepanshutyagi made their first contribution in #396
- @0xsouravm made their first contribution in #369
Full Changelog: v0.11.2...v0.12.0
v0.11.2
chore(release): publish v0.11.2
v0.11.1
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_exportSnapshotcheatcode 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
- @zsh28 made their first contribution in #379
- @Shradhesh71 made their first contribution in #364
Full Changelog: v0.11.0...v0.11.1