Solana : 本地构建部署合约及前端调用
我们先用最简单的合约测试, 然后用上一节的例子测试, 可以学习 ts 里面怎么创建 PDA 账户
准备本地开发环境
更新工具
确保本地开发环境为最新版本,运行以下命令升级:
agave-install update
你可能会疑惑:为什么是 agave
而不是 solana
?
其实,Solana Labs 的官方仓库已归档(archive),现在由 Anza 团队(由 Solana Labs 前高管和核心工程师组成)全面接手开发。Anza 的主要产品包括:
- Agave:从 Solana Labs fork 的验证客户端,已被 Solana 主网采用,目标 2025 年实现 1M TPS。
- Kit:Solana JavaScript SDK,相当于
@solana/web3.js
的 2.0 版本。 - Move:支持 Move 语言的改造,目前进展有限。
- Rust/C 工具链:编译相关工具。
而我们使用的 Anchor 框架则由 Backpack 钱包团队开发。
小贴士:原生 Rust 开发据说比 Anchor 更省 gas,但对于初学者来说,Anchor 的快速上手优势更重要。
配置环境
solana config set -ud # 设置为开发网(devnet)
solana-keygen new # 生成默认钱包
solana airdrop 2 # 领取 2 SOL
solana-test-validator # 启动本地节点
- 本地测试:用
localnet
快速验证,配合 Solana Explorer 查看本地交易。 - 开发网(devnet):如需用 devnet,可参考对比各 RPC 性能。
- Ping 测试:可以用
solana ping
检查你与 RPC 的连接速度, 需要付 gas。
创建项目
初始化一个 Anchor 项目:
anchor init demo
cd demo
合约代码 lib.rs 我就不展示了, 就是最简单的 hello world, 大家自己看
查看与修改 Program Account
solana 是部署之前就生成 Program Account 而不是部署完之后给你返回, 跟其他链不太一样
查看项目的 Program Address:
anchor keys list
# 或
solana address -k target/deploy/demo-keypair.json
两条命令结果一致,返回当前项目的 Program ID。
如果需要修改 Program Address:
场景:
- 链上销毁合约 (close) 后重新部署, 不能用老的 key pair
- 在不同 cluster 环境, 希望合约地址不一样
- 生成新密钥对:
solana-keygen new --outfile target/deploy/demo-keypair.json solana address -k target/deploy/demo-keypair.json
- 同步到
lib.rs
:anchor keys sync
注意:若不打算升级程序,可销毁私钥以确保安全。
构建项目
anchor build
构建后,合约二进制文件生成在 target/deploy/demo.so
,后续部署的就是这个文件。
项目结构
├── Anchor.toml # Anchor 配置文件
├── programs # 合约代码目录
│ └── demo # 合约子目录
├── target # 编译输出目录
│ ├── deploy
│ │ └── demo-keypair.json # Program Account 私钥
│ │ └── demo.so # 合约二进制文件
│ ├── idl # IDL 文件, 描述合约
│ └── types # TypeScript 类型, 方便 ts 代码调用合约
├── tests # 测试目录
│ └── demo.ts # 测试文件
└── migrations # 部署脚本
└── deploy.ts
部署合约
配置部署
Anchor.toml
中指定部署网络和钱包:
[provider]
cluster = "devnet"
wallet = "~/.config/solana/id.json"
也可通过命令行指定 RPC:
anchor deploy --provider.cluster https://devnet.solana.rpcpool.com
查看 Program 信息
部署后,查看详情:
solana program show <Program-ID>
测试合约
本地测试
anchor test
- 默认使用
localnet
,自动启动节点、部署合约并运行测试。 - 注意:若已手动启动
solana-test-validator
,会因端口冲突报错。 - 缺点:测试后节点关闭,无法在 Explorer 查看交易,可在
.anchor/program-logs
查看日志。 - 改进:用
--skip-local-validator
配合手动启动的节点:anchor test --skip-local-validator
重新部署
修改代码后:
anchor build
anchor test --skip-local-validator
销毁合约
销毁后 Program ID 无法再次使用,但可回收 SOL, 可以给我们回一回血:
solana program close <Program-ID> --bypass-warning
示例:
solana balance # 500000008.72812742 SOL
solana program close <Program-ID> --bypass-warning # 回收 1.26686616 SOL
solana balance # 500000009.994988561 SOL
注意: 再次部署会报错,必须重新生成 Program ID, 参照上面的步骤。
TypeScript 调用合约
代码结构很简单
导入依赖
定义并创建 RPC 连接
加载钱包
获取 Program
调用指令
测试脚本
在 tests
目录下创建 mytest.ts
:
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { Demo } from "../target/types/demo";
import { Connection, Keypair } from "@solana/web3.js";
import * as fs from "fs";
// 本地节点 RPC
const RPC_URL = "http://127.0.0.1:8899";
const connection = new Connection(RPC_URL, "confirmed");
// 加载钱包
const walletKeypair = Keypair.fromSecretKey(
new Uint8Array(JSON.parse(fs.readFileSync("/Users/yc/.config/solana/id.json", "utf-8")))
);
const wallet = new anchor.Wallet(walletKeypair);
const provider = new anchor.AnchorProvider(connection, wallet, { preflightCommitment: "confirmed" });
anchor.setProvider(provider);
// 获取 Program
const program = anchor.workspace.demo as Program<Demo>;
async function main() {
console.log("Using wallet:", wallet.publicKey.toBase58());
try {
const tx = await program.methods
.initialize()
.accounts({ signer: wallet.publicKey })
.signers([walletKeypair])
.rpc();
console.log("Transaction Signature:", tx);
} catch (error) {
console.error("Transaction failed:", error);
}
}
main();
执行测试
当前项目安装 ts-node
(若未安装):
npm install --save-dev ts-node
运行:
npx ts-node tests/mytest.ts
查看交易详情
explorer 是支持 localnet 的
在本地测试之前 PDA 账户的例子
我在 GitHub 提供代码,我本地的版本为:
anchor-cli 0.31.0
solana-cli 2.1.17
说明: 调用代码中可能遇到编译错误,暂时需用 as any
规避, 这一点坑了大概 2 个小时, 可能是新版的问题:
const txId = await program.methods
.setFavorites(favoriteNumber, favoriteColor)
.accounts({
user: userKeypair.publicKey,
fav: favoritesPda,
systemProgram: SystemProgram.programId,
} as any) // 这里
.signers([userKeypair])
.rpc();
总结
- 本地开发:用
solana-test-validator
和anchor test
快速验证。 - 部署与销毁:灵活管理 Program ID 和 SOL。
- TypeScript 调用:结合 Anchor 和
@solana/web3.js
,轻松与合约交互。
赶快动手试试吧,更多相关信息,请,,https://t.me/gtokentool 。