Solana智能合约可以使用Rust编写,所以要学习使用VS Code开发Solana智能合约,首先你得掌握如何在VS Code上面编写Rust程序。这里同学们可以参考之前的文章:
1.创建工程
在自己的workspace下,用cargo创建一个项目, 进入项目目录,添加Solana SDK依赖
luca@LucadeMacBook-Air rust-workspace % cargo new --lib helloworld
Created library `helloworld` package
luca@LucadeMacBook-Air rust-workspace %
luca@LucadeMacBook-Air rust-workspace % cd helloworld
luca@LucadeMacBook-Air helloworld %
luca@LucadeMacBook-Air helloworld % cargo add solana-program
Updating crates.io index
Adding solana-program v1.18.9 to dependencies.
Updating crates.io index
用VS Code打开项目
2.编写合约代码
在 src/lib.rs文件中,填入如下合约代码:
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,
};
// Declare and export the program's entrypoint
entrypoint!(process_instruction);
// Program entrypoint's implementation
pub fn process_instruction(
_program_id: &Pubkey, // Public key of the account the hello world program was loaded into
_accounts: &[AccountInfo], // The account to say hello to
_instruction_data: &[u8], // Ignored, all helloworld instructions are hellos
) -> ProgramResult {
msg!("Hello World Rust program entrypoint");
Ok(())
}
3.构建项目
在Cargo.toml中添加:
[features]
no-entrypoint = []
[lib]
crate-type = ["cdylib", "lib"]
修改后的Cargo.toml完整配置为
[package]
name = "helloworld"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
solana-program = "1.18.9"
[features]
no-entrypoint = []
[lib]
crate-type = ["cdylib", "lib"]
构建:
luca@LucadeMacBook-Air helloworld % cargo build-sbf
Compiling proc-macro2 v1.0.79
Compiling unicode-ident v1.0.12
Compiling version_check v0.9.4
.........................
Compiling bincode v1.3.3
Compiling helloworld v0.1.0 (/Users/luca/dev/rust-workspace/helloworld)
Finished release [optimized] target(s) in 34.78s
生成deploy文件
但是同学们可能会遇到这个报错:
luca@LucadeMacBook-Air helloworld % cargo-build-sbf
error: package `solana-program v1.18.9` cannot be built because it requires rustc 1.75.0 or newer, while the currently active rustc version is 1.68.0-dev
Either upgrade to rustc 1.75.0 or newer, or use
cargo update -p solana-program@1.18.9 --precise ver
where `ver` is the latest version of `solana-program` supporting rustc 1.68.0-dev
然后你会检查自己的Rust版本,是1.77.1,高于1.75.0。
luca@LucadeMacBook-Air helloworld % rustc -V
rustc 1.77.1 (7cf61ebde 2024-03-27)
这个时候你可能会陷入疑惑。但其实cargo-build-sbf使用的是自带的rustc版本1.68.0,不会使用默认的rust版本
luca@LucadeMacBook-Air helloworld % cargo-build-sbf --version
solana-cargo-build-sbf 1.17.25
platform-tools v1.37
rustc 1.68.0
我们可以考虑升级一下,然后就可以正常构建了
solana-install init 1.18.9
4.发布智能合约
设置testnet
luca@LucadeMacBook-Air helloworld % solana config set --url https://api.testnet.solana.com
Config File: /Users/luca/.config/solana/cli/config.yml
RPC URL: https://api.testnet.solana.com
WebSocket URL: wss://api.testnet.solana.com/ (computed)
Keypair Path: /Users/luca/.config/solana/id.json
Commitment: confirmed
发布合约
solana program deploy /Users/luca/dev/rust-workspace/helloworld/target/deploy/helloworld.so
Program Id: BiEjWMFBfRCup21wQMcC7TxioLQZcnFxBXWKSxZoGV1Q
查看浏览器记录:
https://solscan.io/account/BiEjWMFBfRCup21wQMcC7TxioLQZcnFxBXWKSxZoGV1Q?cluster=devnet
5.Rust客户端测试
Cargo.toml
[package]
name = "helloworld"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
solana-program = "1.18.9"
solana-sdk = "1.18.9"
solana-rpc-client = "1.18.9"
bs58 = "0.5.0"
lib.rs
use std::str::FromStr;
use solana_sdk::signature::Signer;
use solana_rpc_client::rpc_client;
use solana_sdk::signer::keypair;
use solana_sdk::transaction;
use solana_program::instruction;
use solana_program::pubkey;
const RPC_ADDR: &str = "https://api.devnet.solana.com";
fn main() {
let helloworld = pubkey::Pubkey::from_str("BiEjWMFBfRCup21wQMcC7TxioLQZcnFxBXWKSxZoGV1Q").unwrap();
let me = keypair::Keypair::from_base58_string("UtwQ...es0");
println!("me is {}", me.pubkey());
let client = rpc_client::RpcClient::new(RPC_ADDR);
let account_metas = vec![
instruction::AccountMeta::new(me.pubkey(), true),
];
let instruction = instruction::Instruction::new_with_bytes(
helloworld,
"hello".as_bytes(),
account_metas,
);
let ixs = vec![instruction];
let latest_blockhash = client.get_latest_blockhash().unwrap();
let sig = client.send_and_confirm_transaction(&transaction::Transaction::new_signed_with_payer(
&ixs,
Some(&me.pubkey()),
&[&me],
latest_blockhash,
)).unwrap();
println!("tx:{}", sig);
}
运行结果:
me is E3NAyseUZrgwSbYe2g47TuFJr5CxAeneK63mR4Ufbqhh
tx:W9aMuL8LGRwYRx2Xge4jj71i4ggcZVLMJairjn11T77qhZkg81YJ9HkKHW4x3ws5CPrXcTTxUmtveZkSPKyqXCR
查看浏览器:
https://solscan.io/tx/W9aMuL8LGRwYRx2Xge4jj71i4ggcZVLMJairjn11T77qhZkg81YJ9HkKHW4x3ws5CPrXcTTxUmtveZkSPKyqXCR?cluster=devnet