paint-brush
Как создать портал цифровых предметов коллекционирования, используя поток и ритм (часть 1)к@johnjvester
375 чтения
375 чтения

Как создать портал цифровых предметов коллекционирования, используя поток и ритм (часть 1)

к John Vester20m2024/02/13
Read on Terminal Reader

Слишком долго; Читать

Узнайте больше о блокчейне Flow и языке смарт-контрактов Cadence, создав новый веб-сайт, посвященный сбору цифровых предметов коллекционирования.
featured image - Как создать портал цифровых предметов коллекционирования, используя поток и ритм (часть 1)
John Vester HackerNoon profile picture

В этом уроке мы узнаем, как создать веб-сайт для сбора цифровых предметов коллекционирования (или NFT) на блокчейне Flow. Мы будем использовать язык смарт-контрактов Cadence вместе с React, чтобы все это произошло. Мы также узнаем о Flow, его преимуществах и интересных инструментах, которые мы можем использовать.


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


Давайте погрузимся прямо сейчас!


Что мы строим?

Мы создаем приложение для цифровых предметов коллекционирования. Каждый предмет коллекционирования представляет собой невзаимозаменяемый токен (NFT). (Если вы новичок и не разбираетесь в NFT, посмотрите здесь.) Наше приложение позволит вам собирать NFT, и каждый предмет будет уникальным.


Чтобы все это работало, мы будем использовать стандарт NonFungibleToken от Flow, который представляет собой набор правил, которые помогают нам управлять этими специальными цифровыми элементами (аналогично ERC-721 в Ethereum).

Предварительные условия

Прежде чем начать, обязательно установите Flow CLI в вашей системе. Если вы этого не сделали, следуйте этим инструкциям по установке .

Настройка

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


Эта команда творит за кулисами волшебство, создавая основу вашего проекта. Он создает систему папок и настраивает файл flow.json для настройки вашего проекта, гарантируя, что все организовано и готово к работе!


Структура проекта

Проект будет содержать папку cadence и файл flow.json . (Файл flow.json — это файл конфигурации вашего проекта, который поддерживается автоматически.)

В папке Cadence содержится следующее:

  • /contracts: содержит все контракты Cadence.
  • /scripts: содержит все сценарии Cadence.
  • /transactions: хранит все транзакции Cadence.


Выполните следующие действия, чтобы использовать Flow NFT Standard.

Шаг 1: Создайте файл.

Сначала перейдите в папку flow-collectibles-portal и найдите папку cadence . Затем откройте папку contracts . Создайте новый файл и назовите его NonFungibleToken.cdc .

Шаг 2: Скопируйте и вставьте.

Теперь откройте ссылку NonFungibleToken , содержащую стандарт NFT. Скопируйте все содержимое этого файла и вставьте его в только что созданный новый файл («NonFungibleToken.cdc»).


Вот и все! Вы успешно установили стандарты для своего проекта.

Теперь давайте напишем код!


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


На верхнем уровне наша кодовая база состоит из трех основных компонентов:

  1. NFT: каждый предмет коллекционирования представлен в виде NFT.


  2. Коллекция: Коллекция относится к группе NFT, принадлежащей конкретному пользователю.


  3. Глобальные функции и переменные: это функции и переменные, определенные на глобальном уровне для смарт-контракта и не связанные с каким-либо конкретным ресурсом.

Структура смарт-контракта

Базовая структура смарт-контракта

Создайте новый файл с именем Collectibles.cdc внутри cadence/contracts . Здесь мы будем писать код.


Структура контракта

 import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ pub var totalSupply: UInt64 // other code will come here init(){ self.totalSupply = 0 } }


Разберем код построчно:


  1. Во-первых, нам нужно стандартизировать создание NFT, включив так называемый «NonFungibleToken». Это стандарт NFT, созданный Flow, который определяет следующий набор функций, которые должны быть включены в каждый смарт-контракт NFT.


  2. После импорта давайте создадим наш контракт. Для этого мы используем pub contract [contract name] . Используйте один и тот же синтаксис каждый раз, когда создаете новый контракт. Вы можете указать в contract name то, что вы хотите назвать своим контрактом. В нашем случае назовем это Collectibles .


  3. Далее мы хотим убедиться, что наш контракт соответствует определенному набору функций и правил NonFungibleToken. Для этого мы добавляем интерфейс NonFungibleToken с помощью `:`.
    Вот так ( `pub contract Collectibles: NonFungibleToken{}` )


  4. Каждый контракт ДОЛЖЕН иметь функцию init() . Он вызывается при первоначальном развертывании контракта. Это похоже на то, что Solidity называет конструктором.


  5. Теперь давайте создадим глобальную переменную totalSupply с типом данных UInt64 . Эта переменная будет отслеживать общее количество ваших предметов коллекционирования.


  6. Теперь инициализируйте totalSupply значением 0 .


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


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


Ресурс NFT

Добавьте следующий код в свой смарт-контракт:


 import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ // above code… pub resource NFT: NonFungibleToken.INFT{ pub let id: UInt64 pub var name: String pub var image: String init(_id:UInt64, _name:String, _image:String){ self.id = _id self.name = _name self.image = _image } } // init()... }


Как вы видели ранее, контракт реализует стандартный интерфейс NFT, представленный pub contract Collectibles: NonFungibleToken . Аналогично, ресурсы также могут реализовывать различные интерфейсы ресурсов.


Итак, давайте добавим интерфейс NonFungibleToken.INFT к ресурсу NFT, который требует существования общедоступного свойства с именем id внутри ресурса.

Вот переменные, которые мы будем использовать в ресурсе NFT:


  • id: поддерживает идентификатор NFT.
  • name: Имя NFT.
  • image: URL-адрес изображения NFT.


После определения переменной обязательно инициализируйте ее в функции init() .


Давайте двинемся дальше и создадим еще один ресурс под названием Collection Resource .

Ресурс коллекции

Во-первых, вам необходимо понять, как работают Collection Resources .


Если вам нужно сохранить на ноутбуке музыкальный файл и несколько фотографий, что бы вы сделали?


Обычно вы переходите на локальный диск (скажем, ваш D-Drive) и создаете папку с music и папку photos . Затем вы скопируете и вставите файлы музыки и фотографий в папки назначения.

Точно так же работают ваши цифровые предметы коллекционирования на Flow.


Представьте себе свой ноутбук как Flow Blockchain Account , свой D-Drive как Account Storage и папку как Collection .


Таким образом, при взаимодействии с любым проектом по покупке NFT проект создает свою collection в account storage , аналогично созданию папки на вашем D-Drive. Когда вы взаимодействуете с 10 различными проектами NFT, в вашей учетной записи появится 10 разных коллекций.


Это похоже на личное пространство для хранения и организации ваших уникальных цифровых сокровищ!


 import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ //Above code NFT Resource… // Collection Resource pub resource Collection{ } // Below code… }


Каждая collection имеет переменную ownedNFTs для хранения NFT Resources .


 pub resource Collection { pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init(){ self.ownedNFTs <- {} } }


Ресурсные интерфейсы

Интерфейс resource в Flow похож на интерфейсы в других языках программирования. Он располагается поверх ресурса и гарантирует, что реализующий его ресурс имеет требуемую функциональность, определенную интерфейсом.


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


В стандарте NonFungibleToken существует несколько интерфейсов ресурсов, таких как INFT , Provider , Receiver и CollectionPublic .


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


В этом контракте мы будем использовать эти три интерфейса из NonFungibleToken: Provider , Receiver и CollectionPublic . Эти интерфейсы определяют такие функции, как deposit , withdraw , borrowNFT и getIDs . По ходу дела мы подробно объясним каждый из них.


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


 pub contract Collectibles:NonFungibleToken{ // rest of the code… pub event ContractInitialized() pub event Withdraw(id: UInt64, from: Address?) pub event Deposit(id: UInt64, to: Address?) pub let CollectionStoragePath: StoragePath pub let CollectionPublicPath: PublicPath pub resource interface CollectionPublic{ pub fun deposit(token: @NonFungibleToken.NFT) pub fun getIDs(): [UInt64] pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT } pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init(){ self.ownedNFTs <- {} } } }


Отзывать


Теперь давайте создадим функцию withdraw() , необходимую для интерфейса.


 pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ // other code pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } init()... }


С помощью этой функции вы можете удалить ресурс NFT из коллекции. Если оно:


  • Сбой : Паника и выдает ошибку.


  • Успешно : генерирует событие вывода и возвращает ресурс вызывающей стороне.


Затем вызывающий абонент может использовать этот ресурс и сохранить его в хранилище своей учетной записи.


Депозит

Теперь пришло время функции deposit() необходимой для NonFungibleToken.Receiver .


 pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ // other code pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } pub fun deposit(token: @NonFungibleToken.NFT) { let id = token.id let oldToken <- self.ownedNFTs[id] <-token destroy oldToken emit Deposit(id: id, to: self.owner?.address) } init()... }


Одолжить и получить ID


Теперь давайте сосредоточимся на двух функциях, необходимых NonFungibleToken.CollectionPublic: borrowNFT() и getID() .


 pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ // other code pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } pub fun deposit(token: @NonFungibleToken.NFT) { let id = token.id let oldToken <- self.ownedNFTs[id] <-token destroy oldToken emit Deposit(id: id, to: self.owner?.address) } pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { if self.ownedNFTs[id] != nil { return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)! } panic("NFT not found in collection.") } pub fun getIDs(): [UInt64]{ return self.ownedNFTs.keys } init()... }


Деструктор

Последнее, что нам нужно для ресурса коллекции, — это деструктор.


 destroy (){ destroy self.ownedNFTs }


Поскольку ресурс Collection содержит другие ресурсы (ресурсы NFT), нам необходимо указать деструктор. Деструктор запускается при уничтожении объекта. Это гарантирует, что ресурсы не останутся «бездомными» при уничтожении их родительского ресурса. Нам не нужен деструктор для ресурса NFT, поскольку он не содержит никаких других ресурсов.


Давайте посмотрим на полный исходный код ресурса коллекции:


 import NonFungibleToken from "./NonFungibleToken.cdc" pub contract Collectibles: NonFungibleToken{ pub var totalSupply: UInt64 pub resource NFT: NonFungibleToken.INFT{ pub let id: UInt64 pub var name: String pub var image: String init(_id:UInt64, _name:String, _image:String){ self.id = _id self.name = _name self.image = _image } } pub resource interface CollectionPublic{ pub fun deposit(token: @NonFungibleToken.NFT) pub fun getIDs(): [UInt64] pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT } pub event ContractInitialized() pub event Withdraw(id: UInt64, from: Address?) pub event Deposit(id: UInt64, to: Address?) pub let CollectionStoragePath: StoragePath pub let CollectionPublicPath: PublicPath pub resource Collection: CollectionPublic, NonFungibleToken.Provider, NonFungibleToken.Receiver, NonFungibleToken.CollectionPublic{ pub var ownedNFTs: @{UInt64: NonFungibleToken.NFT} init(){ self.ownedNFTs <- {} } destroy (){ destroy self.ownedNFTs } pub fun withdraw(withdrawID: UInt64): @NonFungibleToken.NFT { let token <- self.ownedNFTs.remove(key: withdrawID) ?? panic("missing NFT") emit Withdraw(id: token.id, from: self.owner?.address) return <- token } pub fun deposit(token: @NonFungibleToken.NFT) { let id = token.id let oldToken <- self.ownedNFTs[id] <-token destroy oldToken emit Deposit(id: id, to: self.owner?.address) } pub fun borrowNFT(id: UInt64): &NonFungibleToken.NFT { if self.ownedNFTs[id] != nil { return (&self.ownedNFTs[id] as &NonFungibleToken.NFT?)! } panic("NFT not found in collection.") } pub fun getIDs(): [UInt64]{ return self.ownedNFTs.keys } } init(){ self.CollectionPublicPath = /public/NFTCollection self.CollectionStoragePath = /storage/NFTCollection self.totalSupply = 0 emit ContractInitialized() } }


Итак, у нас закончились все ресурсы. Далее мы рассмотрим глобальную функцию.

Глобальная функция

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


  1. createEmptyCollection : эта функция инициализирует пустую Collectibles.Collection в хранилище учетной записи вызывающего абонента.


  2. checkCollection : эта удобная функция поможет вам узнать, есть ли в вашей учетной записи ресурс collection .


  3. mintNFT : эта функция очень крутая, потому что она позволяет любому создать NFT.


 // pub resource Collection… pub fun createEmptyCollection(): @Collection{ return <- create Collection() } pub fun checkCollection(_addr: Address): Bool{ return getAccount(_addr) .capabilities.get<&{Collectibles.CollectionPublic}> (Collectibles.CollectionPublicPath)! .check() } pub fun mintNFT(name:String, image:String): @NFT{ Collectibles.totalSupply = Collectibles.totalSupply + 1 let nftId = Collectibles.totalSupply var newNFT <- create NFT(_id:nftId, _name:name, _image:image) return <- newNFT } init()...


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

И вот, НАКОНЕЦ, когда все готово, мы закончили писать наш смарт-контракт. Взгляните на окончательный код здесь .


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


Для взаимодействия с блокчейном Flow необходимо выполнить два шага:


  1. Изменяйте состояние, выполняя транзакции.
  2. Запросите блокчейн, запустив скрипт.

Изменение состояния путем выполнения транзакций

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


Транзакция включает в себя несколько дополнительных этапов: prepare , pre , execute и post фаза.


Подробнее об этом можно прочитать в справочном документе Cadence по транзакциям . У каждого этапа есть цель; Двумя наиболее важными этапами являются prepare и execute .


Prepare Phase : этот этап используется для доступа к данным и информации внутри учетной записи подписывающего лица (разрешено типом AuthAccount).


Execute Phase : Эта фаза используется для выполнения действий.


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


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

Шаг 1: Создайте файл.

Сначала перейдите в папку проекта и откройте папку cadence . Внутри него откройте папку transaction и создайте новый файл с именем Create_Collection.cdc и mint_nft.cdc

Шаг 2. Добавьте код транзакции создания коллекции.

 import Collectibles from "../contracts/Collectibles.cdc" transaction { prepare(signer: AuthAccount) { if signer.borrow<&Collectibles.Collection>(from: Collectibles.CollectionStoragePath) == nil { let collection <- Collectibles.createEmptyCollection() signer.save(<-collection, to: Collectibles.CollectionStoragePath) let cap = signer.capabilities.storage.issue<&{Collectibles.CollectionPublic}>(Collectibles.CollectionStoragePath) signer.capabilities.publish( cap, at: Collectibles.CollectionPublicPath) } } }


Давайте разберем этот код построчно:


  1. Эта транзакция взаимодействует со смарт-контрактом Collectibles. Затем он проверяет, есть ли у отправителя (подписавшего) ресурс Collection, хранящийся в его учетной записи, заимствуя ссылку на ресурс Collection из указанного пути хранения Collectibles.CollectionStoragePath . Если ссылка равна нулю, это означает, что у подписавшего еще нет коллекции.


  2. Если у подписывающей стороны нет коллекции, она создает пустую коллекцию, вызывая функцию createEmptyCollection() .


  3. После создания пустой коллекции поместите ее в учетную запись подписывающего лица по указанному пути хранения Collectibles.CollectionStoragePath .


Это устанавливает связь между учетной записью подписывающего лица и вновь созданной коллекцией с помощью link() .

Шаг 3. Добавьте код транзакции Mint NFT.

 import NonFungibleToken from "../contracts/NonFungibleToken.cdc" import Collectibles from "../contracts/Collectibles.cdc" transaction(name:String, image:String){ let receiverCollectionRef: &{NonFungibleToken.CollectionPublic} prepare(signer:AuthAccount){ self.receiverCollectionRef = signer.borrow<&Collectibles.Collection>(from: Collectibles.CollectionStoragePath) ?? panic("could not borrow Collection reference") } execute{ let nft <- Collectibles.mintNFT(name:name, image:image) self.receiverCollectionRef.deposit(token: <-nft) } }


Давайте разберем этот код построчно:

  1. Сначала мы импортируем контракт NonFungibleToken и Collectibles contract .


  2. transaction(name: String, image: String) Эта строка определяет новую транзакцию. Он принимает два аргумента: имя и изображение, оба типа String. Эти аргументы используются для передачи имени и изображения чеканимого NFT.


  3. let receiverCollectionRef: &{NonFungibleToken.CollectionPublic} Эта строка объявляет новую receiverCollectionRef. Это ссылка на общедоступную коллекцию NFT типа NonFungibleToken.CollectionPublic . Эта ссылка будет использоваться для взаимодействия с коллекцией, в которую мы поместим недавно созданный NFT.


  4. prepare(signer: AuthAccount) Эта строка запускает блок подготовки, который выполняется перед транзакцией. Он принимает подписывающую сторону аргумента типа AuthAccount . AuthAccount представляет учетную запись лица, подписавшего транзакцию.


  5. Он заимствует ссылку на Collectibles.Collection из хранилища подписывающего лица внутри блока подготовки. Он использует функцию заимствования для доступа к ссылке на коллекцию и сохранения ее в receiverCollectionRef .


    Если ссылка не найдена (например, если коллекция не существует в хранилище подписывающего лица), будет выдано сообщение об ошибке «не удалось заимствовать ссылку на коллекцию».


  6. Блок execute содержит основную логику выполнения транзакции. Код внутри этого блока будет выполнен после успешного завершения блока prepare .


  7. nft <- Collectibles.mintNFT(_name: name, image: image) Внутри блока execute эта строка вызывает функцию mintNFT из контракта Collectibles с указанными аргументами имени и изображения. Ожидается, что эта функция создаст новый NFT с заданным именем и изображением. Символ <- указывает, что NFT принимается как объект, который можно перемещать (ресурс).


  8. self.receiverCollectionRef.deposit(token: <-nft) Эта строка помещает вновь созданный NFT в указанную коллекцию. Он использует функцию депозита в receiverCollectionRef для передачи права собственности на NFT со счета выполнения транзакции в коллекцию. Символ <- здесь также указывает, что NFT перемещается как ресурс во время процесса deposit .

Запросите блокчейн, запустив скрипт

Мы используем скрипт для просмотра или чтения данных из блокчейна. Скрипты бесплатны и не требуют подписи.

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

Шаг 1: Создайте файл.

Сначала перейдите в папку проекта и откройте папку cadence . Внутри него откройте папку script и создайте новый файл с именем view_nft.cdc .

Шаг 2. Просмотрите сценарий NFT

 import NonFungibleToken from "../contracts/NonFungibleToken.cdc" import Collectibles from "../contracts/Collectibles.cdc" pub fun main(user: Address, id: UInt64): &NonFungibleToken.NFT? { let collectionCap= getAccount(user).capabilities .get<&{Collectibles.CollectionPublic}>(/public/NFTCollection) ?? panic("This public capability does not exist.") let collectionRef = collectionCap.borrow()! return collectionRef.borrowNFT(id: id) }


Давайте разберем этот код построчно:


  1. Сначала мы импортируем контракт NonFungibleToken и Collectibles .


  2. pub fun main(acctAddress: Address, id: UInt64): &NonFungibleToken.NFT? Эта строка определяет точку входа скрипта, которая представляет собой общедоступную функцию с именем main. Функция принимает два параметра:


  • acctAddress : параметр типа Address , представляющий адрес учетной записи в блокчейне Flow.


  • id : параметр типа UInt64 , представляющий уникальный идентификатор NFT в коллекции.


  1. Затем мы используем getCapability для получения возможности Collectibles.Collection для указанного acctAddress . Возможность — это ссылка на ресурс, которая обеспечивает доступ к его функциям и данным. В данном случае происходит выборка возможностей для типа ресурса Collectibles.Collection .


  2. Затем мы заимствуем NFT из collectionRef , используя функцию borrowNFT . Функция borrowNFT принимает параметр id , который является уникальным идентификатором NFT в коллекции. Функция borrow для возможности позволяет читать данные ресурса.


  3. Наконец, мы возвращаем NFT из функции.

Шаг 3. Развертывание тестовой сети

Теперь пришло время развернуть наш смарт-контракт в тестовой сети Flow.


1. Настройте учетную запись Flow.


Запустите следующую команду в терминале, чтобы создать учетную запись Flow:


 flow keys generate


Обязательно запишите свой открытый и закрытый ключи.


Далее мы перейдем к кран потока , создайте новый адрес на основе наших ключей и пополните наш счет тестовыми токенами. Выполните следующие шаги, чтобы создать учетную запись:


  1. Вставьте свой открытый ключ в указанное поле ввода.


  2. Оставьте для алгоритмов подписи и хеширования значения по умолчанию.


  3. Заполните капчу.


  4. Нажмите «Создать учетную запись».


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


2. Настройте проект.


Теперь давайте настроим наш проект. Изначально, когда мы настраивали проект, он создал файл flow.json .


Это файл конфигурации для Flow CLI, определяющий конфигурацию действий, которые Flow CLI может выполнять за вас. Считайте это примерно эквивалентом hardhat.config.js в Ethereum.


Теперь откройте редактор кода, скопируйте и вставьте приведенный ниже код в файл flow.json .


 { "contracts": { "Collectibles": "./cadence/contracts/Collectibles.cdc", "NonFungibleToken": { "source": "./cadence/contracts/NonFungibleToken.cdc", "aliases": { "testnet": "0x631e88ae7f1d7c20" } } }, "networks": { "testnet": "access.devnet.nodes.onflow.org:9000" }, "accounts": { "testnet-account": { "address": "ENTER YOUR ADDRESS FROM FAUCET HERE", "key": "ENTER YOUR GENERATED PRIVATE KEY HERE" } }, "deployments": { "testnet": { "testnet-account": [ "Collectibles" ] } } }


  1. Скопировать и вставить.

Вставьте сгенерированный закрытый ключ в место (ключ: «ВВЕДИТЕ СВОЙ СГЕНЕРИРОВАННЫЙ ЗАКРЫТЫЙ КЛЮЧ ЗДЕСЬ») в коде.


  1. Выполнять.

Теперь выполните код в тестовой сети. Перейдите в терминал и запустите следующий код:


 flow project deploy --network testnet


5. Дождитесь подтверждения.


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


Проверьте свой развернутый контракт здесь .


Полный код проверьте на GitHub .

Заключительные мысли и поздравления!

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


Хорошего дня!


Также опубликовано здесь