Создание классического децентрализованного приложения Web3 NFT Minting с помощью React и Solidity: часть 1

Создание классического децентрализованного приложения Web3 NFT Minting с помощью React и Solidity: часть 1

4 апреля 2022 г.

Что вы будете создавать: см. [живую демонстрацию] (https://adulam-nft.web.app/) и [репозиторий GitHub] (https://github.com/Daltonic/adulamNFT) для получения дополнительной информации, не Не забудьте отметить проект звездочкой.


Введение


Мир разработки программного обеспечения, каким вы его знаете, изменился, как и спрос на новые навыки. Революция Web3 осталась с экспоненциальным ростом, зарегистрированным в различных секторах разработки программного обеспечения.


Адулам


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


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


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


В этом уроке вы узнаете следующее:


  • Как настроить безошибочный проект Web3.

  • Как кодировать смарт-контракт NFT Minting.

  • Как закодировать интерфейс для чеканки NFT с помощью Tailwind CSS.

  • Как использовать Truffle и Ganache CLI для разработки блокчейна.

  • Как развернуть смарт-контракт.

  • Как писать тесты для ваших смарт-контрактов.

  • Как писать сценарии для смарт-контрактов.

  • Еще больше…

Оставайтесь на связи, потому что нас ждет небольшая поездка…


Обязательное условие


Для прохождения этого урока вам понадобится следующее:


  • NodeJs установлен на вашем компьютере.

  • Установлен [менеджер пакетов Yarn] (https://classic.yarnpkg.com/en/docs/install#windows-stable).


  • [Ganache-CLI] (https://docs.nethereum.com/en/latest/ethereum-and-clients/ganache-cli/) установлен.

  • И непреклонное отношение к изучению Web3.

Существует не так много уроков, чтобы правильно провести вас через этот толстый мир Web3. Вскоре я выпущу несколько курсов, которые помогут вам получить прибыль в качестве разработчика блокчейна, так что будьте осторожны. Вы также можете связаться со мной для получения уроков…


Установка зависимостей приложений


Чтобы сэкономить ваше время и избежать болезненных переживаний при настройке проекта Web3, я подготовил для вас [стартовый набор в моем репозитории git] (https://github.com/Daltonic/tailwind_truffle_starter_kit). Клонируйте и установите зависимости, следуя инструкциям ниже. Пожалуйста, не забудьте оставить звезду на проекте.


На своем терминале перейдите к местоположению вашего проекта и запустите код ниже:


``` ударить


Убедитесь, что у вас уже установлены указанные выше компоненты!


клон git https://github.com/Daltonic/truffle-starter-kit.git adulamNFT


cd adulamNFT # Перейдите к новой папке.


yarn install # Устанавливает все зависимости.


Свободно рекомендую, пожалуйста, используйте vs code для руководства, в нем есть все, что вам нужно для кодирования.


Если вы закончили с этим, давайте перейдем к следующему шагу…


Кодирование смарт-контракта


Откройте проект в коде VS, перейдите в каталог src >> Contracts, и вы увидите существующий контракт с именем Migration.sol.


Создайте новый контракт Solidity с именем Adulam.sol. Внутри файла определите следующие структуры.


```javascript


// SPDX-идентификатор лицензии: MIT


прочность прагмы >=0,7,0 <0,9,0;


импортировать "./ERC721.sol";


импортировать "./ERC721Enumerable.sol";


импортировать "@openzeppelin/contracts/access/Ownable.sol";


контракт Adulam - ERC721Enumerable, Ownable {


// Коды идут сюда


Мы используем конкретную версию ERC721 для нашего смарт-контракта, допустим, она дает нам преимущество перед более новыми версиями.


Фрагмент кода выше описывает смарт-контракт, унаследовавший некоторые атрибуты, свойства и методы от ERC721. ERC721 — это стандарт смарт-контрактов для написания смарт-контрактов на основе NFT.


Примечание. В Solidity объявление смарт-контракта в вашем коде похоже на объявление класса, они просто похожи, поэтому ваши навыки объектно-ориентированного программирования могут дать вам дополнительное преимущество.


Давайте приступим к остальной части смарт-контракта…


```javascript


// Определение основных переменных...


использование строк для uint256;


сопоставление (строка => uint8) общедоступных существующих URI;


uint256 публичная стоимость = 0,01 эфира;


uint256 public maxSupply = 100;


uint256 общественное питание;


общедоступная строка baseURI;


Мы убеждаемся, что переменная uint256 может вызывать функцию в библиотеке строк. Затем мы создали существующую переменную URIs, которая возвращает 0 или 1, когда в нее передается URI NFT.


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


Наконец, переменная Supply будет отслеживать количество отчеканенных NFT, а baseURI отслеживает расположение нашей папки NFT в IPFS.


```javascript


// Структура события продажи


Событие Распродажа(


идентификатор uint256,


адрес проиндексирован из,


адрес проиндексирован,


стоимость uint256,


строка метаданныхURI,


uint256 метка времени


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


Он будет отслеживать идентификатор токена, адреса покупателя и продавца, стоимость NFT, URI произведения искусства, а также время, когда был приобретен NFT.


```javascript


// Объект продаж NFT


структура ПродажаСтруктура {


идентификатор uint256;


адрес от;


Отправить;


стоимость uint256;


заголовок строки;


строковое описание;


uint256 метка времени;


SaleStruct[] отчеканено;


Эта структура выглядит почти как интерфейсы на TypeScript. Задача этой структуры — помочь нам определить сложные типы данных, где одного типа данных недостаточно для описания наших данных.


Если вы посмотрите на приведенную выше структуру SaleStruct, вы обнаружите, что в ней есть несколько типов данных, таких как uint256, адрес и строка. Solidity упрощает объединение данных благодаря использованию структур.


```javascript


конструктор(


строковая память _name,


строковая память _symbol,


строковая память _baseURI


) ERC721(_имя, _символ) {


предложение = общее предложение();


базовыйURI = _baseURI;


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


```javascript


функция payToMint(


название строки памяти,


описание строковой памяти


) государственная кредиторская задолженность {


// Определяет критерии для создания NFT


require(supply <= maxSupply, "Извините, все NFT отчеканены!");


require(msg.value > 0 ether, "Слишком мало эфира для чеканки!");


require(msg.sender != owner(), "Это не разрешено!");


// Определяет критические математические операции


питание += 1;


URI строковой памяти = concat (Strings.toString (поставка + 1));


существующие URIs[URI] = 1;


sendMoneyTo(владелец(), msg.value);


// Сохраняет созданный NFT в массиве


чеканить.push(


ПродажаСтруктура(


поставка,


сообщение.отправитель,


владелец(),


сообщение.значение,


заглавие,


описание,


block.timestamp


// Выводит информацию о продажах NFT


выпустить Продажа(


поставка,


сообщение.отправитель,


владелец(),


сообщение.значение,


УРИ,


блок.временная метка);


// Отчеканить NFT с помощью метода safeMint ERC721


_safeMint (msg.sender, поставка);


Этот метод payToMint отвечает в основном за пять вещей, в том числе;


  • Получение данных NFT от внешнего интерфейса и передача их смарт-контракту.

  • Проверка соблюдения всех критериев для чеканки NFT.

  • Выполнение математических операций, включая отправку денег на чеканку деплойеру.

  • Включая NFT в отчеканенный массив для дальнейших ссылок.

  • Регистрация сведений о продажах клиенту, а также запись их в сети ethereum.

  • Чеканка NFT с использованием метода _safeMint, унаследованного от ERC721.

```javascript


// возвращает все выпущенные NFT


функция getAllNFTs() возвращает публичное представление (память SalesStruct[]) {


возврат чеканки;


В настоящее время переменная массива, которую мы объявили ранее, отслеживает все созданные NFT. Мы подготовили этот метод для извлечения всех созданных NFT из смарт-контракта, когда мы будем использовать их в React.


```javascript


функция getAnNFTs(


идентификатор токена uint256


) публичное представление возвращает (память SalesStruct) {


вернуть отчеканенный [tokenId - 1];


Этот метод возвращает конкретный объект NFT при вызове. Он извлекает NFT, указав свой tokenId. Поскольку массивы начинают свои индексы с 0, нам нужно вычесть 1 из tokenId, чтобы получить именно тот NFT, который нам нужен.


функция concat(


строка памяти ул


) внутреннее представление возвращает (строковая память) {


возвращаемая строка (abi.encodePacked (baseURI, "", str));


Это внутренний метод, который означает, что он доступен только в этом конкретном смарт-контракте. Мы используем этот метод для присоединения tokenId к baseURI. Это сделано таким образом, чтобы каждый NFT мог указать свое точное местоположение в папке IPFS, находящейся где-то в сети.


```javascript


function sendMoneyTo(адрес, сумма uint256) внутренний {


(логический успех1, ) = подлежащий оплате (кому).вызов {значение: сумма} ("");


требуют (успех1);


Наконец, это еще один внутренний метод, вызываемый только этим смарт-контрактом. Он должен отправить эфиры на указанный адрес. Это функция, которая гарантирует, что деньги, использованные для покупки NFT, будут отправлены владельцу NFT или, в данном случае, установщику.


Это все коды, которые нам понадобятся для нашего смарт-контракта, вот полный фрагмент кода.


```javascript


// SPDX-идентификатор лицензии: MIT


прочность прагмы >=0,7,0 <0,9,0;


импортировать "./ERC721.sol";


импортировать "./ERC721Enumerable.sol";


импортировать "@openzeppelin/contracts/access/Ownable.sol";


контракт Adulam - ERC721Enumerable, Ownable {


использование строк для uint256;


сопоставление (строка => uint8) общедоступных существующих URI;


uint256 публичная стоимость = 0,01 эфира;


uint256 public maxSupply = 100;


uint256 общественное питание;


общедоступная строка baseURI;


Событие Распродажа(


идентификатор uint256,


адрес проиндексирован из,


адрес проиндексирован,


стоимость uint256,


строка метаданныхURI,


uint256 метка времени


структура ПродажаСтруктура {


идентификатор uint256;


адрес от;


Отправить;


стоимость uint256;


заголовок строки;


строковое описание;


uint256 метка времени;


SaleStruct[] отчеканено;


конструктор(


строковая память _name,


строковая память _symbol,


строковая память _baseURI


) ERC721(_имя, _символ) {


предложение = общее предложение();


базовыйURI = _baseURI;


function payToMint(строковое название памяти, строковое описание памяти) public payable {


require(supply <= maxSupply, "Извините, все NFT отчеканены!");


require(msg.value > 0 ether, "Слишком мало эфира для чеканки!");


require(msg.sender != owner(), "Это не разрешено!");


питание += 1;


URI строковой памяти = concat (Strings.toString (поставка + 1));


существующие URIs[URI] = 1;


sendMoneyTo(владелец(), msg.value);


чеканить.push(


ПродажаСтруктура(


поставка,


сообщение.отправитель,


владелец(),


сообщение.значение,


заглавие,


описание,


block.timestamp


выпустить продажу (предложение, msg.sender, owner(), msg.value, URI, block.timestamp);


_safeMint (msg.sender, поставка);


функция getAllNFTs() возвращает публичное представление (память SalesStruct[]) {


возврат чеканки;


функция getAnNFTs (uint256 tokenId) возвращает публичное представление (память SalesStruct) {


вернуть отчеканенный [tokenId - 1];


функция concat(string memory str) возвращает внутреннее представление (string memory) {


возвращаемая строка (abi.encodePacked (baseURI, "", str));


function sendMoneyTo(адрес, сумма uint256) внутренний {


(логический успех1, ) = подлежащий оплате (кому).вызов {значение: сумма} ("");


требуют (успех1);


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


Настройка файла миграции


Давайте создадим сценарий миграции в папке migrations, прежде чем мы начнем тестировать смарт-контракт.


Папка миграции


Перейдите в папку миграции и создайте новый файл с именем 2_deploy_contracts.js. Вставьте следующие коды в файл 2_deploy_contracts.js.


```javascript


const Адулам = артефакты.require('Адулам')


module.exports = асинхронная функция (развертывание) {


const BASEURI = https://bafybeidfpvjszubegtoomoknmc7zcqnay7noteadbwxktw46guhdeqohrm.ipfs.infura-ipfs.io/


await deployer.deploy(Adulam, 'Adulam', 'ADU', BASEURI)


Эта конфигурация сделает это. И… да, вы можете использовать мою коллекцию произведений искусства NFT IPFS URI.


Тестирование смарт-контракта


Запустите Ganache и убедитесь, что он работает. Запустите команду ниже на терминале.


```javascript


npm install -g ganache-cli #Пропустить, если он уже установлен


ganache-cli -a #раскручивает сервер блокчейна



Затем найдите папку test и создайте файл с именем Adulam.test.js.


Вставьте фрагмент кода внутрь него.


```javascript


const Адулам = артефакты.require('Адулам')


требовать ('чай'). использовать (требовать ('чай-как-обещано')). должен ()


const toWei = (число) => web3.utils.toWei (num.toString())


const fromWei = (число) => web3.utils.fromWei (num.toString())


const EVM_REVERT = 'Исключение виртуальной машины при обработке транзакции: отменить'


контракт('Адулам', ([развертыватель, покупатель1]) => {


постоянная СТОИМОСТЬ = toWei (0,01)


const _NAME = 'Адулам'


константа _SYMBOL = 'АДУ'


константа _BASE_URI =


'https://bafybeidfpvjszubegtoomoknmc7zcqnay7noteadbwxktw46guhdeqohrm.ipfs.infura-ipfs.io/'


const TITLE = 'Душа Маккалоу'


const ОПИСАНИЕ =


«разрабатывать эффективные решения с помощью этого NFT, созданного для открытого ключа»


пусть адулам, результат


перед каждым (асинхронный () => {


adulam = await Adulam.new(_NAME, _SYMBOL, _BASE_URI)


описать('развертывание', () => {


it('подтверждает имя NFT', async () => {


результат = ожидание adulam.name()


результат.должен.равно(_ИМЯ)


it('подтверждает символ NFT', async () => {


результат = ожидание adulam.symbol()


результат.должен.равный(_SYMBOL)


it('подтверждает NFT baseURI', async () => {


результат = ожидание adulam.baseURI()


результат. должен. равен (_BASE_URI)


it('подтверждает владельца NFT', async () => {


результат = ожидание adulam.owner()


result.should.equal (развертыватель)


it('подтверждает стоимость монетного двора NFT', async () => {


результат = ожидание adulam.cost()


результат.toString().should.equal(СТОИМОСТЬ)


описать('Чеканка', () => {


описать('Успех', () => {


перед каждым (асинхронный () => {


результат = ожидание adulam.payToMint(НАЗВАНИЕ, ОПИСАНИЕ, {


от: покупатель1,


значение: СТОИМОСТЬ,


it('Подтверждает, что покупатель владеет выпущенным токеном', async () => {


результат = ожидание adulam.ownerOf(1)


результат.должен.равный(покупатель1)


it('Подтверждает увеличение предложения на 1', async () => {


результат = ожидание adulam.supply()


результат.toString().should.equal('1')


it('Возвращает массив NFT', async () => {


результат = ожидание adulam.getAllNFTs()


результат.length.toString().should.equal('1')


it('Возвращает объект NFT', async () => {


результат = ожидание adulam.getAnNFTs(1)


результат.length.toString().should.equal('7')


описать('Ошибка', () => {


it('Предотвращает монетный двор со значением 0', async () => {


ждать адулам


.payToMint (НАЗВАНИЕ, ОПИСАНИЕ, {от: покупатель1, значение: 0})


.should.be.rejectedWith(EVM_REVERT)


it('Предотвращает минтинг развертывателем', async () => {


ждать адулам


.payToMint (НАЗВАНИЕ, ОПИСАНИЕ, { от: deployer, значение: СТОИМОСТЬ })


.should.be.rejectedWith(EVM_REVERT)


Теперь запустите тестовый скрипт, используя приведенную ниже команду.


трюфельный тест


Результат должен выглядеть так, как показано ниже.


Тестовые примеры


Предыдущий тест предназначен для того, чтобы убедиться, что наш смарт-контракт может продавать NFT. Написание скрипта для взаимодействия с вашим смарт-контрактом — это дополнительная мера предосторожности, обеспечивающая его правильную работу. Давайте начнем.


Взаимодействие со смарт-контрактом


Это наиболее эффективный метод проверки функциональности вашего смарт-контракта. Мы хотели бы создать скрипт, моделирующий процесс продажи.


Перейдите в папку скриптов и создайте файл с именем BuyNFT.js. Затем вставьте в него следующие коды.


```javascript


const Адулам = артефакты.require('Адулам')


const toWei = (число) => web3.utils.toWei (num.toString())


const fromWei = (число) => web3.utils.fromWei (num.toString())


module.exports = асинхронный (обратный вызов) => {


const [развертыватель, покупатель1] = ожидание web3.eth.getAccounts()


постоянная СТОИМОСТЬ = toWei (0,01)


const TITLE = 'Душа Маккалоу'


const ОПИСАНИЕ =


«разрабатывать эффективные решения с помощью этого NFT, созданного для открытого ключа»


const adulam = ожидание Adulam.deployed()


let deployerBal = await web3.eth.getBalance (развертчик)


пусть покупатель1Бал = ожидание web3.eth.getBalance(покупатель1)


console.log(


`Начальный баланс развертывателя | ${web3.utils.fromWei(


deployerBal.toString(),


'эфир'


console.log(


`Начальный баланс покупателя1 | ${web3.utils.fromWei(


покупатель1Bal.toString(),


'эфир'


)}
`


console.log(Выпуск NFT для покупателя1...<br>)


await adulam.payToMint (НАЗВАНИЕ, ОПИСАНИЕ, { от: покупатель1, значение: СТОИМОСТЬ })


console.log(Баланс после минтинга NFT!<br>)


deployerBal = await web3.eth.getBalance(развертчик)


покупатель1Бал = ожидание web3.eth.getBalance(покупатель1)


console.log(


`Более поздний баланс развертывателя | ${web3.utils.fromWei(


deployerBal.toString(),


'эфир'


console.log(


`Более поздний баланс покупателя1 | ${web3.utils.fromWei(


покупатель1Bal.toString(),


'эфир'


console.log(Информация о новом токене!<br>)


постоянный баланс = ожидание adulam.balanceOf (покупатель1)


console.log(У Покупателя1 есть токены ${balance}...<br>)


Перезвоните()


Отлично, теперь запустите следующую команду на терминале после того, как вы создали и вставили приведенные выше коды. Убедитесь, что ваш ganache-CLI все еще работает, прежде чем запускать приведенный ниже код.


трюфель мигрировать --reset



Обратите внимание на следующий результат на вашем терминале.


Если вы зашли так далеко, поздравляем! Запустим скрипт BuyNFT, введя этот код в терминал.


``` ударить


скрипты truffle exec/BuyNFT.js


Вы должны воспроизвести процесс чеканки на терминале…


Мы можем быть счастливы, что наш смарт-контракт работает. Давайте развернем его в тестовой сети rinkeby.


Развертывание в Алхимию


Разработка и развертывание блокчейна Alchemy


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


Зарегистрируйтесь сейчас или войдите, если у вас уже есть учетная запись.


Страница аутентификации


Когда вы войдете в систему, вы увидите страницу панели инструментов, которая позволяет вам создать новое приложение блокчейна.


Панель управления алхимией


Создание приложения для алхимии


Нажмите кнопку СОЗДАТЬ ПРИЛОЖЕНИЕ и введите информацию, показанную на изображении ниже, обязательно включив сеть теста Ринкеби.


Создать всплывающее окно нового приложения


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


Создано приложение


Скопируйте URL-адрес WSS, как показано на изображении ниже, нажав кнопку VIEW KEY.


Конечная точка веб-сокета


Удивительно, теперь действуйте, как показано на изображениях ниже, чтобы получить свою учетную запись Rinkeby. Пожалуйста, имейте в виду, что мы используем не обычный адрес учетной записи, а закрытый ключ к этой учетной записи.


Шаг первый


Шаг второй


Шаг третий


Шаг четвертый


``` ударить


ENDPOINT_URL=<ВАШ_ALCHEMY_WSS_URL>


SECRET_KEY=<ВАША_METAMASK_SECRET_PHRASE>


DEPLOYER_KEY=<ВАШ_МЕТАМАСК_ЧАСТНЫЙ_КЛЮЧ>


Пожалуйста, не используйте свои настоящие детали метамаски; эти ключи должны храниться в секрете. Вот почему мы помещаем их в файл среды и говорим git игнорировать их.


После того, как вы ввели вышеуказанные ключи в соответствующие переменные, выполните приведенные ниже команды.


``` ударить


truffle migrate --reset --network rinkeby


Как мы видим ниже, ваш смарт-контракт будет развернут в тестовой сети Rinkeby.


Компиляция смарт-контракта


Вы очень много работали, чтобы добраться до этого момента. Вы только что завершили развертывание привлекательного смарт-контракта в сети блокчейна Ethereum. Во ВТОРОЙ ЧАСТИ этого руководства мы подключим его к внешнему интерфейсу ReactJs.


Заключение


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


Индустрия Web3 находится на подъеме, но не так много руководств, которые разбираются в этом, чтобы помочь вам. Вам придется много расчищать путь, прежде чем вы сможете проложить дорогу для себя. К счастью, вам не нужно делать все это самостоятельно, вы можете связаться со мной для личного занятия с репетитором. В настоящее время он ограничен лишь небольшой частью студентов.


До следующего раза!


Об авторе


Госпел Дарлингтон начал свой путь в качестве инженера-программиста в 2016 году. За эти годы он приобрел полноценные навыки работы со стеками JavaScript, такими как React, ReactNative, VueJs, а теперь и с блокчейном.


В настоящее время он работает фрилансером, создает приложения для клиентов и пишет технические руководства, обучая других тому, что делает он.


Евангелие в Дарлингтоне открыто и доступно для вас. Вы можете связаться с ним на LinkedIn, Facebook, Github или на его веб-сайте.



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE