如何使用Rust SDK在Aptos上执行指定Move脚本?
使用Aptos Rust SDK执行Move脚本
需求背景
你有一个位于sources/top_up.move的Move脚本,功能为检查目标账户的Aptos币余额,若余额低于指定的desired_balance,则从源账户转账补足差额。脚本内容如下:
script { use std::signer; use aptos_framework::aptos_account; use aptos_framework::aptos_coin; use aptos_framework::coin; fun main(src: &signer, dest: address, desired_balance: u64) { let src_addr = signer::address_of(src); let balance = coin::balance<aptos_coin::AptosCoin>(src_addr); if (balance < desired_balance) { aptos_account::transfer(src, dest, desired_balance - balance); }; } }
目前你已能通过CLI执行该脚本,命令如下:
# 先编译再执行 aptos move compile aptos move run-script --compiled-script-path build/MyModule/bytecode_scripts/main.mv # 直接执行源码脚本 aptos move run-script --script-path sources/top_up.move
你希望了解是否可以通过Aptos Rust SDK完成相同操作,答案是肯定的,以下是具体实现方案:
实现步骤
1. 添加依赖
在你的Rust项目的Cargo.toml中添加Aptos SDK依赖:
[dependencies] aptos = { version = "~1.0", features = ["full"] } tokio = { version = "1.0", features = ["full"] } anyhow = "1.0"
2. 执行脚本的Rust代码实现
你可以选择直接加载脚本源码让SDK编译,或者使用预编译好的字节码,两种方式的实现如下:
方式一:加载脚本源码执行
use aptos::{ crypto::ed25519::Ed25519PrivateKey, rest_client::Client, signer::local::LocalSigner, transaction_builder::TransactionBuilder, types::{account_address::AccountAddress, transaction::TransactionPayload}, }; use std::fs; #[tokio::main] async fn main() -> anyhow::Result<()> { // 初始化Aptos客户端(测试网地址,主网替换为https://fullnode.mainnet.aptoslabs.com/v1) let client = Client::new("https://fullnode.testnet.aptoslabs.com/v1"); // 加载源账户的私钥和地址(建议从环境变量/配置文件读取,不要硬编码) let private_key = Ed25519PrivateKey::from_hex("你的源账户私钥")?; let src_address = AccountAddress::from_hex("你的源账户地址")?; let signer = LocalSigner::from_private_key(src_address, private_key); // 读取Move脚本源码 let script_source = fs::read_to_string("sources/top_up.move")?; // 定义脚本参数:目标账户地址、期望余额(单位为Octa,1 Aptos = 1e8 Octa) let dest_address = AccountAddress::from_hex("目标账户地址")?; let desired_balance = 100_000_000; // 等价于100 Aptos // 编译脚本并构建交易Payload let payload = TransactionPayload::Script( aptos::transaction_builder::compile_script(&script_source, vec![], vec![ dest_address.into(), desired_balance.into(), ])?, ); // 获取源账户当前序列号,构建交易 let sequence_number = client.get_account(signer.address()).await?.into_inner().sequence_number; let transaction = TransactionBuilder::new(payload) .sequence_number(sequence_number) .max_gas_amount(100_000) .gas_unit_price(100) .expiration_timestamp_secs(std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_secs() + 300) .build(); // 签名并提交交易 let signed_tx = signer.sign_transaction(&transaction)?; let response = client.submit_transaction(&signed_tx).await?; println!("交易提交成功,哈希: {}", response.into_inner().hash); Ok(()) }
方式二:加载预编译字节码执行
如果你已经通过CLI编译好了脚本字节码,可以直接加载字节码文件执行,替换上述代码中的脚本加载和Payload构建部分:
// 替换方式一中的脚本读取和Payload构建代码 let script_bytecode = fs::read("build/MyModule/bytecode_scripts/main.mv")?; let payload = TransactionPayload::Script( aptos::types::script::Script::new( script_bytecode, vec![], // 脚本无泛型类型参数,传入空向量 vec![ dest_address.into(), desired_balance.into(), ], ), );
注意事项
- 私钥安全:绝对不要在代码中硬编码私钥,建议通过环境变量、加密配置文件等方式加载。
- 网络适配:根据你使用的网络(测试网/主网/本地节点)替换客户端URL。
- Gas参数调整:
max_gas_amount和gas_unit_price需要根据当前网络拥堵情况调整,避免交易失败。 - 版本兼容性:确保Aptos SDK版本与你使用的CLI版本大致匹配,避免因版本差异导致的编译或执行错误。
内容的提问来源于stack exchange,提问作者Daniel Porteous
相关产品推荐
相关产品推荐

