Δυναμικά μεταδεδομένα NFT χρησιμοποιώντας Token Extensions

Με το Token Extension program, μπορείτε να δημιουργήσετε NFT και ψηφιακά στοιχεία χρησιμοποιώντας τις επεκτάσεις μεταδεδομένων. Μαζί, αυτές οι επεκτάσεις (metadata pointer και token metadata) σας επιτρέπουν να τοποθετείτε οποιαδήποτε επιθυμητά μεταδεδομένα εγγενώς onchain. Όλα αυτά σε ένα προσαρμόσιμο αποθηκευτικό χώρο κλειδιού-τιμής απευθείας στο mint account του token, μειώνοντας το κόστος και την πολυπλοκότητα.

Αυτά μπορούν να είναι ιδιαίτερα χρήσιμα για παιχνίδια web3 καθώς μπορούμε πλέον να έχουμε αυτά τα «πρόσθετα πεδία μεταδεδομένων» σε έναν onchain αποθηκευτικό χώρο κλειδιού-τιμής, επιτρέποντας στα παιχνίδια να αποθηκεύουν/προσπελαύνουν μοναδική κατάσταση μέσα στο ίδιο το NFT (όπως τα στατιστικά ή την αποθήκη ενός χαρακτήρα παιχνιδιού).

Δημιουργία του onchain προγράμματος

Σε αυτόν τον οδηγό για προγραμματιστές, θα δείξουμε πώς να δημιουργείτε αυτά τα NFT βασισμένα στο Token Extension και προσαρμοσμένα μεταδεδομένα χρησιμοποιώντας ένα πρόγραμμα Anchor. Αυτό το πρόγραμμα θα αποθηκεύει το επίπεδο και τους συλλεχθέντες πόρους ενός παίκτη παιχνιδιού μέσα σε ένα NFT.

Αυτό το NFT θα δημιουργείται από το πρόγραμμα Anchor, επομένως είναι πολύ εύκολο να γίνει mint από τον JavaScript client. Κάθε NFT θα έχει κάποια βασική δομή που παρέχεται μέσω του Token Metadata interface:

  • προεπιλεγμένα onchain πεδία - name, symbol και uri
    • το uri είναι ένας σύνδεσμος προς ένα offchain αρχείο json που περιέχει τα off chain μεταδεδομένα του NFT
  • θα έχουμε επίσης προσαρμοσμένα «πρόσθετα πεδία» που ορίζουμε εμείς

Όλα αυτά τα πεδία αποθηκεύονται χρησιμοποιώντας την επέκταση μεταδεδομένων που δείχνει στο mint account του NFT, καθιστώντας τα προσβάσιμα σε οποιονδήποτε ή οποιοδήποτε πρόγραμμα.

Βίντεο και Πηγαίος Κώδικας

Μπορείτε να βρείτε μια βιντεοπαρουσίαση αυτού του παραδείγματος στο κανάλι Youtube του Solana Foundation:

Άλλες περιπτώσεις χρήσης στα παιχνίδια

Αυτοί οι τύποι NFT με προσαρμόσιμα onchain μεταδεδομένα ανοίγουν πολλές ενδιαφέρουσες δυνατότητες για προγραμματιστές παιχνιδιών. Ειδικά επειδή αυτά τα μεταδεδομένα μπορούν να αλληλεπιδράσουν άμεσα ή να διαχειριστούν από ένα onchain πρόγραμμα.

Μερικές από αυτές τις περιπτώσεις χρήσης που σχετίζονται με παιχνίδια περιλαμβάνουν:

  • αποθήκευση του επιπέδου και του XP του παίκτη
  • το τρέχον όπλο και η τρέχουσα πανοπλία
  • η τρέχουσα αποστολή
  • η λίστα συνεχίζεται!

Δημιουργία mint του NFT

Για να δημιουργήσουμε το NFT πρέπει να εκτελέσουμε τα παρακάτω βήματα:

  1. Δημιουργία mint account
  2. Αρχικοποίηση του mint account
  3. Δημιουργία λογαριασμού δείκτη μεταδεδομένων
  4. Αρχικοποίηση του λογαριασμού δείκτη μεταδεδομένων
  5. Δημιουργία του λογαριασμού μεταδεδομένων
  6. Αρχικοποίηση του λογαριασμού μεταδεδομένων
  7. Δημιουργία του associated token account
  8. Mint του token στο associated token account
  9. Πάγωμα της αρχής mint

Κώδικας προγράμματος Rust

Ακολουθεί ο κώδικας Rust που χρησιμοποιείται για το mint του NFT χρησιμοποιώντας το Token Extension program:

// calculate the space need for the mint account with the desired extensions
let space = ExtensionType::try_calculate_account_len::<Mint>(
&[ExtensionType::MetadataPointer])
.unwrap();
// This is the space required for the metadata account.
// We put the metadata into the mint account at the end so we
// don't need to create and additional account.
// Then the metadata pointer points back to the mint account.
// Using this technique, only one account is needed for both the mint
// information and the metadata.
let meta_data_space = 250;
let lamports_required = (Rent::get()?).minimum_balance(space + meta_data_space);
msg!(
"Create Mint and metadata account size and cost: {} lamports: {}",
space as u64,
lamports_required
);
system_program::create_account(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
system_program::CreateAccount {
from: ctx.accounts.signer.to_account_info(),
to: ctx.accounts.mint.to_account_info(),
},
),
lamports_required,
space as u64,
&ctx.accounts.token_program.key(),
)?;
// Assign the mint to the token program
system_program::assign(
CpiContext::new(
ctx.accounts.token_program.to_account_info(),
system_program::Assign {
account_to_assign: ctx.accounts.mint.to_account_info(),
},
),
&token_2022::ID,
)?;
// Initialize the metadata pointer (Need to do this before initializing the mint)
let init_meta_data_pointer_ix =
spl_token_2022::extension::metadata_pointer::instruction::initialize(
&Token2022::id(),
&ctx.accounts.mint.key(),
Some(ctx.accounts.nft_authority.key()),
Some(ctx.accounts.mint.key()),
)
.unwrap();
invoke(
&init_meta_data_pointer_ix,
&[
ctx.accounts.mint.to_account_info(),
ctx.accounts.nft_authority.to_account_info()
],
)?;
// Initialize the mint cpi
let mint_cpi_ix = CpiContext::new(
ctx.accounts.token_program.to_account_info(),
token_2022::InitializeMint2 {
mint: ctx.accounts.mint.to_account_info(),
},
);
token_2022::initialize_mint2(
mint_cpi_ix,
0,
&ctx.accounts.nft_authority.key(),
None).unwrap();
// We use a PDA as a mint authority for the metadata account because
// we want to be able to update the NFT from the program.
let seeds = b"nft_authority";
let bump = ctx.bumps.nft_authority;
let signer: &[&[&[u8]]] = &[&[seeds, &[bump]]];
msg!("Init metadata {0}", ctx.accounts.nft_authority.to_account_info().key);
// Init the metadata account
let init_token_meta_data_ix =
&spl_token_metadata_interface::instruction::initialize(
&spl_token_2022::id(),
ctx.accounts.mint.key,
ctx.accounts.nft_authority.to_account_info().key,
ctx.accounts.mint.key,
ctx.accounts.nft_authority.to_account_info().key,
"Beaver".to_string(),
"BVA".to_string(),
"https://arweave.net/MHK3Iopy0GgvDoM7LkkiAdg7pQqExuuWvedApCnzfj0".to_string(),
);
invoke_signed(
init_token_meta_data_ix,
&[ctx.accounts.mint.to_account_info().clone(), ctx.accounts.nft_authority.to_account_info().clone()],
signer,
)?;
// Update the metadata account with an additional metadata field in this case the player level
invoke_signed(
&spl_token_metadata_interface::instruction::update_field(
&spl_token_2022::id(),
ctx.accounts.mint.key,
ctx.accounts.nft_authority.to_account_info().key,
spl_token_metadata_interface::state::Field::Key("level".to_string()),
"1".to_string(),
),
&[
ctx.accounts.mint.to_account_info().clone(),
ctx.accounts.nft_authority.to_account_info().clone(),
],
signer
)?;
// Create the associated token account
associated_token::create(
CpiContext::new(
ctx.accounts.associated_token_program.to_account_info(),
associated_token::Create {
payer: ctx.accounts.signer.to_account_info(),
associated_token: ctx.accounts.token_account.to_account_info(),
authority: ctx.accounts.signer.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
},
))?;
// Mint one token to the associated token account of the player
token_2022::mint_to(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
token_2022::MintTo {
mint: ctx.accounts.mint.to_account_info(),
to: ctx.accounts.token_account.to_account_info(),
authority: ctx.accounts.nft_authority.to_account_info(),
},
signer
),
1,
)?;
// Freeze the mint authority so no more tokens can be minted to make it an NFT
token_2022::set_authority(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
token_2022::SetAuthority {
current_authority: ctx.accounts.nft_authority.to_account_info(),
account_or_mint: ctx.accounts.mint.to_account_info(),
},
signer
),
AuthorityType::MintTokens,
None,
)?;

Κώδικας JavaScript client

Η κλήση mint NFT από τον client είναι πολύ εύκολη:

const nftAuthority = PublicKey.findProgramAddressSync(
[Buffer.from("nft_authority")],
program.programId
);
const mint = new Keypair();
const destinationTokenAccount = getAssociatedTokenAddressSync(
mint.publicKey,
publicKey,
false,
TOKEN_2022_PROGRAM_ID
);
const transaction = await program.methods
.mintNft()
.accounts({
signer: publicKey,
systemProgram: SystemProgram.programId,
tokenProgram: TOKEN_2022_PROGRAM_ID,
tokenAccount: destinationTokenAccount,
mint: mint.publicKey,
rent: web3.SYSVAR_RENT_PUBKEY,
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
nftAuthority: nftAuthority[0]
})
.signers([mint])
.transaction();
console.log("transaction", transaction);
const txSig = await sendTransaction(transaction, connection, {
signers: [mint],
skipPreflight: true
});
console.log(`https://explorer.solana.com/tx/${txSig}?cluster=devnet`);

Παράδειγμα γρήγορης εκκίνησης

Το παραπάνω παράδειγμα βασίζεται στο Solana Games Preset, το οποίο δημιουργεί ένα σκελετό που περιλαμβάνει έναν JavaScript και Unity client για αυτό το παιχνίδι, συμπεριλαμβανομένης της διαμόρφωσης για αλληλεπίδραση με το πρόγραμμα Anchor του Solana.

Μπορείτε να το εκτελέσετε μόνοι σας με την παρακάτω εντολή:

npx create-solana-game gameName

Ρύθμιση του τοπικού σας περιβάλλοντος

Για να εκτελέσετε αυτό το παράδειγμα τοπικά, θα πρέπει να βεβαιωθείτε ότι έχετε ρυθμίσει το τοπικό σας περιβάλλον για ανάπτυξη Solana, συμπεριλαμβανομένης της εγκατάστασης και διαμόρφωσης του Anchor CLI. Εάν δεν το έχετε κάνει ήδη, μπορείτε να ακολουθήσετε τον προαναφερθέντα οδηγό ρύθμισης για να το κάνετε.

Δομή έργου

Το έργο Anchor είναι δομημένο ως εξής:

Το σημείο εισόδου βρίσκεται στο αρχείο lib.rs. Εδώ ορίζουμε το αναγνωριστικό προγράμματος και τις εντολές. Οι εντολές ορίζονται στον φάκελο instructions. Η κατάσταση ορίζεται στον φάκελο state.

Έτσι οι κλήσεις φτάνουν στο αρχείο lib.rs και στη συνέχεια προωθούνται στις εντολές. Οι εντολές στη συνέχεια καλούν την κατάσταση για να λάβουν τα δεδομένα και να τα ενημερώσουν.

Μπορείτε να βρείτε την εντολή mint NFT στον φάκελο instructions.

├── src
├── instructions
│ ├── chop_tree.rs
│ ├── init_player.rs
│ ├── mint_nft.rs
│ └── update_energy.rs
├── state
│ ├── game_data.rs
│ ├── mod.rs
│ └── player_data.rs
├── lib.rs
└── constants.rs
└── errors.rs

Πρόγραμμα Anchor

Για να ολοκληρώσετε τη ρύθμιση του προγράμματος Anchor που δημιουργήθηκε από το εργαλείο create-solana-game:

  1. cd program για μετάβαση στον κατάλογο του προγράμματος
  2. Εκτελέστε anchor build για να δημιουργήσετε το πρόγραμμα
  3. Εκτελέστε anchor deploy για να αναπτύξετε το πρόγραμμα
  4. Αντιγράψτε το αναγνωριστικό προγράμματος από το τερματικό στα lib.rs, anchor.toml και μέσα στο έργο Unity στο AnchorService και αν χρησιμοποιείτε JavaScript στο αρχείο anchor.ts
  5. Δημιουργήστε και αναπτύξτε ξανά

NextJS client

Για να ολοκληρώσετε τη ρύθμιση του NextJS client που δημιουργήθηκε από το εργαλείο create-solana-game:

  1. Αντιγράψτε το programId στο app/utils/anchor.ts
  2. cd app για μετάβαση στον κατάλογο της εφαρμογής
  3. Εκτελέστε yarn install για εγκατάσταση των εξαρτήσεων Node
  4. Εκτελέστε yarn dev για εκκίνηση του client
  5. Μετά από αλλαγές στο πρόγραμμα Anchor, φροντίστε να αντιγράψετε τους τύπους από το πρόγραμμα στον client για να μπορείτε να τους χρησιμοποιήσετε. Μπορείτε να βρείτε τους τύπους TypeScript στον φάκελο target/idl.

Εκτέλεση αυτού του παραδείγματος τοπικά

Η χρήση της εντολής test του Anchor με την παράμετρο --detach θα εκκινήσει και θα διαμορφώσει τον τοπικό σας validator δοκιμών Solana ώστε να έχει αναπτυχθεί το πρόγραμμα (και θα διατηρεί τον validator σε λειτουργία μετά την ολοκλήρωση των δοκιμών):

cd program
anchor test --detach

Στη συνέχεια μπορείτε να ρυθμίσετε το Solana Explorer να χρησιμοποιεί τον τοπικό σας validator δοκιμών (ο οποίος εκκινεί κατά την εκτέλεση της εντολής anchor test) για να βλέπετε τις συναλλαγές:

https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899

Το πρόγραμμα είναι επίσης ήδη αναπτυγμένο στο net, ώστε να μπορείτε να το δοκιμάσετε στο devnet. Ο JavaScript client διαθέτει επίσης ένα κουμπί για mint του NFT. Εκκίνηση του JavaScript client:

cd app
yarn install
yarn dev

Άνοιγμα του έργου Unity

Πρώτα ανοίξτε το έργο Unity με την έκδοση Unity 2021.3.32.f1 (ή παρόμοια), στη συνέχεια ανοίξτε το GameScene ή LoginScene και πατήστε play. Χρησιμοποιήστε το κουμπί σύνδεσης του editor στο κάτω αριστερό μέρος.

Εάν δεν μπορείτε να αποκτήσετε devnet SOL, μπορείτε να αντιγράψετε τη διεύθυνσή σας από την κονσόλα και να ακολουθήσετε τις οδηγίες σε αυτόν τον οδηγό για πώς να αποκτήσετε devnet SOL

Σύνδεση στον validator δοκιμών Solana στο Unity

Εάν θέλετε να αποφύγετε την ανησυχία για τη διατήρηση devnet SOL, μπορείτε να συνδεθείτε στον τοπικό σας εκτελούμενο validator δοκιμών μέσα από το Unity. Απλώς προσθέστε αυτούς τους συνδέσμους στο αντικείμενο παιχνιδιού wallet holder:

http://localhost:8899
ws://localhost:8900

Εκτέλεση του JavaScript client

Για να εκκινήσετε τον JavaScript client και να μπορείτε να αλληλεπιδράτε με το παιχνίδι και το πρόγραμμα χρησιμοποιώντας το πρόγραμμα περιήγησής σας:

  • ανοίξτε τον κατάλογο app μέσα στο αποθετήριο
  • εγκαταστήστε τις εξαρτήσεις Node
  • εκτελέστε την εντολή dev για εκκίνηση του διακομιστή ανάπτυξης
cd app
yarn install
yarn dev

Για να αρχίσετε να αλλάζετε το πρόγραμμα και να συνδέεστε στο δικό σας πρόγραμμα, ακολουθήστε τα παρακάτω βήματα.

Is this page helpful?

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