使用锚点将 Solana 发送到程序帐户中的多个公钥的方法比我当前实现的方法更好吗?

问题描述 投票:0回答:1

这里是新的 Solana Anchor 开发人员,我有一个关于当前如何将 Sol 发送到程序中的多个钱包的问题。 目前我使用下面的代码两次,然后调用两个单独的事务。

system_instruction::transfer(from_account.key, to_account.key, amount);

但是,我注意到 Rust 文档中有一个使用 vec 指令数组的“transfer_many”系统指令。

有人可以向我解释如何使用transfer_many 创建 1 条指令然后调用该指令吗? 该文档对我来说是胡言乱语,所以如果有人能用人性化的语言解释我将不胜感激。

下面是我将 sol 发送到多个地址的完整代码。 请忽略“feeaccount”,因为最终我将更改我的代码以发送程序帐户接受的 sol 的百分比。 (稍后,一旦我了解更多)

use anchor_lang::prelude::*;
use anchor_spl::token::{self, Token, TokenAccount, Transfer as SplTransfer};
use solana_program::system_instruction;

declare_id!("HBj3u9jbTigqXb47TAF2H44TAoTckVJnjzFc4jxusUN2");

#[derive(Accounts)]
pub struct TransferLamports<'info> {
    #[account(mut)]
    pub from: Signer<'info>,
    #[account(mut)]
    pub to: AccountInfo<'info>,
    #[account(mut)]
    pub feeto: AccountInfo<'info>,
    pub system_program: Program<'info, System>,
}

#[program]
pub mod solana_lamport_transfer {
    use super::*;
    pub fn transfer_lamports(ctx: Context<TransferLamports>, amount: u64) -> Result<()> {
        let from_account = &ctx.accounts.from;
        let to_account = &ctx.accounts.to;
        let fee_account = &ctx.accounts.feeto;

        // Create the transfer instruction
        let transfer_instruction1 =
            system_instruction::transfer(from_account.key, to_account.key, amount);
        // Create the transfer instruction
        let transfer_instruction2 =
            system_instruction::transfer(from_account.key, fee_account.key, amount);

        // Invoke the transfer instruction
        anchor_lang::solana_program::program::invoke_signed(
            &transfer_instruction1,
            &[
                from_account.to_account_info(),
                to_account.clone(),
                ctx.accounts.system_program.to_account_info(),
            ],
            &[],
        )?;

        // Invoke the transfer instruction
        anchor_lang::solana_program::program::invoke_signed(
            &transfer_instruction2,
            &[
                from_account.to_account_info(),
                fee_account.clone(),
                ctx.accounts.system_program.to_account_info(),
            ],
            &[],
        )?;

        Ok(())
    }
}

我的代码按照我编写的方式工作,但是,我在使用“transfer_many”片段时迷失了方向。 我写的代码没问题吗? 或者我会遇到问题吗? 我注意到我没有支付两次交易费用,因为它是在同一个调用中,所以也许我不需要使用transfer_many?

rust anchor solana
1个回答
0
投票

TLDR;你的代码没问题。

通过链上程序传输 Sol 需要对系统程序进行“跨程序调用”。这个本机程序有一组已定义的可能的指令,您可以向它提供这些指令,这些指令在此处的文档中定义为枚举。我们首先注意到的是,在 13 条可能的指令中,只有 2 条提到了转移:SystemInstruction::Transfer

SystemInstruction::TransferWithSeed
。没有可用的
TransferMany
说明。
当我们深入研究 

solana_program::system_instruction::transfer_many()

函数时,我们发现它返回一个

Vec<Instruction>
,而
transfer()
函数仅返回一个
Instruction
。如果你能在源代码中找到
它的定义
,你可以看到以下内容: pub fn transfer_many(from_pubkey: &Pubkey, to_lamports: &[(Pubkey, u64)]) -> Vec<Instruction> { to_lamports .iter() .map(|(to_pubkey, lamports)| transfer(from_pubkey, to_pubkey, *lamports)) .collect() }

这个功能其实作用很少。 
from_pubkey

to_pubkey
lamports
作为参数(例如
transfer()
函数),
transfer_many()
采用一个
from_pubkey
和元组切片,每个元组包含一个
to_pubkey
lamports
组合。对于每个元组,它调用常规
transfer()
方法来构造
Instruction
,然后将它们全部返回(作为
Vec
Instruction
)。
现在,当您创建链上程序时,

transfer_many()

几乎没有什么价值,因为跨程序调用只允许您指定一条指令。这与创建客户端程序(例如与 Solana 交互的链下软件)时不同,其中指令被捆绑到交易中。在这种情况下,使用

transfer_many()
是有意义的,因为您可以将一组指令捆绑到一个事务中。
过去,

solana-sdk

(用于客户端或链下开发)和

solana_program
组合了板条箱,因此这就是为什么您会看到一些“遗留”功能,这些功能在创建链上时毫无意义程序,但在构建某些客户端应用程序时非常合乎逻辑。
上述文档中的示例实际上说明了这一点。 

客户端示例

使用transfer_many()构造多个传输指令,并直接将生成的

Vec<Instruction>
放入新的
Transaction
中。同一页上的
程序示例
在链上开发的背景下解释这个概念的效果很差,但最关键的是最后的 for 循环: for instr in instrs { invoke_signed(&instr, accounts, &[&[b"bank", &[bank_pda_bump_seed]]])?; }

它实际上为 
invoke_signed

中的每个

Instruction
分别调用
transfer_many()
希望这能为您澄清一些点滴!

© www.soinside.com 2019 - 2024. All rights reserved.