Ομάδες και μέλη token

Τι Είναι οι Επεκτάσεις Group και Group Member;

Μια ομάδα είναι ένα mint που αντιπροσωπεύει μια συλλογή. Ένα μέλος ομάδας είναι ένα mint που ανήκει σε αυτή τη συλλογή.

Χρησιμοποιήστε αυτές τις επεκτάσεις όταν ένα mint πρέπει να αντιπροσωπεύει τη συλλογή και άλλα mints πρέπει να αντιπροσωπεύουν στοιχεία που ανήκουν σε αυτή.

Το Token Extensions Program μπορεί να αποθηκεύσει δεδομένα ομάδας token απευθείας σε ένα mint με τέσσερις σχετικές επεκτάσεις:

  • GroupPointer δείχνει ένα mint στον λογαριασμό που αποθηκεύει τα δεδομένα της ομάδας.
  • TokenGroup αποθηκεύει τα ίδια τα δεδομένα της ομάδας, συμπεριλαμβανομένης της αρχής ενημέρωσης, του τρέχοντος μεγέθους και του μέγιστου μεγέθους.
  • GroupMemberPointer δείχνει ένα mint στον λογαριασμό που αποθηκεύει τα δεδομένα του μέλους.
  • TokenGroupMember αποθηκεύει τη διεύθυνση της ομάδας του μέλους και τον αριθμό μέλους.

Τα GroupPointer και GroupMemberPointer μπορούν να αναφέρονται σε οποιονδήποτε λογαριασμό που ανήκει σε ένα πρόγραμμα που υλοποιεί το Token group interface.

Το Token Extensions Program υλοποιεί επίσης αυτή τη διεπαφή απευθείας μέσω των επεκτάσεων mint TokenGroup και TokenGroupMember.

Πώς να Δημιουργήσετε Ομάδες και Μέλη που Αποθηκεύονται στο Mint Account

Για να δημιουργήσετε ομάδες και μέλη που αποθηκεύονται στο mint account:

  1. Δημιουργήστε ένα group mint account και αρχικοποιήστε το GroupPointer.
  2. Αρχικοποιήστε το group mint με InitializeMint.
  3. Αρχικοποιήστε το TokenGroup στο ίδιο αυτό mint.
  4. Δημιουργήστε ένα member mint account και αρχικοποιήστε το GroupMemberPointer.
  5. Αρχικοποιήστε το member mint με InitializeMint.
  6. Αρχικοποιήστε το TokenGroupMember στο ίδιο αυτό mint ώστε να αναφέρεται στο group mint.

Υπολογισμός μεγέθους και ενοικίου για το group mint

Υπολογίστε το μέγεθος και το ενοίκιο που απαιτούνται για το group mint.

Δημιουργία και Αρχικοποίηση Group Mint

Δημιουργήστε το λογαριασμό group mint, αρχικοποιήστε το GroupPointer, αρχικοποιήστε το mint και αρχικοποιήστε το TokenGroup σε μία συναλλαγή.

Υπολογισμός μεγέθους και ενοικίου για το member mint

Υπολογίστε το μέγεθος και το ενοίκιο που απαιτούνται για το member mint.

Δημιουργία και Αρχικοποίηση Member Mint

Δημιουργήστε το λογαριασμό member mint, αρχικοποιήστε το GroupMemberPointer, αρχικοποιήστε το mint και αρχικοποιήστε το TokenGroupMember σε μία συναλλαγή.

Υπολογισμός μεγέθους και ενοικίου για το group mint

Υπολογίστε το μέγεθος και το ενοίκιο που απαιτούνται για το group mint.

Δημιουργία και Αρχικοποίηση Group Mint

Δημιουργήστε το λογαριασμό group mint, αρχικοποιήστε το GroupPointer, αρχικοποιήστε το mint και αρχικοποιήστε το TokenGroup σε μία συναλλαγή.

Υπολογισμός μεγέθους και ενοικίου για το member mint

Υπολογίστε το μέγεθος και το ενοίκιο που απαιτούνται για το member mint.

Δημιουργία και Αρχικοποίηση Member Mint

Δημιουργήστε το λογαριασμό member mint, αρχικοποιήστε το GroupMemberPointer, αρχικοποιήστε το mint και αρχικοποιήστε το TokenGroupMember σε μία συναλλαγή.

Example
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();

Δείκτες και Σειρά Εντολών

Το GroupPointer και το GroupMemberPointer αποθηκεύουν τη διεύθυνση του λογαριασμού όπου βρίσκονται τα δεδομένα της ομάδας ή του μέλους. Το TokenGroup και το TokenGroupMember αποθηκεύουν τα πραγματικά δεδομένα της ομάδας ή του μέλους.

Το GroupPointerInstruction::Initialize και το GroupMemberPointerInstruction::Initialize πρέπει να προηγούνται του InitializeMint. Το TokenGroupInstruction::InitializeGroup και το TokenGroupInstruction::InitializeMember πρέπει να έπονται του InitializeMint. Για κάθε mint, το CreateAccount, η εντολή αρχικοποίησης του δείκτη και το InitializeMint πρέπει να συμπεριλαμβάνονται στην ίδια συναλλαγή.

Αναφορά Πηγής

Το GroupPointer και το GroupMemberPointer είναι εντολές δείκτη στο Token Extensions Program. Το TokenGroup και το TokenGroupMember ακολουθούν τη διεπαφή Token group, την οποία υλοποιεί το Token Extensions Program.

Group Pointer και Group Member Pointer

ΣτοιχείοΠεριγραφήΠηγή
GroupPointerΕπέκταση mint που αποθηκεύει την εξουσιοδότηση και τη διεύθυνση για τον λογαριασμό που αποθηκεύει τα δεδομένα μιας ομάδας.Πηγή
GroupMemberPointerΕπέκταση mint που αποθηκεύει την εξουσιοδότηση και τη διεύθυνση για τον λογαριασμό που αποθηκεύει τα δεδομένα ενός μέλους.Πηγή
GroupPointerInstruction::InitializeΑρχικοποιεί την επέκταση group pointer πριν από το InitializeMint.Πηγή
GroupPointerInstruction::UpdateΕνημερώνει τη διεύθυνση ομάδας που αποθηκεύεται από την επέκταση GroupPointer του mint.Πηγή
GroupMemberPointerInstruction::InitializeΑρχικοποιεί την επέκταση group member pointer πριν από το InitializeMint.Πηγή
GroupMemberPointerInstruction::UpdateΕνημερώνει τη διεύθυνση μέλους που αποθηκεύεται από την επέκταση GroupMemberPointer του mint.Πηγή
process_initialize (GroupPointer)Γράφει την αρχική εξουσιοδότηση GroupPointer και τη διεύθυνση ομάδας στο mint.Πηγή
process_update (GroupPointer)Επικυρώνει την εξουσιοδότηση του group pointer και στη συνέχεια επανεγγράφει την αποθηκευμένη διεύθυνση ομάδας του mint.Πηγή
process_initialize (GroupMemberPointer)Γράφει την αρχική εξουσιοδότηση GroupMemberPointer και τη διεύθυνση μέλους στο mint.Πηγή
process_update (GroupMemberPointer)Επικυρώνει την εξουσιοδότηση του group member pointer και στη συνέχεια επανεγγράφει την αποθηκευμένη διεύθυνση μέλους του mint.Πηγή

Ομάδα Tokens και Μέλος Ομάδας Tokens

ΣτοιχείοΠεριγραφήΠηγή
TokenGroupΚατάσταση διεπαφής ομάδας tokens που αποθηκεύεται στο mint, συμπεριλαμβανομένης της αρχής ενημέρωσης, του τρέχοντος μεγέθους και του μέγιστου μεγέθους.Πηγή
TokenGroupMemberΚατάσταση διεπαφής μέλους ομάδας tokens που αποθηκεύεται στο mint, συμπεριλαμβανομένου του mint μέλους, της διεύθυνσης ομάδας και του αριθμού μέλους.Πηγή
TokenGroupInstruction::InitializeGroupΕντολή διεπαφής ομάδας tokens που υποστηρίζεται από το Token Extensions Program για την προετοιμασία μιας νέας ομάδας για ένα ήδη προετοιμασμένο mint.Πηγή
TokenGroupInstruction::UpdateGroupMaxSizeΕντολή διεπαφής ομάδας tokens που υποστηρίζεται από το Token Extensions Program για την ενημέρωση του μέγιστου αριθμού μελών που επιτρέπονται σε μια ομάδα.Πηγή
TokenGroupInstruction::UpdateGroupAuthorityΕντολή διεπαφής ομάδας tokens που υποστηρίζεται από το Token Extensions Program για την εναλλαγή ή την εκκαθάριση της αρχής ενημέρωσης της ομάδας.Πηγή
TokenGroupInstruction::InitializeMemberΕντολή διεπαφής ομάδας tokens που υποστηρίζεται από το Token Extensions Program για την προετοιμασία ενός νέου μέλους για μια ήδη προετοιμασμένη ομάδα.Πηγή
process_initialize_groupΕπικυρώνει το mint, ελέγχει ότι το GroupPointer είναι παρόν και εκχωρεί την κατάσταση TokenGroup στο mint της ομάδας.Πηγή
process_update_group_max_sizeΕπικυρώνει την τρέχουσα αρχή ενημέρωσης και στη συνέχεια ενημερώνει το μέγιστο μέγεθος της ομάδας.Πηγή
process_update_group_authorityΕπικυρώνει την τρέχουσα αρχή ενημέρωσης και στη συνέχεια εναλλάσσει ή εκκαθαρίζει την αρχή ενημέρωσης της ομάδας.Πηγή
process_initialize_memberΕπικυρώνει το mint μέλους και την αρχή της ομάδας, αυξάνει το μέγεθος της ομάδας και εκχωρεί την κατάσταση TokenGroupMember στο mint.Πηγή

Typescript

Το παρακάτω παράδειγμα με Kit χρησιμοποιεί απευθείας τις παραγόμενες οδηγίες. Παλαιότερα παραδείγματα που χρησιμοποιούν @solana/web3.js, @solana/spl-token και τους βοηθούς ομάδας token περιλαμβάνονται για αναφορά.

Kit

Instructions
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
)
);
Console
Click to execute the code.

Web3.js

Instructions
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
)
);
Console
Click to execute the code.

Rust

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(())
}
Console
Click to execute the code.

Is this page helpful?

Διαχειρίζεται από

© 2026 Ίδρυμα Solana.
Με επιφύλαξη παντός δικαιώματος.
Συνδεθείτε