3 个版本

0.0.3 2022年1月27日
0.0.2 2022年1月26日
0.0.1 2022年1月26日

#38 in #on-chain

ISC 许可证

34KB
905

列表程序

列表程序创建Solana账户地址列表。开发者可以使用这些列表来索引与其程序相关的账户数据,而无需依赖于链下索引解决方案。

开始使用

# Cargo.toml

[dependencies]
index-program = { version = "0.0.2" }

主网: HPVqgVHeD9NPrJFSCd2UnpBudMYvorXYkzAqmy5naHTr

开发网: HPVqgVHeD9NPrJFSCd2UnpBudMYvorXYkzAqmy5naHTr

说明

create_list

  • 初始化一个新的List账户。
  • 如果
    • 给定的所有者和命名空间已经存在列表。

delete_list

  • 关闭一个List账户。
  • 将租金返还给所有者。

push_element

  • 初始化一个新的Element账户。
  • 将元素追加到索引的数据结构中。
  • 如果
    • 列表已经达到最大容量。

pop_element

  • 关闭一个Element账户。
  • 从索引的数据结构中删除元素。
  • 将租金返还给所有者。

状态

列表

  • 管理地址列表的元数据。
  • PDA是所有者地址和自定义命名空间地址的哈希。

元素

  • 具有列表中位置的地址值。
  • PDA是列表地址和指针位置的哈希。

示例

以下示例适用于需要创建和管理自己的链上列表的Solana程序。以下示例显示了具有用于代表程序签署指令的单一实例“授权账户”的Anchor程序。

创建列表

以下是一个示例指令create_my_list,用于创建由程序拥有的列表。

// create_my_list.rs

use {
    crate::state::*,
    anchor_lang::{prelude::*, solana_program::system_program},
    std::mem::size_of,
};

#[derive(Accounts)]
#[instruction(bump: u8)]
pub struct CreateMyList<'info> {
    #[account(
        mut,
        seeds = [SEED_AUTHORITY],
        bump = authority.bump,
        owner = crate::ID
    )]
    pub authority: Account<'info, Authority>,

    #[account(mut)]
    pub list: AccountInfo<'info>,

    #[account(address = list_program::ID)]
    pub list_program: Program<'info, list_program::program::ListProgram>,

    #[account(
        init,
        payer = signer,
        space = 8 + size_of<Namespace>()
    )]
    pub namespace: Account<'info, Namespace>

    #[account(mut)]
    pub signer: Signer<'info>,

    #[account(address = system_program::ID)]
    pub system_program: Program<'info, System>,
}

pub fn handler(ctx: Context<CreateMyIndex>, bump: u8) -> ProgramResult {
    // Get accounts.
    let authority = &ctx.accounts.authority;
    let list = &ctx.accounts.list;
    let list_program = &ctx.accounts.list_program;
    let namespace = &ctx.accounts.namespace;
    let signer = &ctx.accounts.signer;
    let system_program = &ctx.accounts.system_program;

    // Create a list owned by the program authority.
    list_program::cpi::create_index(
        CpiContext::new_with_signer(
            list_program.to_account_info(),
            list_program::cpi::accounts::CreateList {
                index: index.to_account_info(),
                namespace: namespace.to_account_info(),
                owner: authority.to_account_info(),
                payer: signer.to_account_info(),
                system_program: system_program.to_account_info(),
            },
            &[&[SEED_AUTHORITY, &[authority.bump]]],
        ),
        bump,
    )
}

推送元素

以下是一个示例指令push_my_element,用于将元素添加到由程序拥有的列表中。

// create_my_pointer.rs

use {
    crate::state::*,
    anchor_lang::{prelude::*, solana_program::system_program},
    std::mem::size_of,
};

#[derive(Accounts)]
#[instruction(reference: Pubkey, bump: u8)]
pub struct CreateMyPointer<'info> {
    #[account(
        mut,
        seeds = [SEED_AUTHORITY],
        bump = authority.bump,
        owner = crate::ID
    )]
    pub authority: Account<'info, Authority>,

    #[account()]
    pub element: AccountInfo<'info>,

    #[account(
      mut,
      constraint = list.owner == authority.key(),
      constraint = list.namespace == namespace.key(),
      owner = list_program.key()
    )]
    pub list: AccountInfo<'info>,

    #[account(address = list_program::ID)]
    pub list_program: Program<'info, list_program::program::IndexProgram>,

    #[account()]
    pub namespace: Account<'info, Namespace>

    #[account(mut)]
    pub signer: Signer<'info>,

    #[account(address = system_program::ID)]
    pub system_program: Program<'info, System>,
}

pub fn handler(
  ctx: Context<CreateMyPointer>,
  reference: Pubkey,
  bump: u8,
) -> ProgramResult {
    // Get accounts.
    let authority = &ctx.accounts.authority;
    let element = &ctx.accounts.element;
    let list = &ctx.accounts.list;
    let list_program = &ctx.accounts.list_program;
    let signer = &ctx.accounts.signer;
    let system_program = &ctx.accounts.system_program;

    // Add the reference address into the list.
    list_program::cpi::push_element(
        CpiContext::new_with_signer(
            list_program.to_account_info(),
            list_program::cpi::accounts::PushElement {
                element: element.to_account_info(),
                list: list.to_account_info(),
                owner: authority.to_account_info(),
                payer: signer.to_account_info(),
                system_program: system_program.to_account_info(),
            },
            &[&[SEED_AUTHORITY, &[authority.bump]]],
        ),
        reference,
        bump,
    )
}

依赖项

~18–27MB
~461K SLoC