Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Solana development skill covering @solana/kit v5, Anchor programs, LiteSVM testing, and security patterns.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/surfpool/overview.md
1---2title: Surfpool3description: A drop-in replacement for solana-test-validator with sub-second startup, automatic mainnet state cloning, transaction profiling, and a built-in web UI.4---56# Surfpool Reference78## What is Surfpool910Surfpool is a drop-in replacement for `solana-test-validator` built on [LiteSVM](https://github.com/LiteSVM/litesvm). It provides a local Solana network (called a "surfnet") with sub-second startup, automatic mainnet state cloning, transaction profiling, and a built-in web UI (Studio).1112Key differences from `solana-test-validator`:13- **Instant startup** — no genesis ledger to bootstrap; the SVM runs in-process.14- **Mainnet state on demand** — accounts are lazily fetched from a remote RPC and cached locally. No need to pre-clone accounts.15- **Cheatcodes** — 22 `surfnet_*` RPC methods to manipulate time, accounts, programs, and scenarios without restarting.16- **Transaction profiling** — compute-unit estimation with before/after account snapshots.17- **Scenario system** — override protocol state (Pyth, Jupiter, Raydium, etc.) to simulate market conditions.18- **Infrastructure as Code** — define deployment runbooks in `txtx.yml` and auto-execute on start.19- **MCP server** — expose surfnet operations as tool calls for AI agents.2021## Installation2223```bash24curl -sL https://run.surfpool.run/ | bash25```2627Or install from source with Cargo:2829```bash30cargo surfpool-install31```3233Verify installation:3435```bash36surfpool --version37```3839## Agent Usage (NO_DNA)4041When running surfpool commands as an agent, always prefix with `NO_DNA=1`. This disables TUI, interactive prompts, and enables verbose structured output:4243```bash44NO_DNA=1 surfpool start45NO_DNA=1 surfpool start --watch46NO_DNA=1 surfpool run deployment --unsupervised --output-json ./outputs/47```4849See [no-dna.org](https://no-dna.org) for the full standard.5051## Quick Start5253### Anchor Project5455Start surfpool in the root of an Anchor workspace. It detects `txtx.yml` (or generates one) and deploys programs automatically:5657```bash58cd my-anchor-project59surfpool start60```6162Use `--watch` to auto-redeploy when `.so` files change in `target/deploy/`:6364```bash65surfpool start --watch66```6768For Anchor test suites, enable compatibility mode:6970```bash71surfpool start --legacy-anchor-compatibility72```7374### Mainnet State Cloning7576Fork mainnet state with zero config — accounts are fetched lazily when accessed:7778```bash79surfpool start --network mainnet80```8182Use a custom RPC for better rate limits:8384```bash85surfpool start --rpc-url https://my-rpc-provider.com86```8788Run fully offline (no remote fetching):8990```bash91surfpool start --offline92```9394### CI Mode9596Start with CI-optimized defaults (no TUI, no Studio, no profiling, no logs):9798```bash99surfpool start --ci100```101102Run as a background daemon (Linux only):103104```bash105surfpool start --ci --daemon106```107108## When to Use Surfpool109110| Criterion | surfpool | solana-test-validator | litesvm / bankrun |111|---|---|---|---|112| Startup time | Sub-second | 10-30 seconds | Sub-second |113| Architecture | In-process SVM (LiteSVM) | Full validator runtime | In-process SVM |114| RPC server | Full JSON-RPC on port 8899 | Full JSON-RPC on port 8899 | No RPC server (bankrun has limited BanksClient) |115| WebSocket support | Yes (port 8900) | Yes | No |116| Mainnet state | Lazy clone on first access | Manual `--clone` per account | Manual account setup |117| Account manipulation | 22 cheatcode RPC methods | None (restart + `--account` files) | Direct `set_account()` in-process |118| Time control | `surfnet_timeTravel`, `pauseClock`, `resumeClock` | `--slots-per-epoch`, warp via CLI | `warp_to_slot()` in-process |119| Transaction profiling | Built-in CU profiling with snapshots | None | None |120| Program hot-reload | `--watch` flag | Restart required | Restart required |121| Web UI | Studio (port 18488) | None | None |122| Protocol scenarios | 8 built-in protocols | None | None |123| MCP server | Built-in (`surfpool mcp`) | None | None |124| Geyser plugins | Supported | Supported | Not supported |125| CI mode | `--ci` flag | Manual config | Native (no server needed) |126| Infrastructure as Code | txtx.yml runbooks | None | None |127| Offline mode | `--offline` flag | Always offline | Always offline |128| Persistent state | `--db` flag (SQLite) | Ledger directory | None |129130**Use surfpool** for local development, integration testing, mainnet forking, and CI pipelines that need an RPC endpoint.131132**Use litesvm/bankrun** for unit-level program tests that run in-process without an RPC server.133134**Use solana-test-validator** only when specific validator runtime behavior is required that surfpool does not yet replicate (vote processing, leader schedule, etc.).135136### Decision Tree137138- **Unit test exercising a single instruction in isolation?** Use litesvm (Rust) or bankrun (JS/Python).139- **Need a full JSON-RPC endpoint?** Use surfpool.140- **Need mainnet account state (tokens, programs, oracles)?** Use surfpool (lazy cloning).141- **Need to manipulate time, accounts, or protocol state at runtime?** Use surfpool (cheatcodes).142- **Local dev environment with hot-reload?** Use surfpool (`--watch`).143- **CI pipeline needing RPC?** Use `surfpool start --ci`.144- **DeFi scenario simulation?** Use surfpool (scenario system).145- **Full validator fidelity?** Use solana-test-validator.146147### Summary Table148149| Use Case | Recommended Tool |150|---|---|151| Unit testing a single instruction | litesvm / bankrun |152| Integration testing with RPC | surfpool |153| Local development with hot-reload | surfpool |154| Mainnet fork testing | surfpool |155| CI pipeline (needs RPC) | surfpool (`--ci`) |156| CI pipeline (in-process only) | litesvm / bankrun |157| DeFi scenario simulation | surfpool |158| AI agent-assisted development | surfpool (MCP server) |159| Full validator fidelity testing | solana-test-validator |160161## Migration from solana-test-validator162163Replace:164165```bash166solana-test-validator \167--clone TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA \168--clone <account-1> \169--clone <account-2> \170--url https://api.mainnet-beta.solana.com \171--reset172```173174With:175176```bash177surfpool start178```179180Accounts are cloned lazily — no need to specify them upfront.181182Replace account file loading:183184```bash185solana-test-validator --account <pubkey> ./account.json186```187188With snapshot loading:189190```bash191surfpool start --snapshot ./accounts.json192```193194Or use cheatcodes at runtime:195196```bash197curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \198-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_setAccount","params":["<pubkey>",{"lamports":1000000000}]}'199```200201### From litesvm/bankrun (adding RPC layer)202203If in-process tests need to be promoted to integration tests with an RPC endpoint, start surfpool alongside:204205```bash206surfpool start --ci207```208209Then point the test client to `http://127.0.0.1:8899` instead of using the in-process bank.210211## CLI Reference212213### `surfpool start`214215Start a local Solana network (surfnet). Alias: `surfpool simnet`.216217#### Network Configuration218219| Flag | Short | Default | Env Var | Description |220|---|---|---|---|---|221| `--port` | `-p` | `8899` | — | RPC port |222| `--ws-port` | `-w` | `8900` | — | WebSocket port |223| `--host` | `-o` | `127.0.0.1` | `SURFPOOL_NETWORK_HOST` | Bind address |224| `--rpc-url` | `-u` | — | `SURFPOOL_DATASOURCE_RPC_URL` | Custom datasource RPC URL (conflicts with `--network`) |225| `--network` | `-n` | — | — | Predefined network: `mainnet`, `devnet`, `testnet` (conflicts with `--rpc-url`) |226| `--offline` | — | `false` | — | Start without a remote RPC client |227228#### Block Production229230| Flag | Short | Default | Description |231|---|---|---|---|232| `--slot-time` | `-t` | `400` | Slot time in milliseconds |233| `--block-production-mode` | `-b` | `clock` | Block production mode: `clock`, `transaction`, `manual` |234235Modes:236- `clock` — advance slots at a fixed interval (default, `400ms`)237- `transaction` — advance a slot only when a transaction is received238- `manual` — slots only advance via explicit RPC calls239240#### Airdrops241242| Flag | Short | Default | Description |243|---|---|---|---|244| `--airdrop` | `-a` | — | Pubkey(s) to airdrop SOL to on start. Repeatable. |245| `--airdrop-amount` | `-q` | `10000000000000` | Amount of lamports to airdrop (default ~10,000 SOL) |246| `--airdrop-keypair-path` | `-k` | `~/.config/solana/id.json` | Keypair file(s) to airdrop to. Repeatable. |247248#### Deployment & Runbooks249250| Flag | Short | Default | Description |251|---|---|---|---|252| `--manifest-file-path` | `-m` | `./txtx.yml` | Path to the runbook manifest |253| `--runbook` | `-r` | `deployment` | Runbook ID(s) to execute. Repeatable. |254| `--runbook-input` | `-i` | — | JSON input file(s) for runbooks. Repeatable. |255| `--no-deploy` | — | `false` | Disable auto deployment |256| `--yes` | `-y` | `false` | Skip runbook generation prompts |257| `--watch` | — | `false` | Auto re-execute deployment on `.so` file changes in `target/deploy/` |258259#### Anchor Compatibility260261| Flag | Short | Default | Description |262|---|---|---|---|263| `--legacy-anchor-compatibility` | — | `false` | Apply Anchor test suite defaults |264| `--anchor-test-config-path` | — | — | Path(s) to `Test.toml` files. Repeatable. |265266#### Studio267268| Flag | Short | Default | Description |269|---|---|---|---|270| `--studio-port` | `-s` | `18488` | Studio web UI port |271| `--no-studio` | — | `false` | Disable Studio |272273#### Profiling & Logging274275| Flag | Short | Default | Description |276|---|---|---|---|277| `--disable-instruction-profiling` | — | `false` | Disable instruction profiling |278| `--max-profiles` | `-c` | `200` | Max transaction profiles to hold in memory |279| `--log-level` | `-l` | `info` | Log level: `trace`, `debug`, `info`, `warn`, `error`, `none` |280| `--log-path` | — | `.surfpool/logs` | Log file directory |281| `--log-bytes-limit` | — | `10000` | Max bytes in transaction logs (0 = unlimited) |282283#### SVM Features284285| Flag | Short | Default | Description |286|---|---|---|---|287| `--feature` | `-f` | — | Enable specific SVM features. Repeatable. |288| `--disable-feature` | — | — | Disable specific SVM features. Repeatable. |289| `--features-all` | — | `false` | Enable all SVM features (override mainnet defaults) |290291By default, surfpool uses mainnet feature flags.292293#### Plugins & Subgraphs294295| Flag | Short | Default | Description |296|---|---|---|---|297| `--geyser-plugin-config` | `-g` | — | Geyser plugin config file(s). Repeatable. |298| `--subgraph-db` | `-d` | `:memory:` | Subgraph database URL (SQLite or Postgres) |299300#### Persistence & Snapshots301302| Flag | Short | Default | Description |303|---|---|---|---|304| `--db` | — | — | Surfnet database URL for persistent state (`:memory:` or `*.sqlite`) |305| `--surfnet-id` | — | `default` | Unique ID to isolate database storage across instances |306| `--snapshot` | — | — | JSON snapshot file(s) to preload accounts from. Repeatable. |307308#### Telemetry309310| Flag | Short | Default | Env Var | Description |311|---|---|---|---|---|312| `--metrics-enabled` | — | `false` | `SURFPOOL_METRICS_ENABLED` | Enable Prometheus metrics |313| `--metrics-addr` | — | `0.0.0.0:9000` | `SURFPOOL_METRICS_ADDR` | Prometheus endpoint address |314315#### Process Control316317| Flag | Short | Default | Description |318|---|---|---|---|319| `--no-tui` | — | `false` | Stream logs instead of terminal UI |320| `--daemon` | — | `false` | Run as background process (Linux only) |321| `--ci` | — | `false` | CI mode (sets `--no-tui`, `--no-studio`, `--disable-instruction-profiling`, `--log-level none`) |322| `--skip-signature-verification` | — | `false` | Skip signature verification for all transactions |323324### `surfpool run`325326Execute a runbook from the manifest.327328| Flag | Short | Default | Description |329|---|---|---|---|330| `--manifest-file-path` | `-m` | `./txtx.yml` | Path to the manifest |331| `--unsupervised` | `-u` | `false` | Execute without interactive supervision |332| `--browser` | `-b` | `false` | Supervise via browser UI |333| `--terminal` | `-t` | `false` | Supervise via terminal (coming soon) |334| `--output-json` | — | — | Output results as JSON. Optional directory path. |335| `--output` | — | — | Pick a specific output to stdout |336| `--explain` | — | `false` | Explain execution plan without running |337| `--env` | — | — | Environment from txtx.yml |338| `--input` | — | — | Input file(s) for batch processing. Repeatable. |339| `--force` | `-f` | `false` | Execute even if cached state shows already executed |340| `--log-level` | `-l` | `info` | Log level |341| `--log-path` | — | `.surfpool/logs` | Log directory |342343Positional argument: `<runbook>` — runbook name or `.tx` file path.344345```bash346# Execute interactively in browser347surfpool run deployment348349# Execute without supervision, output JSON350surfpool run deployment --unsupervised --output-json ./outputs/351352# Force re-execution353surfpool run deployment --unsupervised --force354```355356### `surfpool ls`357358List runbooks in the current directory.359360| Flag | Short | Default | Description |361|---|---|---|---|362| `--manifest-file-path` | `-m` | `./txtx.yml` | Path to the manifest |363364### `surfpool mcp`365366Start the MCP (Model Context Protocol) server for AI agent integrations. No additional flags.367368```bash369surfpool mcp370```371372### `surfpool completions`373374Generate shell completion scripts. Alias: `surfpool completion`.375376Positional argument: `<shell>` — `bash`, `zsh`, `fish`, `elvish`, `powershell`.377378```bash379surfpool completions zsh380```381382### Environment Variables383384| Variable | Description | Used By |385|---|---|---|386| `NO_DNA` | Non-human operator signal — disables TUI, prompts; enables verbose/structured output | All commands |387| `SURFPOOL_DATASOURCE_RPC_URL` | Default datasource RPC URL | `--rpc-url` |388| `SURFPOOL_NETWORK_HOST` | Override bind host | `--host` |389| `SURFPOOL_METRICS_ENABLED` | Enable Prometheus metrics | `--metrics-enabled` |390| `SURFPOOL_METRICS_ADDR` | Prometheus endpoint address | `--metrics-addr` |391392## Infrastructure as Code393394Surfpool uses `txtx.yml` manifests and runbooks to define deployment workflows.395396### Manifest Structure397398Place a `txtx.yml` at the project root:399400```yaml401name: my-project402runbooks:403- name: deployment404description: Deploy programs to localnet405file: ./runbooks/deployment.tx406```407408### Auto-Deploy with Watch409410Combine `--watch` with runbooks to auto-redeploy on `.so` file changes:411412```bash413surfpool start --watch --runbook deployment414```415416### Runbook Inputs417418Pass inputs to runbooks for parameterized deployments:419420```bash421surfpool start --runbook-input params.json422```423424## MCP Integration425426Surfpool includes a built-in MCP (Model Context Protocol) server for AI agent integrations. The server communicates over stdio using the MCP protocol.427428### Configuration429430The MCP server uses stdio transport. Add the server entry to your tool's MCP config file:431432| Tool | Config file |433|---|---|434| Claude Code | `.claude/settings.json` (project) or `~/.claude/settings.json` (global) |435| Claude Desktop | `claude_desktop_config.json` |436| Cursor | `.cursor/mcp.json` |437| Windsurf | `~/.codeium/windsurf/mcp_config.json` |438| VS Code / Copilot | `.vscode/mcp.json` |439| Codex | `codex.json` or MCP config via CLI |440441**Standard MCP config** (Claude Code, Claude Desktop, Cursor, Windsurf):442443```json444{445"mcpServers": {446"surfpool": {447"command": "surfpool",448"args": ["mcp"]449}450}451}452```453454**VS Code / Copilot** (uses `servers` instead of `mcpServers`):455456```json457{458"servers": {459"surfpool": {460"command": "surfpool",461"args": ["mcp"]462}463}464}465```466467For any other MCP-compatible tool, use the stdio transport with command `surfpool` and args `["mcp"]`.468469### Available MCP Tools470471| Tool | Description |472|---|---|473| `start_surfnet` | Start a local Solana network. Default returns a shell command; `run_as_subprocess: true` starts in background. |474| `set_token_accounts` | Set SOL/SPL token balances for accounts on a running surfnet |475| `start_surfnet_with_token_accounts` | Start network + fund accounts in one call (background process) |476| `call_surfnet_rpc` | Call any RPC method (standard Solana or `surfnet_*` cheatcodes) on a running surfnet |477| `create_scenario` | Create a protocol state scenario. Read `override_templates` resource first. |478| `get_override_templates` | List available override templates |479480### MCP Resources481482| Resource URI | Description |483|---|---|484| `str:///rpc_endpoints` | List of all available RPC endpoints |485| `str:///override_templates` | All available scenario override templates |486487### Agent Workflow via MCP4884891. **Start surfnet:** Call `start_surfnet` or `start_surfnet_with_token_accounts`4902. **Set up state:** Use `set_token_accounts` to fund accounts, or `call_surfnet_rpc` with cheatcodes4913. **Create scenarios:** Read `override_templates`, then call `create_scenario`4924. **Execute transactions:** Use `call_surfnet_rpc` with `sendTransaction` or `simulateTransaction`4935. **Inspect results:** Use `call_surfnet_rpc` with `surfnet_getTransactionProfile` or `surfnet_exportSnapshot`494495## Cheatcodes Overview496497Surfpool exposes 22 `surfnet_*` JSON-RPC methods on the same port as the standard Solana RPC:498499### Account Manipulation500- `surfnet_setAccount` — set lamports, data, owner, executable flag on any account501- `surfnet_setTokenAccount` — set SPL token account balances, delegates, state502- `surfnet_resetAccount` — restore an account to its initial state503- `surfnet_streamAccount` — mark an account for automatic remote fetching and caching504- `surfnet_getStreamedAccounts` — list all streamed accounts505506### Program Management507- `surfnet_cloneProgramAccount` — copy a program from one address to another508- `surfnet_setProgramAuthority` — change a program's upgrade authority509- `surfnet_writeProgram` — deploy program data in chunks (bypasses TX size limits)510- `surfnet_registerIdl` — register an IDL for a program in memory511- `surfnet_getActiveIdl` — retrieve the registered IDL for a program512513### Time Control514- `surfnet_timeTravel` — jump to an absolute timestamp, slot, or epoch515- `surfnet_pauseClock` — freeze slot advancement516- `surfnet_resumeClock` — resume slot advancement517518### Transaction Profiling519- `surfnet_profileTransaction` — simulate a transaction and return CU estimates with account snapshots520- `surfnet_getTransactionProfile` — retrieve a stored profile by signature or UUID521- `surfnet_getProfileResultsByTag` — retrieve all profiles for a given tag522523### Network State524- `surfnet_setSupply` — configure what `getSupply` returns525- `surfnet_resetNetwork` — reset the entire network to initial state526- `surfnet_getLocalSignatures` — get recent transaction signatures with logs527- `surfnet_getSurfnetInfo` — get network info including runbook execution history528- `surfnet_exportSnapshot` — export all account state as a JSON snapshot529530### Scenarios531- `surfnet_registerScenario` — register a set of account overrides on a timeline532533See [cheatcodes.md](cheatcodes.md) for full parameter schemas and JSON-RPC examples.534535## Scenarios Overview536537The scenario system allows overriding protocol account state to simulate market conditions, liquidation events, and oracle price movements without deploying mock contracts.538539### Supported Protocols540541| Protocol | Version | Account Types | Templates |542|---|---|---|---|543| Pyth | v2 | PriceUpdateV2 | SOL/USD, BTC/USD, ETH/USD, ETH/BTC |544| Jupiter | v6 | TokenLedger | Token ledger override |545| Raydium | CLMM v3 | PoolState | SOL/USDC, BTC/USDC, ETH/USDC |546| Switchboard | on-demand | SwitchboardQuote | Quote override |547| Meteora | DLMM v1 | LbPair | SOL/USDC, USDT/SOL |548| Kamino | v1 | Reserve, Obligation | Reserve state, reserve config, obligation health |549| Drift | v2 | PerpMarket, SpotMarket, User, State | Perp market, spot market, user state, global state |550| Whirlpool | v0.7.0 | Whirlpool | SOL/USDC, SOL/USDT, mSOL/SOL, ORCA/USDC |551552Protocol templates and scenario coverage are summarized in this section.553554## Common Agent Workflows555556> **Note:** All commands below should be prefixed with `NO_DNA=1` when run by an agent.557558### 1. Start a Local Network and Deploy a Program559560```bash561NO_DNA=1 surfpool start --watch562```563564Surfpool detects `txtx.yml`, generates a deployment runbook if needed, deploys programs, and airdrops SOL to the default keypair. The RPC is available at `http://127.0.0.1:8899`.565566### 2. Set Up Token Accounts for Testing567568```bash569curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \570-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_setTokenAccount","params":["<OWNER>","<MINT>",{"amount":"1000000000"}]}'571```572573### 3. Test Time-Sensitive Logic574575```bash576# Pause577curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \578-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_pauseClock","params":[]}'579580# Time travel to a future epoch581curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \582-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_timeTravel","params":[{"absoluteEpoch":100}]}'583584# Resume585curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \586-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_resumeClock","params":[]}'587```588589### 4. Profile Transaction Compute Units590591```bash592curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \593-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_profileTransaction","params":["<BASE64_TX>"]}'594```595596### 5. Export and Restore State597598```bash599# Export snapshot600curl -X POST http://127.0.0.1:8899 -H "Content-Type: application/json" \601-d '{"jsonrpc":"2.0","id":1,"method":"surfnet_exportSnapshot","params":[]}'602603# Load on next start604NO_DNA=1 surfpool start --snapshot ./snapshot.json605```606