За допомогою Token Extension program ви можете створювати NFT та цифрові активи, використовуючи розширення метаданих. Разом ці розширення (metadata pointer та token metadata) дозволяють розміщувати будь-які потрібні метадані безпосередньо в блокчейні. Все це зберігається в налаштовуваному сховищі даних у форматі ключ-значення прямо на token's mint account, що знижує витрати та складність.
Це може бути особливо корисно для web3-ігор, оскільки тепер ми можемо мати ці «додаткові поля метаданих» в onchain-сховищі ключ-значення, що дозволяє іграм зберігати та отримувати унікальний стан безпосередньо в NFT (наприклад, статистику чи інвентар ігрового персонажа).
Розробка onchain-програми
У цьому посібнику для розробників ми покажемо, як створювати NFT на основі Token Extension та користувацькі метадані за допомогою програми Anchor. Ця програма зберігатиме рівень та зібрані ресурси гравця у NFT.
Цей NFT створюватиметься програмою Anchor, тому його дуже легко карбувати з JavaScript-клієнта. Кожен NFT матиме базову структуру, надану через інтерфейс Token Metadata:
- стандартні onchain-поля —
name,symbolтаuriuri— це посилання на offchain json-файл, який містить offchain- метадані NFT
- також ми матимемо користувацькі «додаткові поля», які визначаємо самостійно
Усі ці поля зберігаються за допомогою розширення метаданих, яке вказує на mint account NFT, що робить їх доступними для будь-кого або будь-якої програми.
Відео та вихідний код
Ви можете знайти відеоогляд цього прикладу на YouTube-каналі Solana Foundation:
Інші варіанти використання в іграх
Такі NFT з налаштовуваними onchain-метаданими відкривають безліч цікавих можливостей для розробників ігор. Особливо з огляду на те, що цими метаданими можна безпосередньо взаємодіяти або керувати за допомогою onchain-програми.
Деякі з цих ігрових варіантів використання включають:
- збереження рівня та досвіду (XP) гравця
- поточна зброя та броня
- поточний квест
- і це ще не все!
Карбування NFT
Для створення NFT необхідно виконати такі кроки:
- Створити mint account
- Ініціалізувати mint account
- Створити обліковий запис вказівника метаданих
- Ініціалізувати обліковий запис вказівника метаданих
- Створити обліковий запис метаданих
- Ініціалізувати обліковий запис метаданих
- Створити associated token account
- Карбувати токен до associated token account
- Заморозити повноваження карбування
Код програми на Rust
Ось код на Rust для карбування NFT з використанням Token Extensions Program:
// 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,)?;
Код JavaScript-клієнта
Виклик карбування NFT з клієнта дуже простий:
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-клієнт для цієї гри, а також конфігурацію для взаємодії з програмою Solana Anchor.
Ви можете запустити його самостійно за допомогою такої команди:
npx create-solana-game gameName
Налаштування локального середовища
Щоб запустити цей приклад локально, вам необхідно переконатися, що ви налаштували локальне середовище для розробки на Solana, включаючи встановлення та налаштування Anchor CLI. Якщо ви ще не зробили цього, дотримуйтесь раніше згаданого посібника з налаштування.
Структура проєкту
Проєкт Anchor має таку структуру:
Точка входу знаходиться у файлі lib.rs. Тут ми визначаємо ідентифікатор програми та інструкції. Інструкції визначені в папці instructions. Стан визначений у папці state.
Таким чином, виклики надходять до файлу lib.rs, а потім перенаправляються до інструкцій. Інструкції звертаються до стану для отримання та оновлення даних.
Інструкцію карбування 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:
cd programдля переходу в директорію програми- Виконайте
anchor buildдля збірки програми - Виконайте
anchor deployдля розгортання програми - Скопіюйте ідентифікатор програми з термінала до
lib.rs,anchor.tomlта у проєкт Unity вAnchorService, а якщо використовуєте JavaScript — до файлуanchor.ts - Виконайте збірку та розгортання знову
NextJS-клієнт
Щоб завершити налаштування NextJS-клієнта, згенерованого інструментом create-solana-game:
- Скопіюйте
programIdдоapp/utils/anchor.ts cd appдля переходу в директорію застосунку- Виконайте
yarn installдля встановлення залежностей Node - Виконайте
yarn devдля запуску клієнта - Після внесення змін до програми Anchor переконайтеся, що ви скопіювали типи
з програми до клієнта для їх використання. TypeScript-типи знаходяться в папці
target/idl.
Запуск прикладу локально
Використання команди test Anchor з прапорцем --detach запустить і налаштує
локальний тестовий validator Solana з розгорнутою програмою (і залишить
validator запущеним після завершення тестів):
cd programanchor test --detach
Потім ви можете налаштувати Solana Explorer для використання вашого
локального тестового validator (який запускається під час виконання команди anchor test), щоб
переглядати транзакції:
https://explorer.solana.com/?cluster=custom&customUrl=http%3A%2F%2Flocalhost%3A8899
Програма також вже розгорнута в мережі, тому ви можете спробувати її на devnet.
JavaScript-клієнт також має кнопку для карбування NFT. Запуск JavaScript-клієнта:
cd appyarn installyarn dev
Відкриття проєкту Unity
Спочатку відкрийте проєкт Unity у Unity Version 2021.3.32.f1 (або подібній), потім
відкрийте GameScene або LoginScene і натисніть «Play». Використовуйте кнопку входу в редакторі
у нижньому лівому куті.
Якщо ви не можете отримати devnet SOL, ви можете скопіювати свою адресу з консолі та дотримуватись інструкцій у цьому посібнику про те, як отримати devnet SOL
Підключення до тестового validator Solana в Unity
Якщо ви хочете уникнути необхідності підтримувати баланс devnet SOL, ви можете підключитися до локального тестового validator безпосередньо з Unity. Просто додайте ці посилання на ігровий об'єкт wallet holder:
http://localhost:8899ws://localhost:8900
Запуск JavaScript-клієнта
Щоб запустити JavaScript-клієнт і мати можливість взаємодіяти з грою та програмою через веб-браузер:
- відкрийте директорію
appу репозиторії - встановіть залежності Node
- виконайте команду
devдля запуску сервера розробки
cd appyarn installyarn dev
Щоб почати змінювати програму та підключатися до власної програми, виконайте наведені нижче кроки.
Is this page helpful?