Dzięki programowi Token Extension program możesz tworzyć NFT i zasoby cyfrowe przy użyciu rozszerzeń metadanych. Łącznie te rozszerzenia (metadata pointer i token metadata) umożliwiają przechowywanie dowolnych metadanych natywnie w łańcuchu bloków. Wszystko w konfigurowalnym magazynie danych klucz-wartość bezpośrednio na mint account tokena, co obniża koszty i złożoność.
Rozwiązanie to może być szczególnie przydatne dla gier web3, ponieważ teraz możemy mieć te "dodatkowe pola metadanych" w onchainowym magazynie klucz-wartość, co pozwala grom zapisywać i odczytywać unikalny stan w samym NFT (np. statystyki lub ekwipunek postaci w grze).
Budowanie programu onchain
W tym przewodniku dla deweloperów pokażemy, jak budować NFT oparte na Token Extension i niestandardowe metadane przy użyciu programu Anchor. Ten program zapisze poziom i zebrane zasoby gracza w NFT.
NFT zostanie stworzone przez program Anchor, dzięki czemu jego mintowanie z poziomu klienta JavaScript jest bardzo proste. Każde NFT będzie miało podstawową strukturę dostarczaną przez interfejs Token Metadata:
- domyślne pola onchain –
name,symboliuriurito link do pliku JSON przechowywanego poza łańcuchem bloków, który zawiera offchain metadane NFT
- zdefiniujemy również niestandardowe "dodatkowe pola"
Wszystkie te pola są zapisywane przy użyciu rozszerzenia metadanych wskazującego na mint account NFT, dzięki czemu są dostępne dla każdego użytkownika lub programu.
Wideo i kod źródłowy
Filmowy przewodnik po tym przykładzie znajdziesz na kanale YouTube Solana Foundation:
Inne przypadki użycia w grach
Tego typu NFT z konfigurowalnymi metadanymi onchain otwierają wiele interesujących możliwości dla deweloperów gier. Zwłaszcza że tymi metadanymi można bezpośrednio wchodzić w interakcję lub zarządzać za pomocą programu onchain.
Niektóre z tych zastosowań związanych z grami obejmują:
- zapisywanie poziomu i XP gracza
- aktualny ekwipunek i zbroja
- bieżące zadanie
- lista jest długa!
Mintowanie NFT
Aby stworzyć NFT, należy wykonać następujące kroki:
- Utwórz mint account
- Zainicjalizuj mint account
- Utwórz konto wskaźnika metadanych
- Zainicjalizuj konto wskaźnika metadanych
- Utwórz konto metadanych
- Zainicjalizuj konto metadanych
- Utwórz associated token account
- Mintuj token do associated token account
- Zablokuj uprawnienia mintowania
Kod programu w Rust
Oto kod Rust użyty do mintowania NFT przy użyciu programu 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,)?;
Kod klienta JavaScript
Wywołanie mintowania NFT z poziomu klienta jest bardzo proste:
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`);
Przykład szybkiego startu
Powyższy przykład oparty jest na Solana Games Preset, który generuje szkielet projektu zawierający klienta JavaScript i Unity dla tej gry, w tym konfigurację do interakcji z programem Anchor w Solanie.
Możesz uruchomić go samodzielnie za pomocą następującego polecenia:
npx create-solana-game gameName
Konfiguracja lokalnego środowiska
Aby uruchomić ten przykład lokalnie, musisz upewnić się, że masz skonfigurowane lokalne środowisko do programowania w Solanie, w tym zainstalowane i skonfigurowane Anchor CLI. Jeśli jeszcze tego nie zrobiłeś, może skorzystać z wcześniej podanego przewodnika konfiguracji.
Struktura projektu
Projekt Anchor ma następującą strukturę:
Punkt wejścia znajduje się w pliku lib.rs. Tam definiujemy identyfikator programu i instrukcje. Instrukcje są zdefiniowane w folderze instructions. Stan jest zdefiniowany w folderze state.
Wywołania trafiają do pliku lib.rs i są następnie przekazywane do instrukcji. Instrukcje wywołują następnie stan, aby pobrać dane i je aktualizować.
Instrukcję mintowania NFT znajdziesz w folderze 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
Program Anchor
Aby dokończyć konfigurację programu Anchor wygenerowanego przez narzędzie create-solana-game:
cd programaby przejść do katalogu programu- Uruchom
anchor build, aby zbudować program - Uruchom
anchor deploy, aby wdrożyć program - Skopiuj identyfikator programu z terminala do plików
lib.rs,anchor.tomloraz w projekcie Unity doAnchorService, a jeśli używasz JavaScript – do plikuanchor.ts - Zbuduj i wdróż ponownie
Klient NextJS
Aby dokończyć konfigurację klienta NextJS wygenerowanego przez narzędzie create-solana-game:
- Skopiuj
programIddoapp/utils/anchor.ts cd appaby przejść do katalogu aplikacji- Uruchom
yarn install, aby zainstalować zależności Node - Uruchom
yarn dev, aby uruchomić klienta - Po wprowadzeniu zmian w programie Anchor pamiętaj, aby skopiować typy
z programu do klienta, żeby móc z nich korzystać. Typy TypeScript znajdziesz
w folderze
target/idl.
Uruchamianie tego przykładu lokalnie
Użycie polecenia test Anchor z flagą --detach uruchomi i skonfiguruje
lokalne środowisko testowe validator Solany z wdrożonym programem (i utrzyma
validator uruchomiony po zakończeniu testów):
cd programanchor test --detach
Następnie możesz ustawić Solana Explorer tak, aby korzystał z
lokalnegośrodowiska testowego validator (uruchamianego podczas wykonywania polecenia anchor test),
dzięki czemu możesz przeglądać transakcje:
https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899
Program jest już wdrożony w sieci, więc możesz go wypróbować na devnet.
Klient JavaScript posiada również przycisk do mintowania NFT. Uruchamianie klienta JavaScript:
cd appyarn installyarn dev
Otwieranie projektu Unity
Najpierw otwórz projekt Unity w wersji Unity 2021.3.32.f1 (lub podobnej), następnie
otwórz GameScene lub LoginScene i naciśnij play. Użyj przycisku logowania edytora
w lewym dolnym rogu.
Jeśli nie możesz uzyskać SOL z devnet, możesz skopiować swój adres z konsoli i postępować zgodnie z instrukcjami zawartymi w tym przewodniku o tym, jak uzyskać devnet SOL
Połączenie z lokalnym środowiskiem testowym validator Solany w Unity
Jeśli chcesz uniknąć konieczności zarządzania SOL z devnet, możesz połączyć się z uruchomionym lokalnym środowiskiem testowym validator z poziomu Unity. Wystarczy dodać te linki do obiektu gry wallet holder:
http://localhost:8899ws://localhost:8900
Uruchamianie klienta JavaScript
Aby uruchomić klienta JavaScript i móc wchodzić w interakcję z grą i programem przez przeglądarkę internetową:
- otwórz katalog
appw repozytorium - zainstaluj zależności Node
- uruchom polecenie
dev, aby uruchomić serwer deweloperski
cd appyarn installyarn dev
Aby zacząć modyfikować program i połączyć się z własnym programem, wykonaj poniższe kroki.
Is this page helpful?