Anchor
Token2022 di Anchor

Token2022 di Anchor

Ekstensi Memo Transfer

Ekstensi MemoTranfer adalah ekstensi akun Token yang mewajibkan semua transfer masuk ke akun token menyertakan memo, memfasilitasi pelacakan transaksi yang lebih baik dan identifikasi pengguna.

Initializing the Token Account

Karena Anchor tidak memiliki makro untuk ekstensi memo_transfer, kita akan membuat akun Token menggunakan CPI mentah.

Berikut cara membuat token dengan ekstensi Memo Transfer:

rust
use anchor_lang::prelude::*;
use anchor_lang::system_program::{create_account, CreateAccount};
use anchor_spl::{
    token_2022::{
        initialize_account3,
        spl_token_2022::{extension::ExtensionType, pod::PodAccount},
        InitializeAccount3,
    },
    token_interface::{memo_transfer_initialize, MemoTransfer, Mint, Token2022},
};
 
// There is currently not an anchor constraint to automatically initialize the MemoTransfer extension
// We can manually create and initialize the token account via CPIs in the instruction handler
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
    // Calculate space required for token and extension data
    let token_account_size =
        ExtensionType::try_calculate_account_len::<PodAccount>(&[ExtensionType::MemoTransfer])?;
 
    // Calculate minimum lamports required for size of token account with extensions
    let lamports = (Rent::get()?).minimum_balance(token_account_size);
 
    // Invoke System Program to create new account with space for token account and extension data
    create_account(
        CpiContext::new(
            ctx.accounts.system_program.to_account_info(),
            CreateAccount {
                from: ctx.accounts.payer.to_account_info(),
                to: ctx.accounts.token_account.to_account_info(),
            },
        ),
        lamports,                          // Lamports
        token_account_size as u64,         // Space
        &ctx.accounts.token_program.key(), // Owner Program
    )?;
 
    // Initialize the standard token account data
    initialize_account3(CpiContext::new(
        ctx.accounts.token_program.to_account_info(),
        InitializeAccount3 {
            account: ctx.accounts.token_account.to_account_info(),
            mint: ctx.accounts.mint_account.to_account_info(),
            authority: ctx.accounts.payer.to_account_info(),
        },
    ))?;
 
    // Initialize the memo transfer extension
    // This instruction must come after the token account initialization
    memo_transfer_initialize(CpiContext::new(
        ctx.accounts.token_program.to_account_info(),
        MemoTransfer {
            token_program_id: ctx.accounts.token_program.to_account_info(),
            account: ctx.accounts.token_account.to_account_info(),
            owner: ctx.accounts.payer.to_account_info(),
        },
    ))?;
 
    Ok(())
}
 
#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(mut)]
    pub payer: Signer<'info>,
 
    #[account(mut)]
    pub token_account: Signer<'info>,
    pub mint_account: InterfaceAccount<'info, Mint>,
    pub token_program: Program<'info, Token2022>,
    pub system_program: Program<'info, System>,
}

Transferring Token with a Memo

Untuk menggunakan program Memo di Solana, kita memiliki dua jalur yang memungkinkan.

Membangun instruksi memo "mentah" kita sendiri seperti ini:

ts
const message = "Hello, Solana";
 
new TransactionInstruction({
    keys: [{ pubkey: keypair.publicKey, isSigner: true, isWritable: true }],
    data: Buffer.from(message, "utf-8"), // Memo message. In this case it is "Hello, Solana"
    programId: new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"), // Memo program that validates keys and memo message
}),

Atau kita dapat menggunakan SDK program Memo setelah mengunduh paketnya seperti ini:

 
npm i @solana/spl-memo

Setelah membuat memo, instruksi berikutnya akan menjadi instruksi transfer sederhana.

Dalam contoh kita, kita akan menggunakan opsi kedua dan akan terlihat seperti ini:

ts
const memoInstruction = createMemoInstruction(
    "Hello, world!",
    [keypair.publicKey],
);
 
//...anchor instruction with the transfer instruction
 
const transferTransaction = new Transaction().add(
    memoInstruction,
    transferInstruction,
);
 
const transferSignature = await sendAndConfirmTransaction(connection, transferTransaction, [keypair]);
 
console.log(`Tokens transferred with memo! Check out your TX here: https://explorer.solana.com/tx/${transferSignature}?cluster=devnet`);

Disabling and Enabling the Memo

Jika kita tidak ingin mewajibkan transfer disertai dengan memo, kita dapat melakukannya menggunakan fungsi memo_transfer_disable dan akan terlihat seperti ini:

rust
use anchor_lang::prelude::*;
use anchor_spl::token_interface::{memo_transfer_disable, MemoTransfer, Token, Mint, Token2022};
 
#[derive(Accounts)]
pub struct DisableMemo<'info> {
    #[account(mut)]
    pub owner: Signer<'info>,
 
    #[account(
        mut,
        token::authority = owner,
    )]
    pub token_account: InterfaceAccount<'info, TokenAccount>,
    pub token_program: Program<'info, Token2022>,
}
 
pub fn disable_memo(
    ctx: Context<DisableMemo>,
) -> Result<()> {
    memo_transfer_disable(CpiContext::new(
        ctx.accounts.token_program.to_account_info(),
        MemoTransfer {
            token_program_id: ctx.accounts.token_program.to_account_info(),
            account: ctx.accounts.token_account.to_account_info(),
            owner: ctx.accounts.owner.to_account_info(),
        },
    ))?;
    
    Ok(())
}
Daftar Isi
Lihat Sumber
Blueshift © 2025Commit: 96f50c6