关于 surfpool
surfpool 是面向 Solana 开发者的本地开发环境,可替代 `solana-test-validator`,并按需读取 Mainnet 数据。它支持状态操控、部署自动化和交易分析,适用于基于真实链上账户进行测试。
主要功能
- 01按需分叉 Mainnet 账户和程序
- 02通过 RPC Cheatcodes 操控状态与时间
- 03自动检测 Anchor 项目并部署程序
- 04用 Surfpool Studio 检查交易和计算用量
- 05通过 txtx DSL 编写可复现部署
适用场景
- 01使用 Mainnet 账户状态测试 Solana 程序
- 02设置余额、账户数据或网络时间来覆盖边界情况
- 03分析交易计算用量并查看账户状态
- 04为测试和 CI 导出可复现的交易快照
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sendaifun/ skills --skill surfpool安装后在 Claude Code 中输入/surfpool确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
docs/troubleshooting.mdexamples/basic/getting-started.tsexamples/cheatcodes/state-manipulation.tsexamples/iac/deployment.txresources/cheatcodes.mdcli-reference.mdgithub-repos.mdtemplates/Surfpool.tomltest-setup.ts详细介绍
Surfpool - Solana 开发环境
Surfpool 权威指南——开发者 Solana 之旅的起点。它可直接替代 solana-test-validator,利用即时获取的 Mainnet 账户在本地模拟程序。
什么是 Surfpool?
Surfpool 是一个全面的开发环境,将本地优先测试与真实 Mainnet 数据访问相结合:
- Mainnet 分叉 - 即时克隆 Mainnet 上的账户、程序和代币余额
- 作弊码 - 用于时间穿越、余额调整和状态控制的特殊 RPC 方法
- 基础设施即代码 - 使用 txtx DSL 实现可复现、可审计的部署
- Surfpool Studio - 内嵌仪表板,支持交易检查和性能分析
- 通用水龙头 - 通过单一界面获取 SOL、USDC、USDT、BONK
主要优势
| 功能 | 说明 |
|---|---|
| 即时启动 | 无需 2 TB 快照,可在 Raspberry Pi 上运行 |
| 惰性分叉 | 按需复制数据的策略会在需要时拉取 mainnet 数据 |
| 完全兼容 | 适用于 solana-cli、Anchor、钱包和区块链浏览器 |
| 零配置 | 自动检测 Anchor 项目并部署程序 |
统计数据
- 460+ GitHub 星标
- 100+ 个复刻
- Apache 2.0 许可证
- 当前版本:v1.0.0
安装
自动安装程序(推荐)
curl -sL https://run.surfpool.run/ | bash
Homebrew(macOS)
brew install txtx/taps/surfpool
从源代码安装
git clone https://github.com/txtx/surfpool.git
cd surfpool
cargo surfpool-install
Docker
docker pull surfpool/surfpool
docker run -p 8899:8899 -p 18488:18488 surfpool/surfpool
快速开始
启动本地网络
# Start with default configuration
surfpool start
# Start with custom RPC source
surfpool start -u https://api.mainnet-beta.solana.com
# Start without terminal UI
surfpool start --no-tui
# Start with debug logging
surfpool start --debug
访问地址
| 服务 | URL | 说明 |
|---|---|---|
| RPC 端点 | http://127.0.0.1:8899 | 标准 Solana RPC |
| WebSocket | ws://127.0.0.1:8900 | 实时订阅 |
| Surfpool Studio | http://127.0.0.1:18488 | Web 仪表板 |
CLI 命令
surfpool start
启动本地 Surfnet 网络。
surfpool start [OPTIONS]
选项:
| 选项 | 默认值 | 说明 |
|---|---|---|
-m, --manifest-file-path | ./Surfpool.toml | 清单文件路径 |
-p, --port | 8899 | RPC 端口 |
-o, --host | 127.0.0.1 | 主机地址 |
-s, --slot-time | 400 | Slot 时间,单位为毫秒 |
-u, --rpc-url | https://api.mainnet-beta.solana.com | 源 RPC URL |
--no-tui | - | 禁用终端 UI |
--debug | - | 启用调试日志 |
--no-deploy | - | 禁用自动部署 |
-r, --runbook | deployment | 要执行的运行手册 |
-a, --airdrop | - | 要空投的公钥 |
-q, --airdrop-amount | 10000000000000 | 空投数量(lamports) |
-k, --airdrop-keypair-path | - | 空投使用的密钥对路径 |
--no-explorer | - | 禁用区块链浏览器 |
使用示例
# Start with airdrop to specific address
surfpool start -a YOUR_PUBKEY -q 100000000000
# Start with custom slot time (faster blocks)
surfpool start -s 100
# Start with specific runbook
surfpool start -r deployment -r setup
Surfpool.toml 配置
在项目根目录中创建 Surfpool.toml:
[network]
slot_time = 400
epoch_duration = 432000
rpc_url = "https://api.mainnet-beta.solana.com"
[behavior]
# Fork from mainnet genesis
genesis = false
# Fork from specific point
point_fork = true
[accounts]
# Pre-clone specific accounts
clone = [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", # Token Program
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", # ATA Program
]
[programs]
# Auto-deploy local programs
deploy = ["./target/deploy/my_program.so"]
[airdrop]
# Default airdrop recipients
addresses = ["YOUR_PUBKEY"]
amount = 10000000000000 # 10,000 SOL
作弊码
Surfpool 提供特殊 RPC 方法,用于测试期间进行高级状态操作。
账户操作
surfnet_setAccount
设置任意账户数据:
await connection.send("surfnet_setAccount", [
{
pubkey: "AccountPubkey...",
lamports: 1000000000,
data: "base64EncodedData",
owner: "OwnerPubkey...",
executable: false,
},
]);
surfnet_setTokenAccount
创建或修改代币账户:
await connection.send("surfnet_setTokenAccount", [
{
owner: "OwnerPubkey...",
mint: "MintPubkey...",
tokenProgram: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
update: {
amount: "1000000000",
delegate: null,
state: "initialized",
},
},
]);
surfnet_cloneProgramAccount
从 mainnet 克隆程序:
await connection.send("surfnet_cloneProgramAccount", [
{
source: "SourceProgramPubkey...",
destination: "DestinationPubkey...",
},
]);
surfnet_resetAccount
将账户重置为 mainnet 状态:
await connection.send("surfnet_resetAccount", [
{
pubkey: "AccountPubkey...",
includeOwnedAccounts: true,
},
]);
时间控制
surfnet_timeTravel
推进网络时间:
await connection.send("surfnet_timeTravel", [
{
epoch: 100,
slot: 50000,
timestamp: 1700000000,
},
]);
surfnet_pauseClock / surfnet_resumeClock
控制区块生成:
// Pause
await connection.send("surfnet_pauseClock", []);
// Resume
await connection.send("surfnet_resumeClock", []);
surfnet_advanceClock
逐步推进时钟:
await connection.send("surfnet_advanceClock", [
{ slots: 100 },
]);
交易性能分析
surfnet_profileTransaction
分析交易执行情况:
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
按标签获取性能分析结果:
const results = await connection.send("surfnet_getProfileResults", [
{ tag: "my-test-tag" },
]);
网络控制
surfnet_resetNetwork
将整个网络重置为初始状态:
await connection.send("surfnet_resetNetwork", []);
surfnet_getClock
获取当前网络时间:
const clock = await connection.send("surfnet_getClock", []);
console.log("Slot:", clock.slot);
console.log("Epoch:", clock.epoch);
console.log("Timestamp:", clock.timestamp);
Surfpool Studio
访问 http://127.0.0.1:18488 上的 Web 控制面板,使用以下功能:
- 交易检查器 - 查看交易详情和字节级差异
- 账户浏览器 - 探索账户状态和历史记录
- 计算分析器 - 分析每条指令的计算单元用量
- 通用水龙头 - 申请 SOL 和代币
- 网络状态 - 监控插槽、纪元和区块生成情况
基础设施即代码
Surfpool 集成了 txtx DSL,可用于可复现的部署。
Runbook 结构
# 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]
}
运行 Runbook
# Run specific runbook
surfpool start -r deployment
# Run in unsupervised mode
surfpool start -r deployment --unsupervised
场景和固定数据
场景
定义用于测试的账户状态序列:
await connection.send("surfnet_registerScenario", [
{
name: "high-volume-trading",
slots: [
{
slot: 100,
accounts: {
"PoolPubkey...": { lamports: 1000000000000 },
},
},
{
slot: 200,
accounts: {
"PoolPubkey...": { lamports: 500000000000 },
},
},
],
},
]);
固定数据
导出交易固定数据,以便进行可复现的测试:
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));
与 Anchor 集成
Surfpool 会自动检测 Anchor 项目并处理部署:
# In an Anchor project directory
surfpool start
# Programs in target/deploy/ are automatically deployed
使用 Anchor 进行测试
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
});
});
最佳实践
1. 使用 Cheatcodes 进行设置
// Set up test state before each test
beforeEach(async () => {
await connection.send("surfnet_resetNetwork", []);
await connection.send("surfnet_setTokenAccount", [...]);
});
2. 对关键路径进行性能分析
// Tag transactions for profiling
const result = await connection.send("surfnet_profileTransaction", [
{ transaction: tx, tag: "swap-operation" },
]);
expect(result.computeUnits).toBeLessThan(200000);
3. 使用场景测试边界情况
// Test with specific mainnet conditions
await connection.send("surfnet_registerScenario", [
{ name: "low-liquidity", slots: [...] },
]);
4. 为 CI 导出固定数据
// Create reproducible test fixtures
const fixture = await connection.send("surfnet_exportSnapshot", [...]);
资源
官方链接
社区
- Discord:https://discord.gg/surfpool
- Twitter:@surfaboratory
- Telegram:公告频道
教程
技能结构
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 issues
评论
支持 Markdown