64 个稳定版本

4.1.2 2024 年 3 月 7 日
4.0.1 2024 年 1 月 31 日
3.3.0 2023 年 12 月 29 日
3.2.3 2023 年 11 月 28 日
1.2.5 2022 年 2 月 24 日

#1453魔法豆

Download history 8817/week @ 2024-04-20 6290/week @ 2024-04-27 7162/week @ 2024-05-04 7798/week @ 2024-05-11 8216/week @ 2024-05-18 7041/week @ 2024-05-25 6821/week @ 2024-06-01 6194/week @ 2024-06-08 7795/week @ 2024-06-15 6546/week @ 2024-06-22 4262/week @ 2024-06-29 3976/week @ 2024-07-06 5753/week @ 2024-07-13 6294/week @ 2024-07-20 7540/week @ 2024-07-27 25474/week @ 2024-08-03

45,734 每月下载量
用于 128 个 crate (91 个直接使用)

自定义许可证

3MB
67K SLoC

Metaplex Token Metadata SDK

Rust 库,用于与 Metaplex Token Metadata 程序交互。

为什么使用客户端库(SDK)?

将程序 crate 作为依赖项有其局限性。最主要的是,您将绑定到该程序的相同依赖项,这些依赖项往往相当多。在许多情况下,这会导致在尝试更新 crate 版本时出现(不必要的)依赖项问题。其次,程序 crate 是从程序源代码生成的,其主要目的是提供程序的功能,而不一定是 友好 的客户端 API。

引入 SDK crate:最少的依赖项,有用的辅助工具。通过自动生成包含所有 accountstypesinstructionserrors 的客户端 SDK,我们可以显著减少依赖项的数量。可以通过添加(手动编写的)辅助工具来改进自动生成的代码。

尽管 SDK crate 有 5 个依赖项,但实际上唯一的“真实”依赖项是 solana-program crate,因为其余依赖项也是 solana-program 的依赖项。

入门

从您的项目文件夹

cargo add mpl-token-metadata

注意 如果您正在使用 solana-program 版本早于 1.16,首先将 solana-program 依赖项添加到您的项目中,然后添加 mpl-token-metadata。这将确保您只有一个 borsh crate 的副本。

结构

客户端 SDK 被分为几个模块

  • accounts:表示程序账户的结构体
  • errors:表示程序错误的枚举
  • instructions:用于创建指令、指令参数和CPI指令的结构体
  • types:表示程序使用的类型的结构体

指令构建器

客户端SDK的主要功能之一是简化指令的创建。自动生成两种“类型”的指令构建器——两者都支持通过名称和可选位置传递账户

客户端指令构建器

这些是为离链客户端代码使用的。每个指令都由相应的结构体表示——例如,CreateV1

pub struct CreateV1 {
    /// Unallocated metadata account with address as pda of ['metadata', program id, mint id]
    pub metadata: solana_program::pubkey::Pubkey,
    /// Unallocated edition account with address as pda of ['metadata', program id, mint, 'edition']
    pub master_edition: Option<solana_program::pubkey::Pubkey>,
    /// Mint of token asset
    pub mint: (solana_program::pubkey::Pubkey, bool),
    /// Mint authority
    pub authority: solana_program::pubkey::Pubkey,
    /// Payer
    pub payer: solana_program::pubkey::Pubkey,
    /// Update authority for the metadata account
    pub update_authority: (solana_program::pubkey::Pubkey, bool),
    /// System program
    pub system_program: solana_program::pubkey::Pubkey,
    /// Instructions sysvar account
    pub sysvar_instructions: solana_program::pubkey::Pubkey,
    /// SPL Token program
    pub spl_token_program: solana_program::pubkey::Pubkey,
}

填写指令账户字段后,您可以使用 instruction(...) 方法生成相应的 solana_program::instruction::Instruction

// instruction args
let args = CreateV1InstructionArgs {
    name: String::from("pNFT"),
    symbol: String::from(""),
    uri: String::from("http://my.pnft"),
    seller_fee_basis_points: 500,
    primary_sale_happened: false,
    is_mutable: true,
    token_standard: TokenStandard::ProgrammableNonFungible,
    collection: None,
    uses: None,
    collection_details: None,
    creators: None,
    rule_set: None,
    decimals: Some(0),
    print_supply: Some(PrintSupply::Zero),
};

// instruction accounts
let create_ix = CreateV1 {
    metadata,
    master_edition: Some(master_edition),
    mint: (mint_pubkey, true),
    authority: payer_pubkey,
    payer: payer_pubkey,
    update_authority: (payer_pubkey, true),
    system_program: system_program::ID,
    sysvar_instructions: solana_program::sysvar::instructions::ID,
    spl_token_program: spl_token::ID,
};

// creates the instruction
let create_ix = create_ix.instruction(args);

或者,您可以使用 CreateV1Builder 创建适当的指令

let create_ix = CreateV1Builder::new()
    .metadata(metadata)
    .master_edition(Some(master_edition))
    .mint(mint_pubkey, true)
    .authority(payer_pubkey)
    .payer(payer_pubkey)
    .update_authority(payer_pubkey, true)
    .is_mutable(true)
    .primary_sale_happened(false)
    .name(String::from("pNFT"))
    .uri(String::from("http://my.pnft"))
    .seller_fee_basis_points(500)
    .token_standard(TokenStandard::ProgrammableNonFungible)
    .print_supply(PrintSupply::Zero)
    .instruction();

CPI 指令构建器

这些是为链上代码使用的构建器,它们将CPI到Token Metadata。与“离链”构建器类似,每个指令都有一个结构体来调用CPI指令——例如,TransferV1Cpi

pub struct TransferV1Cpi<'a> {
    /// The program to invoke.
    pub __program: &'a solana_program::account_info::AccountInfo<'a>,
    /// Token account
    pub token: &'a solana_program::account_info::AccountInfo<'a>,
    /// Token account owner
    pub token_owner: &'a solana_program::account_info::AccountInfo<'a>,
    /// Destination token account
    pub destination_token: &'a solana_program::account_info::AccountInfo<'a>,
    /// Destination token account owner
    pub destination_owner: &'a solana_program::account_info::AccountInfo<'a>,
    /// Mint of token asset
    pub mint: &'a solana_program::account_info::AccountInfo<'a>,
    /// Metadata (pda of ['metadata', program id, mint id])
    pub metadata: &'a solana_program::account_info::AccountInfo<'a>,
    /// Edition of token asset
    pub edition: Option<&'a solana_program::account_info::AccountInfo<'a>>,
    /// Owner token record account
    pub token_record: Option<&'a solana_program::account_info::AccountInfo<'a>>,
    /// Destination token record account
    pub destination_token_record: Option<&'a solana_program::account_info::AccountInfo<'a>>,
    /// Transfer authority (token owner or delegate)
    pub authority: &'a solana_program::account_info::AccountInfo<'a>,
    /// Payer
    pub payer: &'a solana_program::account_info::AccountInfo<'a>,
    /// System Program
    pub system_program: &'a solana_program::account_info::AccountInfo<'a>,
    /// Instructions sysvar account
    pub sysvar_instructions: &'a solana_program::account_info::AccountInfo<'a>,
    /// SPL Token Program
    pub spl_token_program: &'a solana_program::account_info::AccountInfo<'a>,
    /// SPL Associated Token Account program
    pub spl_ata_program: &'a solana_program::account_info::AccountInfo<'a>,
    /// Token Authorization Rules Program
    pub authorization_rules_program: Option<&'a solana_program::account_info::AccountInfo<'a>>,
    /// Token Authorization Rules account
    pub authorization_rules: Option<&'a solana_program::account_info::AccountInfo<'a>>,
    /// The arguments for the instruction.
    pub __args: TransferV1InstructionArgs,
}

填写程序、指令账户和参数字段后,您可以使用 invoke()invoke_signed(...) 方法执行CPI

// instruction args
let mut args = TransferV1InstructionArgs {
    amount,
    authorization_data: None,
};

// instruction accounts
let cpi_transfer = TransferV1Cpi::new(
    metadata_program_info,
    TransferV1CpiAccounts {
        token: owner_token_info,
        token_owner: owner_info,
        destination_token: destination_token_info,
        destination_owner: destination_info,
        mint: mint_info,
        metadata: metadata_info,
        authority: vault_info,
        payer: payer_info,
        system_program: system_program_info,
        sysvar_instructions: sysvar_instructions_info,
        spl_token_program: spl_token_program_info,
        spl_ata_program: spl_ata_program_info,
        edition: edition_info,
        token_record: None,
        destination_token_record: None,
        authorization_rules: None,
        authorization_rules_program: None,
    },
    args,
);

// performs the CPI
cpi_transfer.invoke_signed(&[&signer_seeds])

您还可以使用 TransferV1CpiBuilder 简化流程

let cpi_transfer = TransferV1CpiBuilder::new(metadata_program_info)
    .token(owner_token_info)
    .token_owner(owner_info)
    .destination_token(destination_token_info)
    .destination_owner(destination_info)
    .mint(mint_info)
    .metadata(metadata_info)
    .edition(edition_info)
    .authority(vault_info)
    .payer(payer_info)
    .system_program(system_program_info)
    .sysvar_instructions(sysvar_instructions_info)
    .spl_token_program(spl_token_program_info)
    .spl_ata_program(spl_ata_program_info)
    .amount(amount);

// performs the CPI
cpi_transfer.invoke_signed(&[&signer_seeds])

注意 > *Builder 提供了一种简化创建所需结构体的方法,因为它们利用了在Kinobi配置上设置的任何默认值,并且不需要为可选字段设置 None 值。

PDA助手

账户类型(例如,Metadata)有相关函数来查找PDA或创建PDA Pubkey

impl Metadata {
    pub fn find_pda(mint: Pubkey) -> (solana_program::pubkey::Pubkey, u8) {
        solana_program::pubkey::Pubkey::find_program_address(
            &[
                "metadata".as_bytes(),
                crate::MPL_TOKEN_METADATA_ID.as_ref(),
                mint.as_ref(),
            ],
            &crate::MPL_TOKEN_METADATA_ID,
        )
    }
    pub fn create_pda(
        mint: Pubkey,
        bump: u8,
    ) -> Result<solana_program::pubkey::Pubkey, solana_program::pubkey::PubkeyError> {
        solana_program::pubkey::Pubkey::create_program_address(
            &[
                "metadata".as_bytes(),
                crate::MPL_TOKEN_METADATA_ID.as_ref(),
                mint.as_ref(),
                &[bump],
            ],
            &crate::MPL_TOKEN_METADATA_ID,
        )
    }
}

如果已知bump种子,使用 create_pda 函数更便宜(在计算单位方面),特别是对于链上代码。

测试

要运行SDK测试,请从存储库的根目录运行以下命令

pnpm install

然后

pnpm clients:rust:test

文档

crate文档可以在 这里 找到。

依赖关系

~16–25MB
~423K SLoC