Solana PDA从javascript客户端传递



我正在编写一个使用pda存储拍卖位置的索拉纳程序,我有一个关于在调用指令时从客户端传递帐户的问题。我的位置使用一个数字计数器作为种子(因为所有其他属性都不是唯一的),当创建一个新的位置帐户时,这个计数器从另一个(state)帐户中取出,如下所示:

pub fn start_auction(ctx: Context<StartAuction>) -> Result<()> {
let state = &mut ctx.accounts.state;
// ...
state.positions_count = state.positions_count + 1;
Ok(())
}
#[derive(Accounts)]
pub struct StartAuction<'info> {
#[account(init, seeds=[&state.positions_count.to_ne_bytes()], bump, payer = authority, space = 5000)]
pub position: Account<'info, Position>,
#[account(mut, seeds=[b"state"], bump)]
pub state: Account<'info, State>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>
}
#[account]
#[derive(Default)]
pub struct State {
pub positions_count: u32
}

令我惊讶的是,我必须从调用start_auction指令的javascript客户端代码传递position帐户(及其种子)。不清楚为什么—因为程序本身已经知道从哪里获得种子(从state)来初始化帐户。但这不仅仅是关于代码整洁——在客户端,我不知道调用时的当前计数器。当然,我可以获取state并检索计数器,但如果在获取和调用另一个用户调用相同的指令之间,计数器在此期间增加了怎么办?是否有一种方法可以避免从客户端代码传递帐户,如果没有,Solana开发人员将如何处理上述计数器问题?

注:我能想到另一个问题,因为需要从客户那里传递账目。假设我正在创建一个程序,该程序存储一些地址列表,它应该在某些条件下向这些地址发送令牌。需要发送令牌的地址(帐户)由程序的逻辑决定,在客户端无法知道。如何在Solana中实现这些功能?

为了并行化事务,Solana运行时要求在开始时显式声明事务中的所有帐户,因此没有"动态加载";的账户。这包括PDA帐户。

在您的设计中,肯定有可能遇到多个用户试图创建相同帐户的竞争条件,因此您可能需要考虑为您的PDA种子设计不同的设计。

我想您的目标是跟踪给定拍卖的所有帐户。在这种情况下,每个Position都可以被一个用户,甚至是一个随机的u64所控制,并且他们都可以在同一个拍卖中为每个Position存储一些ID号。当你想迭代拍卖的所有帐户时,你可以对所有这些帐户执行getProgramAccounts()以解决它们。

直到有一些其他的Solana运行时允许动态加载帐户或一些MEV客户端允许您确定何时您的交易将着陆,这将是您最好的选择!

最新更新