Создайте NFT по протоколу NEAR, используя ржавчину

Введение

NFT или не взаимозаменяемые токены — это уникальные токены со связанными с ними метаданными. NFT нельзя заменить чем-то другим. Их можно купить и как криптовалюты. В этом руководстве мы собираемся создать смарт-контракт для протокола Near, который будет чеканить NFT.

Что такое протокол NEAR?

NEAR Protocol — это новое поколение блокчейна первого уровня, которое решает такие проблемы, как низкая скорость транзакций, ограниченная пропускная способность и плохая совместимость. Он разработан на основе удивительной концепции сегментирования, что означает, что при высокой загрузке сети узлы разбиваются на более мелкие сегменты и выполняются параллельные вычисления на этих сегментах. Эта сеть может масштабироваться при высоком спросе.

Предпосылка

Для создания ближнего смарт-контракта нам нужно.

  • Rust —Rust — это высокопроизводительный язык программирования общего назначения, мы собираемся использовать его для создания смарт-контракта. Есть очень хорошая книга для изучения Rust.
  • Near CLIинтерфейс командной строки для подключения и взаимодействия с ближайшим блокчейном.
  • Near Wallet — Прежде чем начать наш проект, нам нужен ближайший кошелек. Ознакомьтесь с этим руководством по настройке рядом с кошельком.

Настройка

Для начала создайте грузовой проект.

cargo new nft --lib

Перейдите в папку проекта nft, которую вы увидите.
src/lib.rs Здесь мы собираемся написать наш смарт-контракт
Cargo.toml Это наш проект Файл конфигурации

Перейдите к cargo.toml и добавьте

[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
near-sdk = "*"
near-contract-standards = "*"

Начало работы

Давайте начнем с нашего каркаса смарт-контрактов.

use near_sdk::{
    near_bindgen,
    borsh::{self, BorshDeserialize, BorshSerialize}
};
near_sdk::setup_alloc!();
#[near_bindgen]
#[derive(BorshDeserialize, BorshDeserialize)]
pub struct Contract {}
#[near_bindgen]
impl Contract {}

Это выглядит как странный код, и сейчас ничего не делаем, давайте упростим его. NEAR следует подходу с сохранением состояния, поэтому struct Contract будет хранить состояние нашего контракта, а в реализации Contract мы напишем наши функции, которые изменяют состояние.

Здесь следует отметить, что мы реализуем некоторые макросы и получаем черты. макрос #[near_bindgen] преобразует состояние в допустимую форму, чтобы быть активным в цепочке NEAR. BorshDeserialize, BorshDeserialize — трейты из крейта борщ для десериализации и сериализации состояния.

Теперь давайте создадим наше состояние для NFT. Вы знаете, что NFT — это уникальный токен и связанные с ним метаданные. Из этого определения наше состояние выглядит так.

use near_contract_standards::non_fungible_token::{
    metadata::NFTContractMetadata, NonFungibleToken,
};
pub struct Contract {
    token: NonFungibleToken,
    metadata: LazyOption<NFTContractMetadata>,
}

Теперь для этого состояния всегда требуется значение по умолчанию, поэтому нам нужна функция инициализации для установки состояния по умолчанию.

#[derive(BorshSerialize, BorshStorageKey)]
pub enum StorageKey {
    NonFungibleToken,
    Metadata,
    TokenMetadata,
    Enumeration,
    Approval
}
#[near_bindgen]
impl Contract {
    #[init]
    pub fn new(owner_id: ValidAccountId) -> Self {
        Self {
            token: NonFungibleToken::new(
                StorageKey::NonFungibleToken,
                owner_id,
                Some(StorageKey::TokenMetadata),
                Some(StorageKey::Enumeration),
                Some(StorageKey::Approval)
             ),
             metadata: LazyOption::new(
                StorageKey::Metadata,
                Some(&NFTContractMetadata {
                    spec: NFT_METADATA_SPEC.to_string(),
                    name: "Example Name".to_string(),
                    symbol: "Example".to_string(),
                    icon: Some("ANY_SVG".to_string()),
                    base_uri: None,
                    reference: None,
                    reference_hash: None,
                 })
             ),
        }
    }
}

Функция с макросом #[init] всегда будет выполняться первой. Обычно используется для установки состояния по умолчанию. Для стандартов токенов и стандартов метаданных я рекомендую проверить ссылки это и это.

Теперь все настроено для нашего инициализатора и нашего состояния. Давайте сделаем нашу функцию чеканки NFT.

impl Contract {
    
    ......
    
    #[payable]    
    pub fn nft_mint(
        &mut self,
        token_id: TokenId,
        receiver_id: ValidAccountId,
        token_metadata: TokenMetadata,
    ) -> Token {
        self.token.mint(token_id, receiver_id, Some(token_metadata))
    }
}

Давайте развернем это в цепочке. Запустите эту команду, чтобы сделать сборку:

cargo build --target wasm32-unknown-unknown --release

Запустите эту команду для развертывания:

near deploy --wasmFile target/wasm32-unknown-unknown/release/nft.wasm --accountId "your near account username"

Это вернет идентификатор программы, который можно использовать для вызова RPC смарт-контракта. Вы можете использовать рядом CLI или клиент javascript для взаимодействия с контрактом.