surfpool
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSurfpool - Solana Development Environment
Surfpool - Solana开发环境
The definitive guide for Surfpool - where developers start their Solana journey. A drop-in replacement for that enables local program simulation using Mainnet accounts fetched just-in-time.
solana-test-validator这是Surfpool的权威指南——开发者开启Solana开发之旅的起点。它是的直接替代工具,可使用实时获取的主网账户进行本地程序模拟。
solana-test-validatorWhat is Surfpool?
什么是Surfpool?
Surfpool is a comprehensive development environment that combines local-first testing with real Mainnet data access:
- Mainnet Forking - Clone accounts, programs, and token balances from Mainnet instantly
- Cheatcodes - Special RPC methods for time travel, balance manipulation, and state control
- Infrastructure as Code - Reproducible, auditable deployments using txtx DSL
- Surfpool Studio - Embedded dashboard with transaction inspection and profiling
- Universal Faucet - Get SOL, USDC, USDT, BONK from a single interface
Surfpool是一个综合性开发环境,将本地优先测试与真实主网数据访问相结合:
- 主网分叉 - 即时克隆主网中的账户、程序和代币余额
- 作弊码 - 用于时间跳转、余额操控和状态控制的特殊RPC方法
- 基础设施即代码 - 使用txtx DSL实现可复现、可审计的部署
- Surfpool Studio - 内置仪表盘,支持交易检查和性能分析
- 通用水龙头 - 通过单一界面获取SOL、USDC、USDT、BONK
Key Benefits
核心优势
| Feature | Description |
|---|---|
| Instant Boot | No 2TB snapshots, runs on Raspberry Pi |
| Lazy Forking | Copy-on-read strategy pulls mainnet data as needed |
| Full Compatibility | Works with solana-cli, Anchor, wallets, explorers |
| Zero Config | Auto-detects Anchor projects and deploys programs |
| 特性 | 描述 |
|---|---|
| 快速启动 | 无需2TB快照,可在树莓派上运行 |
| 延迟分叉 | 采用读时复制策略,按需拉取主网数据 |
| 完全兼容 | 可与solana-cli、Anchor、钱包、区块浏览器配合使用 |
| 零配置 | 自动检测Anchor项目并部署程序 |
Statistics
项目数据
- 460+ GitHub stars
- 100+ forks
- Apache 2.0 license
- Current version: v1.0.0
- 460+ GitHub星标
- 100+ 复刻数量
- Apache 2.0许可证
- 当前版本:v1.0.0
Installation
安装
Automated Installer (Recommended)
自动安装器(推荐)
bash
curl -sL https://run.surfpool.run/ | bashbash
curl -sL https://run.surfpool.run/ | bashHomebrew (macOS)
Homebrew(macOS系统)
bash
brew install txtx/taps/surfpoolbash
brew install txtx/taps/surfpoolFrom Source
从源码安装
bash
git clone https://github.com/txtx/surfpool.git
cd surfpool
cargo surfpool-installbash
git clone https://github.com/txtx/surfpool.git
cd surfpool
cargo surfpool-installDocker
Docker安装
bash
docker pull surfpool/surfpool
docker run -p 8899:8899 -p 18488:18488 surfpool/surfpoolbash
docker pull surfpool/surfpool
docker run -p 8899:8899 -p 18488:18488 surfpool/surfpoolQuick Start
快速开始
Start Local Network
启动本地网络
bash
undefinedbash
undefinedStart with default configuration
Start with default configuration
surfpool start
surfpool start
Start with custom RPC source
Start with custom RPC source
surfpool start -u https://api.mainnet-beta.solana.com
surfpool start -u https://api.mainnet-beta.solana.com
Start without terminal UI
Start without terminal UI
surfpool start --no-tui
surfpool start --no-tui
Start with debug logging
Start with debug logging
surfpool start --debug
undefinedsurfpool start --debug
undefinedAccess Points
访问地址
| Service | URL | Description |
|---|---|---|
| RPC Endpoint | | Standard Solana RPC |
| WebSocket | | Real-time subscriptions |
| Surfpool Studio | | Web dashboard |
| 服务 | 地址 | 描述 |
|---|---|---|
| RPC端点 | | 标准Solana RPC |
| WebSocket | | 实时订阅 |
| Surfpool Studio | | Web仪表盘 |
CLI Commands
CLI命令
surfpool start
surfpool start
Start the local Surfnet network.
bash
surfpool start [OPTIONS]Options:
| Option | Default | Description |
|---|---|---|
| | Path to manifest file |
| | RPC port |
| | Host address |
| | Slot time in ms |
| | Source RPC URL |
| - | Disable terminal UI |
| - | Enable debug logs |
| - | Disable auto deployments |
| | Runbooks to execute |
| - | Pubkeys to airdrop |
| | Airdrop amount (lamports) |
| - | Keypair path for airdrop |
| - | Disable explorer |
启动本地Surfnet网络。
bash
surfpool start [OPTIONS]选项:
| 选项 | 默认值 | 描述 |
|---|---|---|
| | 清单文件路径 |
| | RPC端口 |
| | 主机地址 |
| | 插槽时间(毫秒) |
| | 源RPC地址 |
| - | 禁用终端UI |
| - | 启用调试日志 |
| - | 禁用自动部署 |
| | 要执行的运行手册 |
| - | 要空投的公钥 |
| | 空投数量(lamports) |
| - | 空投用的密钥对路径 |
| - | 禁用区块浏览器 |
Example Usage
示例用法
bash
undefinedbash
undefinedStart with airdrop to specific address
Start with airdrop to specific address
surfpool start -a YOUR_PUBKEY -q 100000000000
surfpool start -a YOUR_PUBKEY -q 100000000000
Start with custom slot time (faster blocks)
Start with custom slot time (faster blocks)
surfpool start -s 100
surfpool start -s 100
Start with specific runbook
Start with specific runbook
surfpool start -r deployment -r setup
undefinedsurfpool start -r deployment -r setup
undefinedSurfpool.toml Configuration
Surfpool.toml配置
Create a in your project root:
Surfpool.tomltoml
[network]
slot_time = 400
epoch_duration = 432000
rpc_url = "https://api.mainnet-beta.solana.com"
[behavior]在项目根目录创建文件:
Surfpool.tomltoml
[network]
slot_time = 400
epoch_duration = 432000
rpc_url = "https://api.mainnet-beta.solana.com"
[behavior]Fork from mainnet genesis
Fork from mainnet genesis
genesis = false
genesis = false
Fork from specific point
Fork from specific point
point_fork = true
[accounts]
point_fork = true
[accounts]
Pre-clone specific accounts
Pre-clone specific accounts
clone = [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", # Token Program
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", # ATA Program
]
[programs]
clone = [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", # Token Program
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", # ATA Program
]
[programs]
Auto-deploy local programs
Auto-deploy local programs
deploy = ["./target/deploy/my_program.so"]
[airdrop]
deploy = ["./target/deploy/my_program.so"]
[airdrop]
Default airdrop recipients
Default airdrop recipients
addresses = ["YOUR_PUBKEY"]
amount = 10000000000000 # 10,000 SOL
undefinedaddresses = ["YOUR_PUBKEY"]
amount = 10000000000000 # 10,000 SOL
undefinedCheatcodes
作弊码
Surfpool provides special RPC methods for advanced state manipulation during testing.
Surfpool提供特殊的RPC方法,用于测试期间的高级状态操控。
Account Manipulation
账户操控
surfnet_setAccount
surfnet_setAccount
Set arbitrary account data:
typescript
await connection.send("surfnet_setAccount", [
{
pubkey: "AccountPubkey...",
lamports: 1000000000,
data: "base64EncodedData",
owner: "OwnerPubkey...",
executable: false,
},
]);设置任意账户数据:
typescript
await connection.send("surfnet_setAccount", [
{
pubkey: "AccountPubkey...",
lamports: 1000000000,
data: "base64EncodedData",
owner: "OwnerPubkey...",
executable: false,
},
]);surfnet_setTokenAccount
surfnet_setTokenAccount
Create or modify token accounts:
typescript
await connection.send("surfnet_setTokenAccount", [
{
owner: "OwnerPubkey...",
mint: "MintPubkey...",
tokenProgram: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
update: {
amount: "1000000000",
delegate: null,
state: "initialized",
},
},
]);创建或修改代币账户:
typescript
await connection.send("surfnet_setTokenAccount", [
{
owner: "OwnerPubkey...",
mint: "MintPubkey...",
tokenProgram: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
update: {
amount: "1000000000",
delegate: null,
state: "initialized",
},
},
]);surfnet_cloneProgramAccount
surfnet_cloneProgramAccount
Clone a program from mainnet:
typescript
await connection.send("surfnet_cloneProgramAccount", [
{
source: "SourceProgramPubkey...",
destination: "DestinationPubkey...",
},
]);从主网克隆程序:
typescript
await connection.send("surfnet_cloneProgramAccount", [
{
source: "SourceProgramPubkey...",
destination: "DestinationPubkey...",
},
]);surfnet_resetAccount
surfnet_resetAccount
Reset account to mainnet state:
typescript
await connection.send("surfnet_resetAccount", [
{
pubkey: "AccountPubkey...",
includeOwnedAccounts: true,
},
]);将账户重置为主网状态:
typescript
await connection.send("surfnet_resetAccount", [
{
pubkey: "AccountPubkey...",
includeOwnedAccounts: true,
},
]);Time Control
时间控制
surfnet_timeTravel
surfnet_timeTravel
Advance network time:
typescript
await connection.send("surfnet_timeTravel", [
{
epoch: 100,
slot: 50000,
timestamp: 1700000000,
},
]);推进网络时间:
typescript
await connection.send("surfnet_timeTravel", [
{
epoch: 100,
slot: 50000,
timestamp: 1700000000,
},
]);surfnet_pauseClock / surfnet_resumeClock
surfnet_pauseClock / surfnet_resumeClock
Control block production:
typescript
// Pause
await connection.send("surfnet_pauseClock", []);
// Resume
await connection.send("surfnet_resumeClock", []);控制区块生成:
typescript
// Pause
await connection.send("surfnet_pauseClock", []);
// Resume
await connection.send("surfnet_resumeClock", []);surfnet_advanceClock
surfnet_advanceClock
Advance clock incrementally:
typescript
await connection.send("surfnet_advanceClock", [
{ slots: 100 },
]);逐步推进时钟:
typescript
await connection.send("surfnet_advanceClock", [
{ slots: 100 },
]);Transaction Profiling
交易性能分析
surfnet_profileTransaction
surfnet_profileTransaction
Profile transaction execution:
typescript
const result = await connection.send("surfnet_profileTransaction", [
{
transaction: "base64EncodedTx",
tag: "my-test-tag",
},
]);
console.log("Compute units:", result.computeUnits);
console.log("Account changes:", result.accountChanges);分析交易执行情况:
typescript
const result = await connection.send("surfnet_profileTransaction", [
{
transaction: "base64EncodedTx",
tag: "my-test-tag",
},
]);
console.log("Compute units:", result.computeUnits);
console.log("Account changes:", result.accountChanges);surfnet_getProfileResults
surfnet_getProfileResults
Get profiling results by tag:
typescript
const results = await connection.send("surfnet_getProfileResults", [
{ tag: "my-test-tag" },
]);按标签获取性能分析结果:
typescript
const results = await connection.send("surfnet_getProfileResults", [
{ tag: "my-test-tag" },
]);Network Control
网络控制
surfnet_resetNetwork
surfnet_resetNetwork
Reset entire network to initial state:
typescript
await connection.send("surfnet_resetNetwork", []);将整个网络重置为初始状态:
typescript
await connection.send("surfnet_resetNetwork", []);surfnet_getClock
surfnet_getClock
Get current network time:
typescript
const clock = await connection.send("surfnet_getClock", []);
console.log("Slot:", clock.slot);
console.log("Epoch:", clock.epoch);
console.log("Timestamp:", clock.timestamp);获取当前网络时间:
typescript
const clock = await connection.send("surfnet_getClock", []);
console.log("Slot:", clock.slot);
console.log("Epoch:", clock.epoch);
console.log("Timestamp:", clock.timestamp);Surfpool Studio
Surfpool Studio
Access the web dashboard at for:
http://127.0.0.1:18488- Transaction Inspector - View transaction details with byte-level diffs
- Account Browser - Explore account state and history
- Compute Profiler - Analyze compute unit usage per instruction
- Universal Faucet - Request SOL and tokens
- Network Status - Monitor slots, epochs, and block production
访问打开Web仪表盘,可使用以下功能:
http://127.0.0.1:18488- 交易检查器 - 查看交易详情,支持字节级差异对比
- 账户浏览器 - 浏览账户状态与历史记录
- 计算资源分析器 - 分析每条指令的计算单元使用情况
- 通用水龙头 - 请求SOL和代币
- 网络状态监控 - 监控插槽、纪元和区块生成情况
Infrastructure as Code
基础设施即代码
Surfpool integrates txtx DSL for reproducible deployments.
Surfpool集成txtx DSL,实现可复现的部署。
Runbook Structure
运行手册结构
hcl
undefinedhcl
undefineddeployment.tx
deployment.tx
// Define signers
signer "deployer" "svm::secret_key" {
secret_key = env.DEPLOYER_KEY
}
// Deploy program
action "deploy_program" "svm::deploy_program" {
program_path = "./target/deploy/my_program.so"
signer = signer.deployer
}
// Initialize program
action "initialize" "svm::send_transaction" {
transaction {
instruction {
program_id = action.deploy_program.program_id
data = encode_instruction("initialize", {})
}
}
signers = [signer.deployer]
}
undefined// Define signers
signer "deployer" "svm::secret_key" {
secret_key = env.DEPLOYER_KEY
}
// Deploy program
action "deploy_program" "svm::deploy_program" {
program_path = "./target/deploy/my_program.so"
signer = signer.deployer
}
// Initialize program
action "initialize" "svm::send_transaction" {
transaction {
instruction {
program_id = action.deploy_program.program_id
data = encode_instruction("initialize", {})
}
}
signers = [signer.deployer]
}
undefinedRunning Runbooks
运行运行手册
bash
undefinedbash
undefinedRun specific runbook
Run specific runbook
surfpool start -r deployment
surfpool start -r deployment
Run in unsupervised mode
Run in unsupervised mode
surfpool start -r deployment --unsupervised
undefinedsurfpool start -r deployment --unsupervised
undefinedScenarios and Fixtures
场景与测试夹具
Scenarios
场景
Define account state sequences for testing:
typescript
await connection.send("surfnet_registerScenario", [
{
name: "high-volume-trading",
slots: [
{
slot: 100,
accounts: {
"PoolPubkey...": { lamports: 1000000000000 },
},
},
{
slot: 200,
accounts: {
"PoolPubkey...": { lamports: 500000000000 },
},
},
],
},
]);定义用于测试的账户状态序列:
typescript
await connection.send("surfnet_registerScenario", [
{
name: "high-volume-trading",
slots: [
{
slot: 100,
accounts: {
"PoolPubkey...": { lamports: 1000000000000 },
},
},
{
slot: 200,
accounts: {
"PoolPubkey...": { lamports: 500000000000 },
},
},
],
},
]);Fixtures
测试夹具
Export transaction fixtures for reproducible tests:
typescript
const fixture = await connection.send("surfnet_exportSnapshot", [
{
transaction: "txSignature...",
format: "json",
},
]);
// Save fixture for CI/CD
fs.writeFileSync("fixtures/my-test.json", JSON.stringify(fixture));导出交易夹具,用于可复现的测试:
typescript
const fixture = await connection.send("surfnet_exportSnapshot", [
{
transaction: "txSignature...",
format: "json",
},
]);
// Save fixture for CI/CD
fs.writeFileSync("fixtures/my-test.json", JSON.stringify(fixture));Integration with Anchor
与Anchor的集成
Surfpool auto-detects Anchor projects and handles deployment:
bash
undefinedSurfpool会自动检测Anchor项目并处理部署:
bash
undefinedIn an Anchor project directory
In an Anchor project directory
surfpool start
surfpool start
Programs in target/deploy/ are automatically deployed
Programs in target/deploy/ are automatically deployed
undefinedundefinedTesting with Anchor
使用Anchor进行测试
typescript
import * as anchor from "@coral-xyz/anchor";
describe("My Program", () => {
// Use local Surfnet
const provider = anchor.AnchorProvider.local("http://127.0.0.1:8899");
anchor.setProvider(provider);
it("works with mainnet state", async () => {
// Your tests automatically have access to mainnet accounts
});
});typescript
import * as anchor from "@coral-xyz/anchor";
describe("My Program", () => {
// Use local Surfnet
const provider = anchor.AnchorProvider.local("http://127.0.0.1:8899");
anchor.setProvider(provider);
it("works with mainnet state", async () => {
// Your tests automatically have access to mainnet accounts
});
});Best Practices
最佳实践
1. Use Cheatcodes for Setup
1. 使用作弊码进行测试准备
typescript
// Set up test state before each test
beforeEach(async () => {
await connection.send("surfnet_resetNetwork", []);
await connection.send("surfnet_setTokenAccount", [...]);
});typescript
// Set up test state before each test
beforeEach(async () => {
await connection.send("surfnet_resetNetwork", []);
await connection.send("surfnet_setTokenAccount", [...]);
});2. Profile Critical Paths
2. 分析关键路径性能
typescript
// Tag transactions for profiling
const result = await connection.send("surfnet_profileTransaction", [
{ transaction: tx, tag: "swap-operation" },
]);
expect(result.computeUnits).toBeLessThan(200000);typescript
// Tag transactions for profiling
const result = await connection.send("surfnet_profileTransaction", [
{ transaction: tx, tag: "swap-operation" },
]);
expect(result.computeUnits).toBeLessThan(200000);3. Use Scenarios for Edge Cases
3. 使用场景测试边缘情况
typescript
// Test with specific mainnet conditions
await connection.send("surfnet_registerScenario", [
{ name: "low-liquidity", slots: [...] },
]);typescript
// Test with specific mainnet conditions
await connection.send("surfnet_registerScenario", [
{ name: "low-liquidity", slots: [...] },
]);4. Export Fixtures for CI
4. 导出测试夹具用于CI/CD
typescript
// Create reproducible test fixtures
const fixture = await connection.send("surfnet_exportSnapshot", [...]);typescript
// Create reproducible test fixtures
const fixture = await connection.send("surfnet_exportSnapshot", [...]);Resources
资源
Official Links
官方链接
- Website: https://surfpool.run
- Documentation: https://docs.surfpool.run
- GitHub: https://github.com/txtx/surfpool
Community
社区
- Discord: https://discord.gg/surfpool
- Twitter: @surfaboratory
- Telegram: Announcements channel
- Discord: https://discord.gg/surfpool
- Twitter: @surfaboratory
- Telegram: 公告频道
Tutorials
教程
Skill Structure
技能结构
surfpool/
├── SKILL.md # This file
├── resources/
│ ├── cheatcodes.md # Complete cheatcodes reference
│ ├── cli-reference.md # CLI commands reference
│ └── github-repos.md # Repository links
├── examples/
│ ├── basic/
│ │ └── getting-started.ts # Basic setup example
│ ├── cheatcodes/
│ │ └── state-manipulation.ts # Cheatcode examples
│ └── iac/
│ └── deployment.tx # Infrastructure as Code example
├── templates/
│ ├── Surfpool.toml # Configuration template
│ └── test-setup.ts # Test setup template
└── docs/
└── troubleshooting.md # Common issuessurfpool/
├── SKILL.md # This file
├── resources/
│ ├── cheatcodes.md # Complete cheatcodes reference
│ ├── cli-reference.md # CLI commands reference
│ └── github-repos.md # Repository links
├── examples/
│ ├── basic/
│ │ └── getting-started.ts # Basic setup example
│ ├── cheatcodes/
│ │ └── state-manipulation.ts # Cheatcode examples
│ └── iac/
│ └── deployment.tx # Infrastructure as Code example
├── templates/
│ ├── Surfpool.toml # Configuration template
│ └── test-setup.ts # Test setup template
└── docs/
└── troubleshooting.md # Common issues