Group Extension và Group Member Extension là gì?
Một nhóm là một mint đại diện cho một bộ sưu tập. Một thành viên nhóm là một mint thuộc về bộ sưu tập đó.
Sử dụng các extension này khi một mint nên đại diện cho bộ sưu tập và các mint khác nên đại diện cho các mục thuộc về nó.
Token Extensions Program có thể lưu trữ dữ liệu nhóm token trực tiếp trên một mint với bốn extension liên quan:
GroupPointertrỏ một mint tới tài khoản lưu trữ dữ liệu của nhóm.TokenGrouplưu trữ chính dữ liệu nhóm, bao gồm quyền cập nhật, kích thước hiện tại và kích thước tối đa.GroupMemberPointertrỏ một mint tới tài khoản lưu trữ dữ liệu của thành viên.TokenGroupMemberlưu trữ địa chỉ nhóm của thành viên và số thành viên.
GroupPointer và GroupMemberPointer có thể tham chiếu đến bất kỳ tài
khoản nào thuộc sở hữu của một chương trình triển khai
giao diện Token group.
Token Extensions Program cũng triển khai giao diện đó trực tiếp thông qua các
mint extension TokenGroup và TokenGroupMember.
Cách Tạo Nhóm và Thành Viên Được Lưu Trữ Trên Tài Khoản Mint
Để tạo nhóm và thành viên được lưu trữ trên tài khoản mint:
- Tạo một tài khoản mint nhóm và khởi tạo
GroupPointer. - Khởi tạo mint nhóm với
InitializeMint. - Khởi tạo
TokenGrouptrên cùng mint đó. - Tạo một tài khoản mint thành viên và khởi tạo
GroupMemberPointer. - Khởi tạo mint thành viên với
InitializeMint. - Khởi tạo
TokenGroupMembertrên cùng mint đó để nó tham chiếu đến mint nhóm.
Tính toán kích thước và tiền thuê cho group mint
Tính toán kích thước và tiền thuê cần thiết cho group mint.
Tạo và Khởi tạo Group Mint
Tạo tài khoản group mint, khởi tạo GroupPointer, khởi tạo mint, và khởi
tạo TokenGroup trong một giao dịch duy nhất.
Tính toán kích thước và tiền thuê cho member mint
Tính toán kích thước và tiền thuê cần thiết cho member mint.
Tạo và Khởi tạo Member Mint
Tạo tài khoản member mint, khởi tạo GroupMemberPointer, khởi tạo mint, và
khởi tạo TokenGroupMember trong một giao dịch duy nhất.
Con trỏ và Thứ tự Lệnh
GroupPointer và GroupMemberPointer lưu trữ địa chỉ tài khoản
nơi dữ liệu group hoặc member được lưu trữ. TokenGroup và
TokenGroupMember lưu trữ dữ liệu thực tế của group hoặc member.
GroupPointerInstruction::Initialize và
GroupMemberPointerInstruction::Initialize phải được thực hiện trước
InitializeMint. TokenGroupInstruction::InitializeGroup và
TokenGroupInstruction::InitializeMember phải được thực hiện sau
InitializeMint. Đối với mỗi mint, CreateAccount, lệnh khởi tạo con
trỏ, và InitializeMint phải được bao gồm trong cùng một giao dịch.
Tham chiếu Nguồn
GroupPointer và GroupMemberPointer là các lệnh con trỏ trong Token
Extensions Program. TokenGroup và TokenGroupMember tuân theo giao
diện Token group, được Token Extensions Program triển khai.
Group Pointer và Group Member Pointer
| Mục | Mô tả | Nguồn |
|---|---|---|
GroupPointer | Phần mở rộng mint lưu trữ quyền hạn và địa chỉ cho tài khoản chứa dữ liệu của một group. | Nguồn |
GroupMemberPointer | Phần mở rộng mint lưu trữ quyền hạn và địa chỉ cho tài khoản chứa dữ liệu của một member. | Nguồn |
GroupPointerInstruction::Initialize | Khởi tạo phần mở rộng group pointer trước InitializeMint. | Nguồn |
GroupPointerInstruction::Update | Cập nhật địa chỉ group được lưu trữ bởi phần mở rộng GroupPointer của mint. | Nguồn |
GroupMemberPointerInstruction::Initialize | Khởi tạo phần mở rộng group member pointer trước InitializeMint. | Nguồn |
GroupMemberPointerInstruction::Update | Cập nhật địa chỉ member được lưu trữ bởi phần mở rộng GroupMemberPointer của mint. | Nguồn |
process_initialize (GroupPointer) | Ghi quyền hạn GroupPointer ban đầu và địa chỉ group lên mint. | Nguồn |
process_update (GroupPointer) | Xác thực quyền hạn group pointer, sau đó ghi lại địa chỉ group được lưu trữ trên mint. | Nguồn |
process_initialize (GroupMemberPointer) | Ghi quyền hạn GroupMemberPointer ban đầu và địa chỉ member lên mint. | Nguồn |
process_update (GroupMemberPointer) | Xác thực quyền hạn group member pointer, sau đó ghi lại địa chỉ member được lưu trữ trên mint. | Nguồn |
Nhóm Token và Thành viên Nhóm Token
| Mục | Mô tả | Nguồn |
|---|---|---|
TokenGroup | Trạng thái giao diện nhóm token được lưu trữ trên mint, bao gồm quyền cập nhật, kích thước hiện tại và kích thước tối đa. | Nguồn |
TokenGroupMember | Trạng thái giao diện thành viên nhóm token được lưu trữ trên mint, bao gồm mint thành viên, địa chỉ nhóm và số thứ tự thành viên. | Nguồn |
TokenGroupInstruction::InitializeGroup | Lệnh giao diện nhóm token được Token Extensions Program hỗ trợ để khởi tạo một nhóm mới cho mint đã được khởi tạo. | Nguồn |
TokenGroupInstruction::UpdateGroupMaxSize | Lệnh giao diện nhóm token được Token Extensions Program hỗ trợ để cập nhật số lượng thành viên tối đa được phép trong một nhóm. | Nguồn |
TokenGroupInstruction::UpdateGroupAuthority | Lệnh giao diện nhóm token được Token Extensions Program hỗ trợ để luân chuyển hoặc xóa quyền cập nhật của nhóm. | Nguồn |
TokenGroupInstruction::InitializeMember | Lệnh giao diện nhóm token được Token Extensions Program hỗ trợ để khởi tạo thành viên mới cho nhóm đã được khởi tạo. | Nguồn |
process_initialize_group | Xác thực mint, kiểm tra GroupPointer có tồn tại hay không và phân bổ trạng thái TokenGroup trên mint nhóm. | Nguồn |
process_update_group_max_size | Xác thực quyền cập nhật hiện tại, sau đó cập nhật kích thước tối đa của nhóm. | Nguồn |
process_update_group_authority | Xác thực quyền cập nhật hiện tại, sau đó luân chuyển hoặc xóa quyền cập nhật của nhóm. | Nguồn |
process_initialize_member | Xác thực mint thành viên và quyền nhóm, tăng kích thước nhóm và phân bổ trạng thái TokenGroupMember trên mint. | Nguồn |
Typescript
Ví dụ bên dưới sử dụng trực tiếp các hướng dẫn được tạo bởi Kit. Các ví dụ cũ
sử dụng @solana/web3.js, @solana/spl-token và các hàm trợ giúp nhóm token
được bao gồm để tham khảo.
Kit
import {lamports,createClient,generateKeyPairSigner,unwrapOption} from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getCreateAccountInstruction } from "@solana-program/system";import {extension,fetchMint,getInitializeGroupMemberPointerInstruction,getInitializeGroupPointerInstruction,getInitializeMintInstruction,getInitializeTokenGroupInstruction,getInitializeTokenGroupMemberInstruction,getMintSize,isExtension,TOKEN_2022_PROGRAM_ADDRESS} from "@solana-program/token-2022";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const groupMint = await generateKeyPairSigner();const memberMint = await generateKeyPairSigner();const groupPointerExtension = extension("GroupPointer", {authority: client.payer.address,groupAddress: groupMint.address});const groupExtension = extension("TokenGroup", {updateAuthority: client.payer.address,mint: groupMint.address,size: 0n,maxSize: 10n});const groupMintSpace = BigInt(getMintSize([groupPointerExtension, groupExtension]));const groupMintCreateSpace = BigInt(getMintSize([groupPointerExtension]));const groupMintRent = await client.rpc.getMinimumBalanceForRentExemption(groupMintSpace).send();await client.sendTransaction([getCreateAccountInstruction({payer: client.payer, // Account funding the new mint account.newAccount: groupMint, // New group mint account to create.lamports: groupMintRent, // Lamports funding the mint account rent.space: groupMintCreateSpace, // Account size in bytes for the mint plus GroupPointer.programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.}),getInitializeGroupPointerInstruction({mint: groupMint.address, // Mint account that stores the GroupPointer extension.authority: client.payer.address, // Authority allowed to update the group pointer later.groupAddress: groupMint.address // Account address that stores the group data.}),getInitializeMintInstruction({mint: groupMint.address, // Mint account to initialize.decimals: 0, // Number of decimals for the token.mintAuthority: client.payer.address, // Authority allowed to mint new tokens.freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.}),getInitializeTokenGroupInstruction({group: groupMint.address, // Mint account that stores the group data.mint: groupMint.address, // Mint that the group data describes.mintAuthority: client.payer, // Signer authorizing group initialization for the mint.updateAuthority: client.payer.address, // Authority allowed to update the group later.maxSize: 10n // Maximum number of members allowed in the group.})]);const memberPointerExtension = extension("GroupMemberPointer", {authority: client.payer.address,memberAddress: memberMint.address});const memberExtension = extension("TokenGroupMember", {mint: memberMint.address,group: groupMint.address,memberNumber: 1n});const memberMintSpace = BigInt(getMintSize([memberPointerExtension, memberExtension]));const memberMintCreateSpace = BigInt(getMintSize([memberPointerExtension]));const memberMintRent = await client.rpc.getMinimumBalanceForRentExemption(memberMintSpace).send();await client.sendTransaction([getCreateAccountInstruction({payer: client.payer, // Account funding the new mint account.newAccount: memberMint, // New member mint account to create.lamports: memberMintRent, // Lamports funding the mint account rent.space: memberMintCreateSpace, // Account size in bytes for the mint plus GroupMemberPointer.programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.}),getInitializeGroupMemberPointerInstruction({mint: memberMint.address, // Mint account that stores the GroupMemberPointer extension.authority: client.payer.address, // Authority allowed to update the member pointer later.memberAddress: memberMint.address // Account address that stores the member data.}),getInitializeMintInstruction({mint: memberMint.address, // Mint account to initialize.decimals: 0, // Number of decimals for the token.mintAuthority: client.payer.address, // Authority allowed to mint new tokens.freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.}),getInitializeTokenGroupMemberInstruction({member: memberMint.address, // Mint account that stores the member data.memberMint: memberMint.address, // Mint that the member data describes.memberMintAuthority: client.payer, // Signer authorizing member initialization for the mint.group: groupMint.address, // Group mint that this member belongs to.groupUpdateAuthority: client.payer // Signer matching the group's update authority.})]);const groupMintAccount = await fetchMint(client.rpc, groupMint.address);const memberMintAccount = await fetchMint(client.rpc, memberMint.address);const groupExtensions = unwrapOption(groupMintAccount.data.extensions) ?? [];const memberExtensions = unwrapOption(memberMintAccount.data.extensions) ?? [];console.log(JSON.stringify({groupMint: groupMint.address,groupPointer: groupExtensions.find((item) =>isExtension("GroupPointer", item)),group: groupExtensions.find((item) => isExtension("TokenGroup", item)),memberMint: memberMint.address,memberPointer: memberExtensions.find((item) =>isExtension("GroupMemberPointer", item)),member: memberExtensions.find((item) =>isExtension("TokenGroupMember", item))},(_, value) => (typeof value === "bigint" ? value.toString() : value),2));
Web3.js
import {Connection,Keypair,Transaction,SystemProgram,LAMPORTS_PER_SOL,sendAndConfirmTransaction} from "@solana/web3.js";import {TOKEN_2022_PROGRAM_ID,ExtensionType,getMintLen,getMint,createInitializeMintInstruction,createInitializeGroupPointerInstruction,createInitializeGroupInstruction,createInitializeGroupMemberPointerInstruction,createInitializeMemberInstruction,getGroupPointerState,getGroupMemberPointerState,getTokenGroupState,getTokenGroupMemberState} from "@solana/spl-token";const connection = new Connection("http://localhost:8899", "confirmed");const authority = Keypair.generate();const airdropSignature = await connection.requestAirdrop(authority.publicKey,5 * LAMPORTS_PER_SOL);await connection.confirmTransaction(airdropSignature, "confirmed");const groupMint = Keypair.generate();const groupPointerExtensions = [ExtensionType.GroupPointer];const spaceWithGroupPointerExtensions = getMintLen(groupPointerExtensions);const groupAndGroupPointerExtensions = [ExtensionType.GroupPointer,ExtensionType.TokenGroup];const spaceWithGroupAndGroupPointerExtensions = getMintLen(groupAndGroupPointerExtensions);const groupMintRent = await connection.getMinimumBalanceForRentExemption(spaceWithGroupAndGroupPointerExtensions);const { blockhash: latestBlockhash } = await connection.getLatestBlockhash();const createGroupMintAccountInstruction = SystemProgram.createAccount({fromPubkey: authority.publicKey, // Account funding the new mint account.newAccountPubkey: groupMint.publicKey, // New group mint account to create.lamports: groupMintRent, // Lamports funding the mint account rent.space: spaceWithGroupPointerExtensions, // Account size in bytes for the mint plus GroupPointer.programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.});const initializeGroupPointerInstruction =createInitializeGroupPointerInstruction(groupMint.publicKey, // Mint account that stores the GroupPointer extension.authority.publicKey, // Authority allowed to update the group pointer later.groupMint.publicKey, // Account address that stores the group data.TOKEN_2022_PROGRAM_ID // Program that owns the mint account.);const initializeGroupMintInstruction = createInitializeMintInstruction(groupMint.publicKey, // Mint account to initialize.0, // Number of decimals for the token.authority.publicKey, // Authority allowed to mint new tokens.authority.publicKey, // Authority allowed to freeze token accounts.TOKEN_2022_PROGRAM_ID // Program that owns the mint account.);const initializeGroupInstruction = createInitializeGroupInstruction({programId: TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.group: groupMint.publicKey, // Mint account that stores the group data.mint: groupMint.publicKey, // Mint that the group data describes.mintAuthority: authority.publicKey, // Signer authorizing group initialization for the mint.updateAuthority: authority.publicKey, // Authority allowed to update the group later.maxSize: 10n // Maximum number of members allowed in the group.});const groupTransaction = new Transaction({feePayer: authority.publicKey,recentBlockhash: latestBlockhash}).add(createGroupMintAccountInstruction,initializeGroupPointerInstruction,initializeGroupMintInstruction,initializeGroupInstruction);await sendAndConfirmTransaction(connection,groupTransaction,[authority, groupMint],{commitment: "confirmed",skipPreflight: true});const memberMint = Keypair.generate();const memberPointerExtensions = [ExtensionType.GroupMemberPointer];const spaceWithMemberPointerExtension = getMintLen(memberPointerExtensions);const memberAndMemberPointerExtensions = [ExtensionType.GroupMemberPointer,ExtensionType.TokenGroupMember];const spaceWithMemberAndMemberPointerExtensions = getMintLen(memberAndMemberPointerExtensions);const memberMintRent = await connection.getMinimumBalanceForRentExemption(spaceWithMemberAndMemberPointerExtensions);const { blockhash: memberLatestBlockhash } =await connection.getLatestBlockhash();const createMemberMintAccountInstruction = SystemProgram.createAccount({fromPubkey: authority.publicKey, // Account funding the new mint account.newAccountPubkey: memberMint.publicKey, // New member mint account to create.lamports: memberMintRent, // Lamports funding the mint account rent.space: spaceWithMemberPointerExtension, // Account size in bytes for the mint plus GroupMemberPointer.programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.});const initializeMemberPointerInstruction =createInitializeGroupMemberPointerInstruction(memberMint.publicKey, // Mint account that stores the GroupMemberPointer extension.authority.publicKey, // Authority allowed to update the member pointer later.memberMint.publicKey, // Account address that stores the member data.TOKEN_2022_PROGRAM_ID // Program that owns the mint account.);const initializeMemberMintInstruction = createInitializeMintInstruction(memberMint.publicKey, // Mint account to initialize.0, // Number of decimals for the token.authority.publicKey, // Authority allowed to mint new tokens.authority.publicKey, // Authority allowed to freeze token accounts.TOKEN_2022_PROGRAM_ID // Program that owns the mint account.);const initializeMemberInstruction = createInitializeMemberInstruction({programId: TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.member: memberMint.publicKey, // Mint account that stores the member data.memberMint: memberMint.publicKey, // Mint that the member data describes.memberMintAuthority: authority.publicKey, // Signer authorizing member initialization for the mint.group: groupMint.publicKey, // Group mint that this member belongs to.groupUpdateAuthority: authority.publicKey // Signer matching the group's update authority.});const memberTransaction = new Transaction({feePayer: authority.publicKey,recentBlockhash: memberLatestBlockhash}).add(createMemberMintAccountInstruction,initializeMemberPointerInstruction,initializeMemberMintInstruction,initializeMemberInstruction);await sendAndConfirmTransaction(connection,memberTransaction,[authority, memberMint],{commitment: "confirmed",skipPreflight: true});const groupMintAccount = await getMint(connection,groupMint.publicKey,"confirmed",TOKEN_2022_PROGRAM_ID);const memberMintAccount = await getMint(connection,memberMint.publicKey,"confirmed",TOKEN_2022_PROGRAM_ID);console.log(JSON.stringify({groupMint: groupMint.publicKey,groupPointer: getGroupPointerState(groupMintAccount),group: getTokenGroupState(groupMintAccount),memberMint: memberMint.publicKey,memberPointer: getGroupMemberPointerState(memberMintAccount),member: getTokenGroupMemberState(memberMintAccount)},(_, value) => (typeof value === "bigint" ? value.toString() : value),2));
Rust
use anyhow::Result;use solana_client::nonblocking::rpc_client::RpcClient;use solana_commitment_config::CommitmentConfig;use solana_sdk::{signature::{Keypair, Signer},transaction::Transaction,};use solana_system_interface::instruction::create_account;use spl_token_2022_interface::{extension::{group_member_pointer::{instruction::initialize as initialize_group_member_pointer, GroupMemberPointer,},group_pointer::{instruction::initialize as initialize_group_pointer, GroupPointer},BaseStateWithExtensions, ExtensionType, StateWithExtensions,},instruction::initialize_mint,state::Mint,ID as TOKEN_2022_PROGRAM_ID,};use spl_token_group_interface::{instruction::{initialize_group, initialize_member},state::{TokenGroup, TokenGroupMember},};#[tokio::main]async fn main() -> Result<()> {let client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);let authority = Keypair::new();let airdrop_signature = client.request_airdrop(&authority.pubkey(), 5_000_000_000).await?;loop {let confirmed = client.confirm_transaction(&airdrop_signature).await?;if confirmed {break;}}let group_mint = Keypair::new();let group_mint_space =ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::GroupPointer])?;let group_mint_space_with_data = ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::GroupPointer,ExtensionType::TokenGroup,])?;let group_mint_rent = client.get_minimum_balance_for_rent_exemption(group_mint_space_with_data).await?;let create_group_mint_account_instruction = create_account(&authority.pubkey(), // Account funding the new mint account.&group_mint.pubkey(), // New group mint account to create.group_mint_rent, // Lamports funding the mint account rent.group_mint_space as u64, // Account size in bytes for the mint plus GroupPointer.&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.);let initialize_group_pointer_instruction = initialize_group_pointer(&TOKEN_2022_PROGRAM_ID,&group_mint.pubkey(), // Mint account that stores the GroupPointer extension.Some(authority.pubkey()), // Authority allowed to update the group pointer later.Some(group_mint.pubkey()), // Account address that stores the group data.)?;let initialize_group_mint_instruction = initialize_mint(&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.&group_mint.pubkey(), // Mint account to initialize.&authority.pubkey(), // Authority allowed to mint new tokens.Some(&authority.pubkey()), // Authority allowed to freeze token accounts.0, // Number of decimals for the token.)?;let initialize_group_instruction = initialize_group(&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.&group_mint.pubkey(), // Mint account that stores the group data.&group_mint.pubkey(), // Mint that the group data describes.&authority.pubkey(), // Signer authorizing group initialization for the mint.Some(authority.pubkey()), // Authority allowed to update the group later.10, // Maximum number of members allowed in the group.);let group_transaction = Transaction::new_signed_with_payer(&[create_group_mint_account_instruction,initialize_group_pointer_instruction,initialize_group_mint_instruction,initialize_group_instruction,],Some(&authority.pubkey()),&[&authority, &group_mint],client.get_latest_blockhash().await?,);client.send_and_confirm_transaction(&group_transaction).await?;let member_mint = Keypair::new();let member_mint_space =ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::GroupMemberPointer])?;let member_mint_space_with_data = ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::GroupMemberPointer,ExtensionType::TokenGroupMember,])?;let member_mint_rent = client.get_minimum_balance_for_rent_exemption(member_mint_space_with_data).await?;let create_member_mint_account_instruction = create_account(&authority.pubkey(), // Account funding the new mint account.&member_mint.pubkey(), // New member mint account to create.member_mint_rent, // Lamports funding the mint account rent.member_mint_space as u64, // Account size in bytes for the mint plus GroupMemberPointer.&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.);let initialize_member_pointer_instruction = initialize_group_member_pointer(&TOKEN_2022_PROGRAM_ID,&member_mint.pubkey(), // Mint account that stores the GroupMemberPointer extension.Some(authority.pubkey()), // Authority allowed to update the member pointer later.Some(member_mint.pubkey()), // Account address that stores the member data.)?;let initialize_member_mint_instruction = initialize_mint(&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.&member_mint.pubkey(), // Mint account to initialize.&authority.pubkey(), // Authority allowed to mint new tokens.Some(&authority.pubkey()), // Authority allowed to freeze token accounts.0, // Number of decimals for the token.)?;let initialize_member_instruction = initialize_member(&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.&member_mint.pubkey(), // Mint account that stores the member data.&member_mint.pubkey(), // Mint that the member data describes.&authority.pubkey(), // Signer authorizing member initialization for the mint.&group_mint.pubkey(), // Group mint that this member belongs to.&authority.pubkey(), // Signer matching the group's update authority.);let member_transaction = Transaction::new_signed_with_payer(&[create_member_mint_account_instruction,initialize_member_pointer_instruction,initialize_member_mint_instruction,initialize_member_instruction,],Some(&authority.pubkey()),&[&authority, &member_mint],client.get_latest_blockhash().await?,);client.send_and_confirm_transaction(&member_transaction).await?;let group_mint_account = client.get_account(&group_mint.pubkey()).await?;let group_mint_state = StateWithExtensions::<Mint>::unpack(&group_mint_account.data)?;let group_pointer = group_mint_state.get_extension::<GroupPointer>()?;let token_group = group_mint_state.get_extension::<TokenGroup>()?;let member_mint_account = client.get_account(&member_mint.pubkey()).await?;let member_mint_state = StateWithExtensions::<Mint>::unpack(&member_mint_account.data)?;let member_pointer = member_mint_state.get_extension::<GroupMemberPointer>()?;let token_group_member = member_mint_state.get_extension::<TokenGroupMember>()?;println!("\nGroup Mint: {}", group_mint.pubkey());println!("\nGroup Pointer: {:#?}", group_pointer);println!("\nToken Group: {:#?}", token_group);println!("\nMember Mint: {}", member_mint.pubkey());println!("\nGroup Member Pointer: {:#?}", member_pointer);println!("\nToken Group Member: {:#?}", token_group_member);Ok(())}
Is this page helpful?