跟我一起从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主程序,如果你想提前看到我的更新,可以关注我的公众号:认知那些事。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!