Перейти к основному контенту

Как написать и развернуть NFT (Часть 1/3 серии руководств по NFT)

ERC-721
Alchemy
Solidity
смарт-контракты
Для начинающих
Суми Мудгил
22 апреля 2021 г.
12 минут на чтение

Поскольку NFT привлекают внимание общественности к блокчейну, сейчас отличная возможность самостоятельно разобраться в этой шумихе, опубликовав свой собственный контракт NFT (токен ERC-721) в блокчейне Эфириума!

Alchemy невероятно гордится тем, что поддерживает крупнейшие имена в пространстве NFT, включая Makersplace (недавно установившую рекорд продаж цифровых произведений искусства на Christie’s за 69 миллионов долларов), Dapper Labs (создателей NBA Top Shot и Crypto Kitties), OpenSea (крупнейший в мире маркетплейс NFT), Zora, Super Rare, NFTfi, Foundation, Enjin, Origin Protocol, Immutable и другие.

В этом руководстве мы рассмотрим создание и развертывание смарт-контракта ERC-721 в тестовой сети Sepolia с использованием МетаМаск (opens in a new tab), Solidity (opens in a new tab), Hardhat (opens in a new tab), Pinata (opens in a new tab) и Alchemy (opens in a new tab) (не волнуйтесь, если вы пока не понимаете, что все это значит — мы все объясним!).

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

И, конечно же, если у вас возникнут вопросы на любом этапе, не стесняйтесь обращаться в Дискорд Alchemy (opens in a new tab) или посетите документацию по API NFT от Alchemy (opens in a new tab)!

Шаг 1: Подключение к сети Эфириума

Существует множество способов делать запросы к блокчейну Эфириума, но для простоты мы будем использовать бесплатный аккаунт на Alchemy (opens in a new tab) — платформе для разработчиков блокчейна и API, которая позволяет нам взаимодействовать с цепью Эфириума без необходимости запускать собственные узлы.

В этом руководстве мы также воспользуемся инструментами разработчика Alchemy для мониторинга и аналитики, чтобы понять, как технически работает развертывание нашего смарт-контракта. Если у вас еще нет аккаунта Alchemy, вы можете бесплатно зарегистрироваться здесь (opens in a new tab).

Шаг 2: Создание приложения (и ключа API)

После создания аккаунта Alchemy вы можете сгенерировать ключ API, создав приложение. Это позволит нам делать запросы к тестовой сети Sepolia. Ознакомьтесь с этим руководством (opens in a new tab), если хотите узнать больше о тестовых сетях.

  1. Перейдите на страницу «Create App» (Создать приложение) на панели управления Alchemy, наведя курсор на «Apps» (Приложения) на панели навигации и нажав «Create App».

Create your app

  1. Дайте название вашему приложению (мы выбрали «My First NFT!»), добавьте краткое описание, выберите «Ethereum» в качестве цепи (Chain) и «Sepolia» в качестве вашей сети. После Слияния другие тестовые сети были объявлены устаревшими.

Configure and publish your app

  1. Нажмите «Create app», и все готово! Ваше приложение должно появиться в таблице ниже.

Шаг 3: Создание аккаунта Эфириума (адреса)

Нам нужен аккаунт Эфириума для отправки и получения транзакций. В этом руководстве мы будем использовать МетаМаск — виртуальный кошелек в браузере, используемый для управления адресом вашего аккаунта Эфириума. Если вы хотите больше узнать о том, как работают транзакции в Эфириуме, ознакомьтесь с этой страницей от Фонда Ethereum.

Вы можете бесплатно скачать и создать аккаунт МетаМаск здесь (opens in a new tab). При создании аккаунта или если он у вас уже есть, обязательно переключитесь на «Sepolia Test Network» в правом верхнем углу (чтобы мы не имели дело с реальными деньгами).

Set Sepolia as your network

Шаг 4: Добавление эфира из крана

Чтобы развернуть наш смарт-контракт в тестовой сети, нам понадобится немного тестовых ETH. Чтобы получить ETH, вы можете перейти в кран Sepolia (opens in a new tab), размещенный на Alchemy, войти в систему, ввести адрес своего аккаунта и нажать «Send Me ETH». Вскоре после этого вы должны увидеть ETH в своем аккаунте МетаМаск!

Шаг 5: Проверка баланса

Чтобы убедиться, что наш баланс на месте, давайте сделаем запрос eth_getBalance (opens in a new tab) с помощью инструмента песочницы Alchemy (opens in a new tab). Это вернет количество ETH в нашем кошельке. После того как вы введете адрес своего аккаунта МетаМаск и нажмете «Send Request», вы должны увидеть ответ вроде этого:

{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"}

Примечание Этот результат указан в Wei, а не в ETH. Wei используется как наименьшая единица измерения эфира. Конвертация из Wei в ETH: 1 ETH = 1018 Wei. Поэтому, если мы переведем 0xde0b6b3a7640000 в десятичную систему, мы получим 1*1018 Wei, что равно 1 ETH.

Фух! Наши ненастоящие деньги на месте.

Шаг 6: Инициализация нашего проекта

Сначала нам нужно создать папку для нашего проекта. Перейдите в командную строку и введите:

mkdir my-nft cd my-nft

Теперь, когда мы находимся внутри папки нашего проекта, мы будем использовать npm init для инициализации проекта. Если у вас еще не установлен npm, следуйте инструкциям по установке Node.js (opens in a new tab) (нам понадобятся Node.js и npm для этого руководства).

npm init

Не имеет особого значения, как вы ответите на вопросы при установке; вот как мы это сделали для справки:

Одобрите package.json, и мы готовы к работе!

Шаг 7: Установка Hardhat (opens in a new tab)

Hardhat — это среда разработки для компиляции, развертывания, тестирования и отладки вашего программного обеспечения для Эфириума. Она помогает разработчикам при создании смарт-контрактов и децентрализованных приложений (dapp) локально перед развертыванием в рабочей цепи.

Внутри нашего проекта my-nft выполните:

npm install --save-dev hardhat

Ознакомьтесь с этой страницей для получения более подробной информации об инструкциях по установке (opens in a new tab).

Шаг 8: Создание проекта Hardhat

Внутри папки нашего проекта выполните:

npx hardhat

Затем вы должны увидеть приветственное сообщение и возможность выбрать, что вы хотите сделать. Выберите «create an empty hardhat.config.js»:

888 888 888 888 888 888 888 888 888 888 888 888 888 888 888 8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 888 888 "88b 888P" d88" 888 888 "88b "88b 888 888 888 .d888888 888 888 888 888 888 .d888888 888 888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. 888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 👷 Welcome to Hardhat v2.0.11 👷‍ ? What do you want to do? … Create a sample project ❯ Create an empty hardhat.config.js Quit

Это сгенерирует для нас файл hardhat.config.js, в котором мы укажем все настройки для нашего проекта (на шаге 13).

Шаг 9: Добавление папок проекта

Чтобы поддерживать порядок в нашем проекте, мы создадим две новые папки. Перейдите в корневой каталог вашего проекта в командной строке и введите:

mkdir contracts mkdir scripts

  • contracts/ — здесь мы будем хранить код нашего смарт-контракта NFT.

  • scripts/ — здесь мы будем хранить скрипты для развертывания и взаимодействия с нашим смарт-контрактом.

Шаг 10: Написание контракта

Теперь, когда наша среда настроена, перейдем к более интересному: написанию кода нашего смарт-контракта!

Откройте проект my-nft в вашем любимом редакторе (нам нравится VSCode (opens in a new tab)). Смарт-контракты пишутся на языке под названием Solidity, который мы и будем использовать для написания нашего смарт-контракта MyNFT.sol.‌

  1. Перейдите в папку contracts и создайте новый файл с именем MyNFT.sol.

  2. Ниже приведен код нашего смарт-контракта NFT, который мы основали на реализации ERC-721 из библиотеки ОпенЗеппелин (opens in a new tab). Скопируйте и вставьте содержимое ниже в ваш файл MyNFT.sol.

  3. Поскольку мы наследуем классы из библиотеки контрактов ОпенЗеппелин, в командной строке выполните npm install @openzeppelin/contracts^4.0.0, чтобы установить библиотеку в нашу папку.

Итак, что именно делает этот код? Давайте разберем его построчно.

В начале нашего смарт-контракта мы импортируем три класса смарт-контрактов ОпенЗеппелин (opens in a new tab):

  • @openzeppelin/contracts/token/ERC721/ERC721.sol содержит реализацию стандарта ERC-721, которую унаследует наш смарт-контракт NFT. (Чтобы быть действительным NFT, ваш смарт-контракт должен реализовывать все методы стандарта ERC-721). Чтобы узнать больше об унаследованных функциях ERC-721, ознакомьтесь с определением интерфейса здесь (opens in a new tab).

  • @openzeppelin/contracts/utils/Counters.sol предоставляет счетчики, которые могут быть увеличены или уменьшены только на единицу. Наш смарт-контракт использует счетчик для отслеживания общего количества NFT, которые мы чеканим, и установки уникального идентификатора для нашего нового NFT. (Каждому NFT, который мы чеканим с помощью смарт-контракта, должен быть присвоен уникальный идентификатор — здесь наш уникальный идентификатор просто определяется общим количеством существующих NFT. Например, первый NFT, который мы чеканим с помощью нашего смарт-контракта, имеет идентификатор «1», второй NFT имеет идентификатор «2» и т. д.).

  • @openzeppelin/contracts/access/Ownable.sol настраивает контроль доступа (opens in a new tab) в нашем смарт-контракте, поэтому только владелец смарт-контракта (вы) может чеканить NFT. (Обратите внимание, что включение контроля доступа — это исключительно вопрос предпочтений. Если вы хотите, чтобы кто угодно мог чеканить NFT с помощью вашего смарт-контракта, удалите слово Ownable в строке 10 и onlyOwner в строке 17).

После операторов импорта у нас идет наш пользовательский смарт-контракт NFT, который на удивление короткий — он содержит только счетчик, конструктор и одну функцию! Это благодаря нашим унаследованным контрактам ОпенЗеппелин, которые реализуют большинство методов, необходимых нам для создания NFT, таких как ownerOf, который возвращает владельца NFT, и transferFrom, который передает право собственности на NFT от одного аккаунта другому.

В нашем конструкторе ERC-721 вы заметите, что мы передаем 2 строки: «MyNFT» и «NFT». Первая переменная — это имя смарт-контракта, а вторая — его символ. Вы можете назвать каждую из этих переменных как пожелаете!

Наконец, у нас есть функция mintNFT(address recipient, string memory tokenURI), которая позволяет нам чеканить NFT! Вы заметите, что эта функция принимает две переменные:

  • address recipient указывает адрес, на который будет получен ваш свежеотчеканенный NFT.

  • string memory tokenURI — это строка, которая должна указывать на JSON-документ, описывающий метаданные NFT. Метаданные NFT — это то, что действительно оживляет его, позволяя ему иметь настраиваемые свойства, такие как имя, описание, изображение и другие атрибуты. Во второй части этого руководства мы опишем, как настроить эти метаданные.

mintNFT вызывает некоторые методы из унаследованной библиотеки ERC-721 и в конечном итоге возвращает число, которое представляет собой идентификатор свежеотчеканенного NFT.

Шаг 11: Подключение МетаМаск и Alchemy к вашему проекту

Теперь, когда мы создали кошелек МетаМаск, аккаунт Alchemy и написали наш смарт-контракт, пришло время соединить их вместе.

Каждая транзакция, отправленная с вашего виртуального кошелька, требует подписи с использованием вашего уникального приватного ключа. Чтобы предоставить нашей программе это разрешение, мы можем безопасно хранить наш приватный ключ (и ключ API Alchemy) в файле среды.

Чтобы узнать больше об отправке транзакций, ознакомьтесь с этим руководством по отправке транзакций с использованием Web3.

Сначала установите пакет dotenv в каталоге вашего проекта:

npm install dotenv --save

Затем создайте файл .env в корневом каталоге нашего проекта и добавьте в него свой приватный ключ МетаМаск и HTTP URL API Alchemy.

  • Следуйте этим инструкциям (opens in a new tab), чтобы экспортировать свой приватный ключ из МетаМаск.

  • См. ниже, чтобы получить HTTP URL API Alchemy и скопировать его в буфер обмена.

Copy your Alchemy API URL

Ваш .env теперь должен выглядеть так:

API_URL="https://eth-sepolia.g.alchemy.com/v2/your-api-key (opens in a new tab)" PRIVATE_KEY="your-metamask-private-key"

Чтобы фактически подключить их к нашему коду, мы сошлемся на эти переменные в нашем файле hardhat.config.js на шаге 13.

Не коммитьте .env! Пожалуйста, убедитесь, что вы никогда не делитесь и не раскрываете свой файл .env кому-либо, так как тем самым вы ставите под угрозу свои секретные данные. Если вы используете систему контроля версий, добавьте ваш .env в файл gitignore (opens in a new tab).

Шаг 12: Установка Ethers.js

Ethers.js — это библиотека, которая упрощает взаимодействие и выполнение запросов к Эфириуму, оборачивая стандартные методы JSON-RPC в более удобные для пользователя методы.

Hardhat позволяет очень легко интегрировать плагины (opens in a new tab) для дополнительных инструментов и расширенной функциональности. Мы воспользуемся плагином Ethers (opens in a new tab) для развертывания контракта (в Ethers.js (opens in a new tab) есть несколько очень понятных методов развертывания контрактов).

В каталоге вашего проекта введите:

npm install --save-dev @nomiclabs/hardhat-ethers ethers@^5.0.0

Нам также потребуется подключить ethers в нашем hardhat.config.js на следующем шаге.

Шаг 13: Обновление hardhat.config.js

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

Обновите ваш hardhat.config.js, чтобы он выглядел так:

Шаг 14: Компиляция контракта

Чтобы убедиться, что все работает, давайте скомпилируем наш контракт. Задача компиляции — одна из встроенных задач Hardhat.

Из командной строки выполните:

npx hardhat compile

Вы можете получить предупреждение о том, что идентификатор лицензии SPDX не указан в исходном файле, но об этом не стоит беспокоиться — надеемся, что все остальное выглядит хорошо! Если нет, вы всегда можете написать в Дискорд Alchemy (opens in a new tab).

Шаг 15: Написание скрипта развертывания

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

Перейдите в папку scripts/ и создайте новый файл с именем deploy.js, добавив в него следующее содержимое:

Hardhat отлично объясняет, что делает каждая из этих строк кода, в своем руководстве по контрактам (opens in a new tab), и мы позаимствовали их объяснения здесь.

const MyNFT = await ethers.getContractFactory("MyNFT");

ContractFactory в Ethers.js — это абстракция, используемая для развертывания новых смарт-контрактов, поэтому MyNFT здесь является фабрикой для экземпляров нашего контракта NFT. При использовании плагина hardhat-ethers экземпляры ContractFactory и Contract по умолчанию подключаются к первому подписанту.

const myNFT = await MyNFT.deploy();

Вызов deploy() для ContractFactory запустит развертывание и вернет Promise, который разрешается в Contract. Это объект, который имеет метод для каждой из функций нашего смарт-контракта.

Шаг 16: Развертывание контракта

Мы наконец-то готовы развернуть наш смарт-контракт! Вернитесь в корень каталога вашего проекта и в командной строке выполните:

npx hardhat --network sepolia run scripts/deploy.js

Затем вы должны увидеть что-то вроде:

Contract deployed to address: 0x4C5266cCc4b3F426965d2f51b6D910325a0E7650

Если мы перейдем в Etherscan сети Sepolia (opens in a new tab) и выполним поиск по адресу нашего контракта, мы должны увидеть, что он был успешно развернут. Если вы не видите его сразу, пожалуйста, подождите немного, так как это может занять некоторое время. Транзакция будет выглядеть примерно так:

View your transaction address on Etherscan

Адрес «From» (От) должен совпадать с адресом вашего аккаунта МетаМаск, а в адресе «To» (Кому) будет указано «Contract Creation» (Создание контракта). Если мы нажмем на транзакцию, мы увидим адрес нашего контракта в поле «To»:

View your contract address on Etherscan

Даааа! Вы только что развернули свой смарт-контракт NFT в цепи Эфириума (в тестовой сети)!

Чтобы понять, как это работает технически, давайте перейдем на вкладку Explorer (Обозреватель) на нашей панели управления Alchemy (opens in a new tab). Если у вас несколько приложений Alchemy, обязательно отфильтруйте их по приложению и выберите «MyNFT».

View calls made “under the hood” with Alchemy’s Explorer Dashboard

Здесь вы увидите несколько вызовов JSON-RPC, которые Hardhat/Ethers сделали для нас в фоновом режиме, когда мы вызвали функцию .deploy(). Здесь стоит выделить два важных вызова: eth_sendRawTransaction — это запрос на фактическую запись нашего смарт-контракта в цепь Sepolia, и eth_getTransactionByHash — это запрос на чтение информации о нашей транзакции по заданному хешу (типичный паттерн при отправке транзакций). Чтобы узнать больше об отправке транзакций, ознакомьтесь с этим руководством по отправке транзакций с использованием Web3.

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