Con il programma Token Extension, puoi creare NFT e asset digitali utilizzando le estensioni per i metadati. Insieme, queste estensioni (metadata pointer e token metadata) ti permettono di inserire qualsiasi metadato desiderato nativamente onchain. Il tutto all'interno di un archivio dati chiave-valore personalizzabile direttamente sul mint account del token, riducendo costi e complessità.
Questi possono essere particolarmente utili per i giochi web3, poiché ora è possibile avere questi "campi di metadati aggiuntivi" all'interno di un archivio chiave-valore onchain, consentendo ai giochi di salvare/accedere a stati univoci direttamente nell'NFT stesso (ad esempio per le statistiche o l'inventario di un personaggio di gioco).
Sviluppo del programma onchain
In questa guida per sviluppatori, dimostreremo come creare questi NFT basati su Token Extension e metadati personalizzati utilizzando un programma Anchor. Questo programma salverà il livello e le risorse raccolte di un giocatore all'interno di un NFT.
Questo NFT verrà creato dal programma Anchor, rendendo il minting molto semplice tramite client JavaScript. Ogni NFT avrà una struttura di base fornita tramite la Token Metadata interface:
- campi onchain predefiniti -
name,symboleuri- l'
uriè un collegamento a un file JSON offchain che contiene i metadati offchain dell'NFT
- l'
- avremo anche "campi aggiuntivi" personalizzati che definiamo noi stessi
Tutti questi campi vengono salvati utilizzando l'estensione per i metadati, che punta al mint account dell'NFT, rendendoli accessibili a chiunque o a qualsiasi programma.
Video e Codice Sorgente
Puoi trovare una guida video di questo esempio sul canale YouTube della Solana Foundation:
Altri casi d'uso nei giochi
Questi tipi di NFT con metadati onchain personalizzabili aprono molte interessanti possibilità per gli sviluppatori di giochi. Soprattutto perché questi metadati possono essere direttamente interagiti o gestiti da un programma onchain.
Alcuni di questi casi d'uso legati al gaming includono:
- salvare il livello e i punti XP del giocatore
- l'arma e l'armatura attuale
- la missione attuale
- e l'elenco continua!
Minting dell'NFT
Per creare l'NFT dobbiamo eseguire i seguenti passaggi:
- Creare un mint account
- Inizializzare il mint account
- Creare un account metadata pointer
- Inizializzare l'account metadata pointer
- Creare l'account dei metadati
- Inizializzare l'account dei metadati
- Creare l'associated token account
- Eseguire il mint del token sull'associated token account
- Congelare la mint authority
Codice del programma Rust
Ecco il codice Rust utilizzato per eseguire il mint dell'NFT usando il programma Token Extension:
// calculate the space need for the mint account with the desired extensionslet 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 programsystem_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 cpilet 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 accountlet 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 levelinvoke_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 accountassociated_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 playertoken_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 NFTtoken_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,)?;
Codice del client JavaScript
Richiamare il mint dell'NFT dal client è molto semplice:
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`);
Esempio di avvio rapido
L'esempio precedente è basato sul Solana Games Preset, che genera uno scaffold che include un client JavaScript e Unity per questo gioco, comprensiva della configurazione per interagire con il programma Anchor di Solana.
Puoi eseguirlo autonomamente con il seguente comando:
npx create-solana-game gameName
Configurazione dell'ambiente locale
Per eseguire questo esempio in locale, dovrai assicurarti di aver configurato il tuo ambiente locale per lo sviluppo su Solana, includendo l'installazione e la configurazione dell'Anchor CLI. Se non l'hai ancora fatto, puoi seguire la guida di configurazione precedentemente indicata.
Struttura del progetto
Il progetto Anchor è strutturato nel seguente modo:
Il punto di ingresso si trova nel file lib.rs. Qui definiamo l'ID del programma e le istruzioni. Le istruzioni sono definite nella cartella instructions. Lo stato è definito nella cartella state.
Le chiamate arrivano quindi nel file lib.rs e vengono poi inoltrate alle istruzioni. Le istruzioni chiamano poi lo stato per ottenere i dati e aggiornarlo.
Puoi trovare l'istruzione per il mint dell'NFT nella cartella 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
Programma Anchor
Per completare la configurazione del programma Anchor generato dallo strumento create-solana-game:
cd programper accedere alla directory del programma- Esegui
anchor buildper compilare il programma - Esegui
anchor deployper distribuire il programma - Copia l'ID del programma dal terminale nel file
lib.rs,anchor.tomle nel progetto Unity inAnchorServicee, se usi JavaScript, nel fileanchor.ts - Compila e distribuisci di nuovo
Client NextJS
Per completare la configurazione del client NextJS generato dallo strumento create-solana-game:
- Copia il
programIdinapp/utils/anchor.ts cd appper accedere alla directory dell'app- Esegui
yarn installper installare le dipendenze Node - Esegui
yarn devper avviare il client - Dopo aver apportato modifiche al programma Anchor, assicurati di copiare i tipi
dal programma nel client per poterli utilizzare. Puoi trovare i
tipi TypeScript nella cartella
target/idl.
Esegui questo esempio in locale
Utilizzando il comando test di Anchor con il flag --detach, verrà avviato e configurato
il tuo validator locale di test di Solana con il programma distribuito (mantenendo il
validator in esecuzione al termine dei test):
cd programanchor test --detach
Puoi quindi impostare Solana Explorer per utilizzare il tuo
validator locale di test (che si avvia quando si esegue il comando anchor test) in modo
da poter visualizzare le transazioni:
https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899
Il programma è già distribuito sulla rete, quindi puoi provarlo su devnet.
Il client JavaScript include anche un pulsante per eseguire il mint dell'NFT. Per avviare il client JavaScript:
cd appyarn installyarn dev
Aprire il progetto Unity
Prima apri il progetto Unity con Unity versione 2021.3.32.f1 (o simile), poi
apri la GameScene o la LoginScene e premi play. Usa il pulsante di login nell'editor
in basso a sinistra.
Se non riesci a ottenere SOL su devnet, puoi copiare il tuo indirizzo dalla console e seguire le istruzioni in questa guida su come ottenere SOL su devnet
Connessione al validator di test di Solana in Unity
Se vuoi evitare di doverti preoccupare di mantenere SOL su devnet, puoi connetterti al tuo validator locale di test in esecuzione direttamente da Unity. Aggiungi semplicemente questi collegamenti sull'oggetto di gioco wallet holder:
http://localhost:8899ws://localhost:8900
Avviare il client JavaScript
Per avviare il client JavaScript e poter interagire con il gioco e il programma tramite il tuo browser web:
- apri la directory
appnel repository - installa le dipendenze Node
- esegui il comando
devper avviare il server di sviluppo
cd appyarn installyarn dev
Per iniziare a modificare il programma e connetterti al tuo programma personalizzato, segui i passaggi indicati di seguito.
Is this page helpful?