跟我一起从0开始学习Solana合约开发,一起实操,一起做项目。这是一个系列文章,系统地记录了我的学习笔记。
本文是对Solana官网文档的翻译。我会根据我的实操对原文修改,并且针对初学者不容易理解的地方做了更多的翻译。
Anchor框架是让构建Solana程序更加容易的一个工具。无论你是初学者,还是有经验的开发者,Anchor都会让你更加容易地编写、测试和部署Solana程序。
本文共四个部分:
提示 我的前两篇文章已经带你安装好了环境,并初步认识了项目目录结构,这一讲会带你理解更多关键细节问题,学完本文,你将会对Anchor项目更有掌控感!
如果你还没有安装环境,请阅读我前面的文章,这里默认你已经安装好了。
要创建一个新的Anchor项目,使用anchor init
命令,后面跟上你的项目名称。如下所示:
# 创建项目
anchor init my-project
# 进人项目目录
cd my-project
这会创建一个默认的Solana程序,位置在/programs/my-project/src/lib.rs
。以下是完整的代码:
use anchor_lang::prelude::*;
declare_id!("3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg");
#[program]
pub mod my_project {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
msg!("Greetings from: {:?}", ctx.program_id);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize {}
你可以先不用理解代码,我下一篇文章会详细讲解。其中,在declare_id!
里面的值是 Program ID,是程序的唯一标识符。
用 EVM 生态的概念作为类比,
智能合约
对应Solana程序
,合约地址
对应Program ID
。
当你执行anchor build
命令,会生成一个密钥对文件(如果不存在),存储在/target/deploy/my_project-keypair.json
,Program ID 就是这个密钥对的公钥。
Anchor 也会自动生成一个测试文件,位置在/tests/my-project.ts
,里面展示了如何使用 Typescript 调用这个程序的 initialize
函数。
如果你更喜欢使用 Rust 编写测试,在初始化项目的时候,加上 --test-template rust
标志就可以生成由 Rust 编写的测试用例。如下所示:
anchor init --test-template rust my-project
这个 Rust 测试文件生成在 /tests/src/test_initialize.rs
。
执行anchor build
命令是构建Solana程序,这将会把程序编译为一个.so文件,位置在/target/deploy/my_project.so
。当你部署程序时,实际上就是把这个文件内容存储在Solana网络上对应的账户里,称为可执行程序
。
解释
这里提到了.so文件
和账户
,你先对这些名词有个印象,我下一篇文章会详细讲解。
执行anchor test
命令是测试Solana程序,默认情况下,根目录下Anchor.toml
配置文件指定了 localnet
集群(也就是 Solana 本地网络)。当你在本地网络上开发,执行 anchor test 会自动发生下面的过程:
启动一个本地 Solana 验证节点
构建和部署你的程序至本地集群
运行tests
文件夹里的测试用例
停止本地 Solana 验证节点
此外,你可以手动启动一个本地 Solana 验证节点,并在这个集群上面运行测试。如果你希望在迭代你的程序时保持验证节点运行,这个非常有用。而且,更方便检查账户和交易日志。
打开新终端,执行下面命令,手动启动一个本地 Solana 验证节点:
solana-test-validator
打开新终端,执行下面命令,查看交易日志:
solana logs
在项目根目录终端,执行下面命令,运行测试:
anchor test --skip-local-validator
因为已经手动启动好了Solana验证节点,使用--skip-local-validator
标志可以中止自动启动本地Solana验证节点。
默认情况下,根目录下Anchor.toml
配置文件指定了本地集群,如下所示:
[provider]
cluster = "Localnet"
wallet = "~/.config/solana/id.json"
为了将你的程序部署至Solana测试网络,修改以上配置,将 Localnet
改为 Devnet
。注意,wallet 对应的钱包需要有足够的 SOL 测试币。这时候无论执行anchor deploy
命令,还是anchor test
命令,都会使用最新的配置,也就是会将你的程序部署至Solana测试网络集群。
如果你要将程序部署至Solana主网集群,同样地,将 cluster
的值修改为 Mainnet
即可。
Solana程序是可以被更新的,即可以对同一个 Program ID 重复部署不同的程序。当你修改了程序代码,运行anchor build
命令生成一个新的.so文件
,再运行anchor deploy
命令重新部署,这将会更新Solana程序。
提示 如果你了解 EVM 生态,可以把这个过程类比为 智能合约的升级。在 EVM 中,升级合约是一件很麻烦的事,而 Solana 天生就支持升级。
在 Solana 中,有一个租金的概念,当你把程序部署至Solana网络集群中,需要支付相应的租金(根据程序大小按比例支付)。然而,这个租金和现实世界的房租不一样,因为,Solana 里的租金可以全额退回。
为了全额退回你支付的租金,你需要使用 solana program close <PROGRAM_ID>
命令关闭你的Solana程序。如下所示:
solana program close 3ynNB373Q3VAzKp7m4x238po36hjAGFXFJB4ybN2iTyg --bypass-warning
当你关闭程序时,Solana 会给出一个警告,可以使用--bypass-warning
选项来跳过这些警告。
注意:一旦程序被关闭,Program ID 将不能再用于部署新的程序。
官网文档对于项目文件结构,介绍的非常简单。你可以看我的上一篇文章,我详细讲解了项目的目录结构,并带着你一步步精简了目录,移除了初学者不必关心的目录和文件。
/programs
文件夹下面存放了所有的程序,在一个工作空间内,可以包含多个程序。 例如:/programs/程序1
, /programs/程序2
, /programs/程序3
等等。
/tests
文件夹包含了你的项目里所有的测试文件,创建项目时会自动创建一个默认的测试文件。
/target
文件夹包含了构建时输出的文件。下面是主要的子文件夹:
/deploy
包含密钥对(公钥就是 Program ID)和你的程序二进制文件(.so文件)
/idl
包含你的程序 JSON IDL。 (IDL 可以类比为 solidity 的 ABI,用于跟程序交互)
/types
包含 IDL 的 TypeScript 类型。(/tests文件夹下的测试文件引用了这个类型与Solana程序交互)
Anchor.toml 文件配置了你项目的工作区设置。
包括一个 program-logs 文件夹,里面包含了上次运行测试文件时的交易日志。
/app
是一个空文件夹,你可以用来存放你的前端代码,这是可选的。
到这里,本文就讲完了。下一篇我们来学习Rust主程序,如果你想提前看到我的更新,可以关注我的公众号:认知那些事
。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!