NFT
April 6, 2023

NFT Pinata в сети Sui.

Недавно мы познакомились с Sui, блокчейном с исключительными функциями, такими как динамические метаданные, и с акцентом на то, чтобы обычные люди могли легко им пользоваться. Я был приятно удивлен тем, насколько плавно и быстро он работал во время практического опыта, конечно не без "шороховатостей", но это тест, нужно учитывать, что он все еще находится в стадии разработки. У Sui определенно есть потенциал стать крупным, полноценным блокчейном в индустрии.

Я заметил, что не хватает базовых объяснений того, как мантить NFT на Sui и как справляться с некоторыми проблемами, которые могут возникнуть, поэтому я хотел поделиться своим опытом и продемонстрировать процесс.

Если вы хотите понять, как получить и иметь собственные NFT, все, что вам действительно нужно, - это базовые инструменты, такие как NodeJS и текстовый редактор, а также некоторые знания Javascript.

Итак начнем.

Чтобы минтить NFT с помощью Pinata, нам понадобится сервис для хранения любого содержимого, например, изображений или видео, которое вы хотите превратить в NFT в сети Sui. Pinata - отличный вариант, поскольку она использует IPFS, которая предотвращает фальсификацию содержимого.

Работать с Pinata очень просто. Сначала посетите страницу регистрации здесь и создайте бесплатный аккаунт. Затем загрузите изображение, которое вы хотите использовать, перейдя на главную страницу файлов и нажав "Загрузить".

Далее выполните следующие шаги: выберите файл, дайте ему имя, и загрузите! После этого он должен появиться на странице файлов, как показано ниже, необходимо скопировать CID для использования в минте NFT.

Легкая часть закончилась, дальше нужно быть внимательней!

Нам потребуеться JS SDK и мы шаг за шагом напишем код с помошью Sui.

Создаем каталог, для того, чтобы там хранился наш проект с кодом.

mkdir sui-nft && cd sui-nft

Установим Sui Javascript SDK.

npm init -y && npm install @mysten/sui.js

Вносим изменение в фаил package.json убедитесь, что ваш package.json выглядит именно так.

{
"name": "sui-nft",
"type": "module",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@mysten/sui.js": "^0.26.1"
}
}

Создаем файл для запуска, который мы назовем mint-nft.js

touch mint-nft.js

Можем приступить к самому главному - написанию кода для минта нашего NFT!

Откройте файл mint-nft.js в текстовом редакторе и импортируйте следующие методы в верхней части страницы.(в одну строку)

import { Ed25519Keypair, JsonRpcProvider, Network, RawSigner } from '@mysten/sui.js';

Далее создаем кошелек и получаем публичный адрес.

import { Ed25519Keypair, JsonRpcProvider, Network, RawSigner } from '@mysten/sui.js';

const keypair = new Ed25519Keypair()
const address = "0x" + keypair.getPublicKey().toSuiAddress().toString()
console.log(address)

Адрес Sui из открытого ключа не включает в себя значение обычное для начала адресов, начиная с "0x", поэтому здесь я добавляю его вручную. Если вы сейчас зайдете в терминал и запустите "node mint-nft.js", то вы должны увидеть адрес, подобный этому!

0x3de227a66b72b6f7ddd73d061ccb69ddd3cbb4e

Получив адрес, можем подключиться к сети Sui и получить тестовые монеты Sui!

1. укажем новый провайдер и используем JsonRpcProvider

2. передадим с подключением сеть "DEVNET".

import { Ed25519Keypair, JsonRpcProvider, Network, RawSigner } from '@mysten/sui.js';

//Create keypair
const keypair = new Ed25519Keypair()
const address = "0x" + keypair.getPublicKey().toSuiAddress().toString()
console.log(address)

//Create network connection
const provider = new JsonRpcProvider(Network.DEVNET);

Можно использовать провайдера для запроса тестовых Sui из крана Devnet и используя наш новый адрес в качестве получателя следующим образом.

import { Ed25519Keypair, JsonRpcProvider, Network, RawSigner } from '@mysten/sui.js';

//Create keypair
const keypair = new Ed25519Keypair()
const address = "0x" + keypair.getPublicKey().toSuiAddress().toString()
console.log(address)

//Create network connection
const provider = new JsonRpcProvider(Network.DEVNET);

// Get Sui from faucet
const fund = await provider.requestSuiFromFaucet(address)
console.log(fund)

Выполним команду node mint-nft.js для проверки и посмотрим, что получим.

0xf64640227ff94ba762252c15f2adbcedb6d3aaab
{
transferred_gas_objects: [
{
amount: 10000000,
id: '0x39c25c3885c2cccea957c26219de9c7e58a33a21',
transfer_tx_digest: '4ETS2rGNzRYZ95SsLrUsQf8ckfZWQSSqTEpGi32RqKbk'
},
{
amount: 10000000,
id: '0x3bdad5c729495d9d152cfd03b0e44e8549972d53',
transfer_tx_digest: '4ETS2rGNzRYZ95SsLrUsQf8ckfZWQSSqTEpGi32RqKbk'
},
{
amount: 10000000,
id: '0x4a748f4e928b974dd46913e2cc069a21fecaad86',
transfer_tx_digest: '4ETS2rGNzRYZ95SsLrUsQf8ckfZWQSSqTEpGi32RqKbk'
},
{
amount: 10000000,
id: '0x66d601ef1811cbdea82d2eb97a0994afdbbc888a',
transfer_tx_digest: '4ETS2rGNzRYZ95SsLrUsQf8ckfZWQSSqTEpGi32RqKbk'
},
{
amount: 10000000,
id: '0xee8668e7c2fcd60047992f170da075dafd955f48',
transfer_tx_digest: '4ETS2rGNzRYZ95SsLrUsQf8ckfZWQSSqTEpGi32RqKbk'
}
],
error: null
}

Хороший результат! Может быть интересно, почему существует 5 разных идентификаторов отправки - получения, (можно так же это заметить, когда требуешь тестовые монеты из оф. крана Sui) но на самом деле это важный аспект модели Sui.

Каждая монета в Sui имеет свой собственный уникальный идентификатор объекта, несмотря на то, что все они относятся к одному типу Sui по умолчанию. Однако наши 5 монет находятся в отдельных группах, что может создать проблемы при попытке использовать наши Sui для чеканки NFT. Это происходит потому, что он попытается взять данные только из одного из этих объектов, в то время как в идеале мы хотим взять данные из всех объектов, как в обычном блокчейне.

Для простоты понимания, допустим, у вас есть ферма с пятью козьими полями, и каждое поле разделено по типу коз: короткошерстные, длинношерстные и т.д. На каждом поле по 100 коз, так что технически у вас 500 коз, но чтобы обменять их на овец, вам нужно 200 коз. Вам придется освободить два поля от коз и объединить их для обмена. По сути, это то, что мы делаем в Sui с монетами.

С учетом этого, объединяем недавно приобретенные нами тестовые Sui.

// Merge two of the Sui coin objects
const coin1 = fund.transferred_gas_objects[0].id
const coin2 = fund.transferred_gas_objects[1].id
const signer = new RawSigner(keypair, provider);
const mergeTxn = await signer.mergeCoin({
primaryCoin: coin1,
coinToMerge: coin2,
gasBudget: 1000,
});
console.log('MergeCoin txn', mergeTxn);

В этих командах мы передали две наши монеты, а также токены на газ.

Прежде чем мы запустим код, есть одна небольшая вещь, которую я упустил. Попытаетесь запустить этот код сейчас, то, скорее всего, получите ошибку, что не удалось найти идентификатор объекта для тестового токена, потому, что монета только что была создана, и мы пытаемся получить доступ к идентификатору объекта, который еще не обнаружен. Чтобы исправить это, мы сделаем небольшую вспомогательную функцию, показано ниже.

// Pause function
const wait = async (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time)
});
}

Давайте используем после получения airdrop токена и сохраним передачу в течении 3-х секунд. Теперь ваш код должен выглядеть примерно так.

import { Ed25519Keypair, JsonRpcProvider, Network, RawSigner } from '@mysten/sui.js';

// Generate a new Keypair
const keypair = new Ed25519Keypair();
const address = "0x" + keypair.getPublicKey().toSuiAddress().toString()
console.log(address)

// Create Network Connection and receive airdrop
const provider = new JsonRpcProvider(Network.DEVNET);

// Get Sui from faucet
const fund = await provider.requestSuiFromFaucet(address)
console.log(fund)

// Pause function
const wait = async (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time)
});
}

await wait(3000)

// Merge two of the Sui coin objects
const coin1 = fund.transferred_gas_objects[1].id
const coin2 = fund.transferred_gas_objects[2].id
const signer = new RawSigner(keypair, provider);
const mergeTxn = await signer.mergeCoin({
primaryCoin: coin1,
coinToMerge: coin2,
gasBudget: 1000,
});
console.log('MergeCoin txn', mergeTxn);

Запустите этот код, увидите результат сброса, потом паузу перед объединением монет и успешное объединение монет! Теперь, когда у нас есть все наши козы, мы можем успешно минтить NFT!

// Call to Mint NFT
const mintTxn = await signer.executeMoveCall({
packageObjectId: '0x2',
module: 'devnet_nft',
function: 'mint',
typeArguments: [],
arguments: [
'gm',
'A nice gm brought to you by Pinata and Sui',
'ipfs://QmZhnkimthxvL32vin2mrQvnhN8ZbWFMvKMxRqHEq7dPz3',
],
gasBudget: 10000
});
console.log('mint transaction:', mintTxn);

По сути мы просто обращаемся к созданному смарт-контракту под названием 'devnet_nft', и используем функцию 'mint'. Далее нам нужно передать в аргументах, название NFT, описание, а затем ссылку на актив!

Сейчас нам необходимо добавить консольный журнал, который позволит нам просматривать НМТ в браузере. Для этого нам сначала нужно получить ID объекта НМТ после минта, а затем передать этот ID ссылкой в Sui explorer. Вот пример фрагмента кода, который демонстрирует этот процесс.

// View NFT
const nftId = mintTxn.effects.effects.created[0].reference.objectId.toString()
console.log(`View NFT: https://explorer.sui.io/object/${nftId}?network=devnet`)

Проверяем полный код, чтобы убедиться, что все хорошо и запустим его!

import { Ed25519Keypair, JsonRpcProvider, Network, RawSigner } from '@mysten/sui.js';

// Generate a new Keypair
const keypair = new Ed25519Keypair();
const address = "0x" + keypair.getPublicKey().toSuiAddress().toString()
console.log(address)

// Create Network Connection and receive airdrop
const provider = new JsonRpcProvider(Network.DEVNET);

// Get Sui from faucet
const fund = await provider.requestSuiFromFaucet(address)
console.log(fund)

// Pause function
const wait = async (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time)
});
}

await wait(3000)

// Merge two of the Sui coin objects
const coin1 = fund.transferred_gas_objects[1].id
const coin2 = fund.transferred_gas_objects[2].id
const signer = new RawSigner(keypair, provider);
const mergeTxn = await signer.mergeCoin({
primaryCoin: coin1,
coinToMerge: coin2,
gasBudget: 1000,
});
console.log('MergeCoin txn', mergeTxn);

// Call to Mint NFT
const mintTxn = await signer.executeMoveCall({
packageObjectId: '0x2',
module: 'devnet_nft',
function: 'mint',
typeArguments: [],
arguments: [
'gm',
'A nice gm brought to you by Pinata and Sui',
'ipfs://QmZhnkimthxvL32vin2mrQvnhN8ZbWFMvKMxRqHEq7dPz3',
],
gasBudget: 10000
});
console.log('mint transaction:', mintTxn);

// View NFT
const nftId = mintTxn.effects.effects.created[0].reference.objectId.toString()
console.log(`View NFT: https://explorer.sui.io/object/${nftId}?network=devnet`)

Если все работает как надо, вы получите ссылку и увидите свой NFT.

Поздровляю вы сминтили NFT на Sui!!!



Discord / Twitter / Website