paint-brush
So erstellen Sie ein digitales Sammlerportal mit Flow und Cadence (Teil 1)von@johnjvester
375 Lesungen
375 Lesungen

So erstellen Sie ein digitales Sammlerportal mit Flow und Cadence (Teil 1)

von John Vester20m2024/02/13
Read on Terminal Reader

Zu lang; Lesen

Erfahren Sie mehr über die Flow-Blockchain und die intelligente Vertragssprache von Cadence, indem Sie eine neue Website erstellen, die sich auf das Sammeln digitaler Sammlerstücke konzentriert.
featured image - So erstellen Sie ein digitales Sammlerportal mit Flow und Cadence (Teil 1)
John Vester HackerNoon profile picture

In diesem Tutorial lernen wir, wie man eine Website zum Sammeln digitaler Sammlerstücke (oder NFTs) auf der Blockchain Flow erstellt. Um dies zu ermöglichen, verwenden wir die intelligente Vertragssprache Cadence zusammen mit React. Außerdem erfahren wir mehr über Flow, seine Vorteile und die unterhaltsamen Tools, die wir verwenden können.


Am Ende dieses Artikels verfügen Sie über die Tools und Kenntnisse, die Sie zum Erstellen Ihrer eigenen dezentralen Anwendung auf der Flow-Blockchain benötigen.


Lasst uns gleich eintauchen!


Was bauen wir?

Wir entwickeln eine Anwendung für digitale Sammlerstücke. Jedes Sammlerstück ist ein Non-Fungible Token (NFT). (Wenn Sie neu sind und NFT nicht verstehen, dann schauen Sie hier.) Mit unserer App können Sie NFTs sammeln, und jeder Artikel ist einzigartig.


Damit das alles funktioniert, verwenden wir den NonFungibleToken-Standard von Flow, einen Regelsatz, der uns bei der Verwaltung dieser besonderen digitalen Gegenstände hilft (ähnlich ERC-721 in Ethereum).

Voraussetzungen

Bevor Sie beginnen, stellen Sie sicher, dass Sie die Flow CLI auf Ihrem System installieren. Wenn Sie dies noch nicht getan haben, befolgen Sie diese Installationsanweisungen .

Einrichten

Wenn Sie bereit sind, Ihr Projekt zu starten, geben Sie zunächst das Befehlsfluss-Setup ein.


Dieser Befehl wirkt hinter den Kulissen zauberhaft, um die Grundlage für Ihr Projekt zu schaffen. Es erstellt ein Ordnersystem und richtet eine Datei namens flow.json ein, um Ihr Projekt zu konfigurieren und sicherzustellen, dass alles organisiert und einsatzbereit ist!


Projektstruktur

Das Projekt enthält einen cadence Ordner und flow.json Datei. (Eine flow.json-Datei ist eine Konfigurationsdatei für Ihr Projekt, die automatisch verwaltet wird.)

Der Cadence-Ordner enthält Folgendes:

  • /contracts: Enthält alle Cadence-Verträge.
  • /scripts: Enthält alle Cadence-Skripte.
  • /transactions: Speichert alle Cadence-Transaktionen.


Befolgen Sie die folgenden Schritte, um Flow NFT Standard zu verwenden.

Schritt 1: Erstellen Sie eine Datei.

Gehen Sie zunächst zum Ordner flow-collectibles-portal und suchen Sie den Ordner cadence . Öffnen Sie dann den contracts . Erstellen Sie eine neue Datei und nennen Sie sie NonFungibleToken.cdc .

Schritt 2: Kopieren und Einfügen.

Öffnen Sie nun den Link NonFungibleToken , der den NFT-Standard enthält. Kopieren Sie den gesamten Inhalt aus dieser Datei und fügen Sie ihn in die neue Datei ein, die Sie gerade erstellt haben („NonFungibleToken.cdc“).


Das ist es! Sie haben die Standards für Ihr Projekt erfolgreich eingerichtet.

Jetzt schreiben wir etwas Code!


Bevor wir uns jedoch mit dem Codieren befassen, ist es für Entwickler wichtig, ein mentales Modell für die Strukturierung ihres Codes zu entwickeln.


Auf der obersten Ebene besteht unsere Codebasis aus drei Hauptkomponenten:

  1. NFT: Jedes Sammlerstück wird als NFT dargestellt.


  2. Sammlung: Eine Sammlung bezieht sich auf eine Gruppe von NFTs, die einem bestimmten Benutzer gehören.


  3. Globale Funktionen und Variablen: Dies sind Funktionen und Variablen, die auf globaler Ebene für den Smart Contract definiert werden und keiner bestimmten Ressource zugeordnet sind.

Intelligente Vertragsstruktur

Grundstruktur von Smart Contracts

Erstellen Sie eine neue Datei mit dem Namen Collectibles.cdc in cadence/contracts . Hier werden wir den Code schreiben.


Vertragsstruktur

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


Lassen Sie uns den Code Zeile für Zeile aufschlüsseln:


  1. Zuerst müssen wir standardisieren, dass wir einen NFT erstellen, indem wir das sogenannte „NonFungibleToken“ einbeziehen. Dabei handelt es sich um einen von Flow entwickelten NFT-Standard, der die folgenden Funktionen definiert, die in jedem NFT-Smart-Vertrag enthalten sein müssen.


  2. Nach dem Import erstellen wir unseren Vertrag. Dazu verwenden wir pub contract [contract name] . Verwenden Sie jedes Mal dieselbe Syntax, wenn Sie einen neuen Vertrag erstellen. Sie können den contract name mit dem von Ihnen gewünschten Namen für Ihren Vertrag angeben. In unserem Fall nennen wir es Collectibles .


  3. Als Nächstes möchten wir sicherstellen, dass unser Vertrag bestimmte Funktionen und Regeln von NonFungibleToken einhält. Dazu fügen wir mit Hilfe von „:“ eine NonFungibleToken-Schnittstelle hinzu.
    So ( `pub contract Collectibles: NonFungibleToken{}` )


  4. Jeder einzelne Vertrag MUSS über die Funktion init() verfügen. Es wird aufgerufen, wenn der Vertrag zum ersten Mal bereitgestellt wird. Dies ähnelt dem, was Solidity als Konstruktor bezeichnet.


  5. Erstellen wir nun eine globale Variable namens totalSupply mit einem Datentyp UInt64 . Diese Variable verfolgt Ihre gesamten Sammlerstücke.


  6. Initialisieren Sie nun totalSupply mit dem Wert 0 .


Das ist es! Wir legen den Grundstein für unseren Collectibles . Jetzt können wir damit beginnen, weitere Features und Funktionalitäten hinzuzufügen, um es noch spannender zu machen.


Bevor Sie fortfahren, schauen Sie sich bitte das Code-Snippet an, um zu verstehen, wie wir Variablen in Cadence definieren:


Ressourcen-NFT

Fügen Sie Ihrem Smart-Vertrag den folgenden Code hinzu:


 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()... }


Wie Sie bereits gesehen haben, implementiert der Vertrag die NFT-Standardschnittstelle, dargestellt durch pub contract Collectibles: NonFungibleToken . Ebenso können Ressourcen auch verschiedene Ressourcenschnittstellen implementieren.


Fügen wir also der NFT-Ressource die Schnittstelle NonFungibleToken.INFT hinzu, die die Existenz einer öffentlichen Eigenschaft namens id innerhalb der Ressource vorschreibt.

Hier sind die Variablen, die wir in der NFT-Ressource verwenden werden:


  • id: Behält die ID von NFT bei
  • name: Name des NFT.
  • image: Bild-URL von NFT.


Stellen Sie nach dem Definieren der Variablen sicher, dass Sie die Variable in der Funktion init() initialisieren.


Machen wir weiter und erstellen eine weitere Ressource namens Collection Resource .

Sammlungsressource

Zunächst müssen Sie verstehen, wie Collection Resources funktionieren.


Was würden Sie tun, wenn Sie eine Musikdatei und mehrere Fotos auf Ihrem Laptop speichern müssten?


Normalerweise navigieren Sie zu einem lokalen Laufwerk (z. B. Ihrem D-Drive) und erstellen einen music und photos . Anschließend kopieren Sie die Musik- und Fotodateien und fügen sie in Ihre Zielordner ein.

Genauso funktionieren auch Ihre digitalen Sammlerstücke auf Flow.


Stellen Sie sich Ihren Laptop als Flow Blockchain Account , Ihr D-Laufwerk als Account Storage und den Ordner als Collection vor.


Wenn Sie also mit einem Projekt zum Kauf von NFTs interagieren, erstellt das Projekt seine collection in Ihrem account storage , ähnlich wie beim Erstellen eines Ordners auf Ihrem D-Drive. Wenn Sie mit 10 verschiedenen NFT-Projekten interagieren, erhalten Sie 10 verschiedene Sammlungen in Ihrem Konto.


Es ist, als hätten Sie einen persönlichen Raum zum Aufbewahren und Organisieren Ihrer einzigartigen digitalen Schätze!


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


Jede collection verfügt über eine ownedNFTs Variable zum Speichern der NFT Resources .


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


Ressourcenschnittstellen

Eine resource in Flow ähnelt Schnittstellen in anderen Programmiersprachen. Es sitzt über einer Ressource und stellt sicher, dass die Ressource, die es implementiert, über die erforderliche Funktionalität verfügt, wie durch die Schnittstelle definiert.


Es kann auch verwendet werden, um den Zugriff auf die gesamte Ressource einzuschränken und hinsichtlich der Zugriffsmodifikatoren restriktiver zu sein als die Ressource selbst.


Im NonFungibleToken Standard gibt es mehrere Ressourcenschnittstellen wie INFT , Provider , Receiver und CollectionPublic .


Jede dieser Schnittstellen verfügt über spezifische Funktionen und Felder, die von der Ressource, die sie verwendet, implementiert werden müssen.


In diesem Vertrag verwenden wir diese drei Schnittstellen von NonFungibleToken: Provider , Receiver und CollectionPublic . Diese Schnittstellen definieren Funktionen wie deposit , withdraw , borrowNFT und getIDs . Wir werden diese im weiteren Verlauf im Detail erklären.


Wir werden auch einige Ereignisse hinzufügen, die wir von diesen Funktionen ausgeben, und einige Variablen deklarieren, die wir im weiteren Verlauf des Tutorials verwenden werden.


 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 <- {} } } }


Zurückziehen


Erstellen wir nun die für die Schnittstelle erforderliche Funktion 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()... }


Mit Hilfe dieser Funktion können Sie die NFT-Ressource aus der Sammlung verschieben. Wenn es:


  • Schlägt fehl : Panik und löst einen Fehler aus.


  • Erfolgreich : Es wird ein Rückzugsereignis ausgegeben und die Ressource an den Aufrufer zurückgegeben.


Der Anrufer kann diese Ressource dann nutzen und in seinem Kontospeicher speichern.


Kaution

Jetzt ist es Zeit für die von NonFungibleToken.Receiver benötigte Funktion deposit() .


 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()... }


Ausleihen und GetID


Konzentrieren wir uns nun auf die beiden von NonFungibleToken.CollectionPublic: borrowNFT() und 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()... }


Zerstörer

Das Letzte, was wir für die Sammlungsressource benötigen, ist ein Destruktor.


 destroy (){ destroy self.ownedNFTs }


Da die Collection-Ressource andere Ressourcen (NFT-Ressourcen) enthält, müssen wir einen Destruktor angeben. Ein Destruktor wird ausgeführt, wenn das Objekt zerstört wird. Dadurch wird sichergestellt, dass Ressourcen nicht „obdachlos“ bleiben, wenn ihre übergeordnete Ressource zerstört wird. Wir benötigen keinen Destruktor für die NFT-Ressource, da diese keine anderen Ressourcen enthält.


Schauen wir uns den vollständigen Quellcode der Sammlungsressource an:


 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() } }


Jetzt haben wir alle Ressourcen aufgebraucht. Als nächstes schauen wir uns die globale Funktion an.

Globale Funktion

Globale Funktionen sind Funktionen, die auf der globalen Ebene des Smart Contracts definiert sind, d. h. sie sind nicht Teil einer Ressource. Diese sind für die Öffentlichkeit zugänglich und abrufbar und stellen der Öffentlichkeit die Kernfunktionalität des Smart Contracts zur Verfügung.


  1. createEmptyCollection : Diese Funktion initialisiert eine leere Collectibles.Collection im Anruferkontospeicher.


  2. checkCollection : Mit dieser praktischen Funktion können Sie herausfinden, ob Ihr Konto bereits über eine collection verfügt.


  3. mintNFT : Diese Funktion ist super cool, weil sie es jedem ermöglicht, ein NFT zu erstellen.


 // 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()...


Zusammenfassung des Smart Contracts

Und jetzt, ENDLICH, da alles vorbereitet ist, sind wir mit dem Schreiben unseres Smart Contracts fertig. Schauen Sie sich hier den endgültigen Code an.


Schauen wir uns nun an, wie ein Benutzer mit intelligenten Verträgen interagiert, die auf der Flow-Blockchain bereitgestellt werden.


Die Interaktion mit der Flow-Blockchain erfolgt in zwei Schritten:


  1. Ändern Sie den Status, indem Sie Transaktionen ausführen.
  2. Fragen Sie die Blockchain ab, indem Sie ein Skript ausführen.

Ändern Sie den Status, indem Sie Transaktionen ausführen

Transaktionen sind kryptografisch signierte Daten, die eine Reihe von Anweisungen enthalten, die mit dem Smart Contract interagieren, um den Flow-Status zu aktualisieren. Vereinfacht ausgedrückt ist dies wie ein Funktionsaufruf, der die Daten auf der Blockchain ändert. Transaktionen sind in der Regel mit gewissen Kosten verbunden, die je nach Blockchain, auf der Sie sich befinden, variieren können.


Eine Transaktion umfasst mehrere optionale Phasen: prepare , pre , execute und post .


Weitere Informationen hierzu finden Sie im Cadence-Referenzdokument zu Transaktionen . Jede Phase hat einen Zweck; Die beiden wichtigsten Phasen sind prepare und execute .


Prepare Phase : Diese Phase wird verwendet, um auf Daten und Informationen im Konto des Unterzeichners zuzugreifen (durch den AuthAccount-Typ zulässig).


Execute Phase : In dieser Phase werden Aktionen ausgeführt.


Lassen Sie uns nun eine Transaktion für unser Projekt erstellen.


Führen Sie die folgenden Schritte aus, um eine Transaktion in Ihrem Projektordner zu erstellen.

Schritt 1: Erstellen Sie eine Datei.

Gehen Sie zunächst in den Projektordner und öffnen Sie den cadence Ordner. Öffnen Sie darin den transaction und erstellen Sie eine neue Datei mit den Namen Create_Collection.cdc und mint_nft.cdc

Schritt 2: Fügen Sie den Transaktionscode „Sammlung erstellen“ hinzu.

 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) } } }


Lassen Sie uns diesen Code Zeile für Zeile aufschlüsseln:


  1. Diese Transaktion interagiert mit dem Smart-Vertrag Collectibles. Anschließend prüft es, ob der Absender (Unterzeichner) eine Collection-Ressource in seinem Konto gespeichert hat, indem es einen Verweis auf die Collection-Ressource aus dem angegebenen Speicherpfad Collectibles.CollectionStoragePath entlehnt. Wenn die Referenz Null ist, bedeutet dies, dass der Unterzeichner noch keine Sammlung hat.


  2. Wenn der Unterzeichner keine Sammlung hat, erstellt er eine leere Sammlung, indem er die Funktion createEmptyCollection() aufruft.


  3. Nachdem Sie die leere Sammlung erstellt haben, platzieren Sie sie im Konto des Unterzeichners unter dem angegebenen Speicherpfad Collectibles.CollectionStoragePath .


Dadurch wird mithilfe von link() eine Verknüpfung zwischen dem Konto des Unterzeichners und der neu erstellten Sammlung hergestellt.

Schritt 3: Fügen Sie den Mint NFT-Transaktionscode hinzu.

 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) } }


Lassen Sie uns diesen Code Zeile für Zeile aufschlüsseln:

  1. Wir importieren zunächst den NonFungibleToken und Collectibles contract .


  2. transaction(name: String, image: String) Diese Zeile definiert eine neue Transaktion. Es benötigt zwei Argumente, name und image, beide vom Typ String. Diese Argumente werden verwendet, um den Namen und das Bild des zu prägenden NFT zu übergeben.


  3. let receiverCollectionRef: &{NonFungibleToken.CollectionPublic} Diese Zeile deklariert eine neue Variable receiverCollectionRef. Es handelt sich um einen Verweis auf eine öffentliche Sammlung von NFTs vom Typ NonFungibleToken.CollectionPublic . Diese Referenz wird verwendet, um mit der Sammlung zu interagieren, in der wir den neu geprägten NFT hinterlegen.


  4. prepare(signer: AuthAccount) Diese Zeile startet den Prepare-Block, der vor der Transaktion ausgeführt wird. Es benötigt einen Argumentunterzeichner vom Typ AuthAccount . AuthAccount stellt das Konto des Unterzeichners der Transaktion dar.


  5. Es entlehnt einen Verweis auf die Collectibles.Collection aus dem Speicher des Unterzeichners im Prepare-Block. Mithilfe der Funktion „borgen“ greift es auf den Verweis auf die Sammlung zu und speichert ihn in der Variablen receiverCollectionRef .


    Wenn die Referenz nicht gefunden wird (z. B. wenn die Sammlung nicht im Speicher des Unterzeichners vorhanden ist), wird die Fehlermeldung „Sammlungsreferenz konnte nicht ausgeliehen werden“ ausgegeben.


  6. Der execute enthält die Hauptausführungslogik für die Transaktion. Der Code in diesem Block wird ausgeführt, nachdem der prepare erfolgreich abgeschlossen wurde.


  7. nft <- Collectibles.mintNFT(_name: name, image: image) Innerhalb des execute ruft diese Zeile die mintNFT Funktion aus dem Collectibles Vertrag mit den bereitgestellten Namens- und Bildargumenten auf. Von dieser Funktion wird erwartet, dass sie ein neues NFT mit dem angegebenen Namen und Bild erstellt. Das <- -Symbol zeigt an, dass der NFT als verschiebbares Objekt (Ressource) empfangen wird.


  8. self.receiverCollectionRef.deposit(token: <-nft) Diese Zeile hinterlegt den neu geprägten NFT in der angegebenen Sammlung. Es verwendet die Einzahlungsfunktion auf der receiverCollectionRef , um das Eigentum an der NFT vom ausführenden Konto der Transaktion auf die Sammlung zu übertragen. Das <- -Symbol weist hier auch darauf hin, dass der NFT während des deposit als Ressource verschoben wird.

Fragen Sie die Blockchain ab, indem Sie ein Skript ausführen

Wir verwenden ein Skript, um Daten aus der Blockchain anzuzeigen oder zu lesen. Skripte sind kostenlos und müssen nicht signiert werden.

Führen Sie die folgenden Schritte aus, um ein Skript in Ihrem Projektordner zu erstellen.

Schritt 1: Erstellen Sie eine Datei.

Gehen Sie zunächst in den Projektordner und öffnen Sie den cadence Ordner. Öffnen Sie darin den script und erstellen Sie eine neue Datei mit dem Namen view_nft.cdc .

Schritt 2: Sehen Sie sich das NFT-Skript an

 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) }


Lassen Sie uns diesen Code Zeile für Zeile aufschlüsseln:


  1. Zuerst importieren wir den NonFungibleToken und Collectibles -Vertrag.


  2. pub fun main(acctAddress: Address, id: UInt64): &NonFungibleToken.NFT? Diese Zeile definiert den Einstiegspunkt des Skripts, bei dem es sich um eine öffentliche Funktion namens main handelt. Die Funktion benötigt zwei Parameter:


  • acctAddress : Ein Parameter vom Typ Address , der die Adresse eines Kontos in der Flow-Blockchain darstellt.


  • id : Ein Parameter vom Typ UInt64 , der die eindeutige Kennung des NFT innerhalb der Sammlung darstellt.


  1. Dann verwenden wir getCapability , um die Collectibles.Collection Funktion für die angegebene acctAddress abzurufen. Eine Fähigkeit ist ein Verweis auf eine Ressource, die den Zugriff auf ihre Funktionen und Daten ermöglicht. In diesem Fall wird die Funktion für den Ressourcentyp Collectibles.Collection abgerufen.


  2. Anschließend leihen wir mithilfe der Funktion borrowNFT ein NFT aus der collectionRef aus. Die Funktion borrowNFT verwendet den Parameter id , der die eindeutige Kennung des NFT innerhalb der Sammlung darstellt. Die borrow Funktion einer Fähigkeit ermöglicht das Lesen der Ressourcendaten.


  3. Schließlich geben wir die NFT von der Funktion zurück.

Schritt 3: Testnet-Bereitstellung

Jetzt ist es an der Zeit, unseren Smart Contract im Flow-Testnetz bereitzustellen.


1. Richten Sie ein Flow-Konto ein.


Führen Sie den folgenden Befehl im Terminal aus, um ein Flow-Konto zu generieren:


 flow keys generate


Notieren Sie sich unbedingt Ihren öffentlichen und privaten Schlüssel.


Als nächstes machen wir uns auf den Weg zu der Durchflusshahn , erstellen Sie eine neue Adresse basierend auf unseren Schlüsseln und füllen Sie unser Konto mit einigen Testtokens auf. Führen Sie die folgenden Schritte aus, um Ihr Konto zu erstellen:


  1. Fügen Sie Ihren öffentlichen Schlüssel in das angegebene Eingabefeld ein.


  2. Behalten Sie die Standardeinstellungen für die Signatur- und Hash-Algorithmen bei.


  3. Füllen Sie das Captcha aus.


  4. Klicken Sie auf Konto erstellen.


Nach dem Einrichten eines Kontos erhalten wir einen Dialog mit unserer neuen Flow-Adresse, der 1.000 Test-Flow-Token enthält. Kopieren Sie die Adresse, damit wir sie künftig verwenden können .


2. Konfigurieren Sie das Projekt.


Jetzt konfigurieren wir unser Projekt. Als wir das Projekt einrichteten, wurde zunächst eine flow.json Datei erstellt.


Dies ist die Konfigurationsdatei für die Flow CLI und definiert die Konfiguration für Aktionen, die die Flow CLI für Sie ausführen kann. Stellen Sie sich dies als ungefähr gleichbedeutend mit hardhat.config.js auf Ethereum vor.


Öffnen Sie nun Ihren Code-Editor, kopieren Sie den folgenden Code und fügen Sie ihn in Ihre flow.json Datei ein.


 { "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. Kopieren und Einfügen.

Fügen Sie Ihren generierten privaten Schlüssel an der Stelle (Schlüssel: „GEBEN SIE IHREN GENERIERTEN PRIVATEN SCHLÜSSEL HIER EIN“) im Code ein.


  1. Ausführen.

Führen Sie nun den Code im Testnetz aus. Gehen Sie zum Terminal und führen Sie den folgenden Code aus:


 flow project deploy --network testnet


5. Warten Sie auf die Bestätigung.


Nach dem Absenden der Transaktion erhalten Sie eine Transaktions-ID. Warten Sie, bis die Transaktion im Testnetz bestätigt wird, was anzeigt, dass der Smart Contract erfolgreich bereitgestellt wurde.


Überprüfen Sie hier Ihren bereitgestellten Vertrag.


Überprüfen Sie den vollständigen Code auf GitHub .

Abschließende Gedanken und Glückwünsche!

Glückwunsch! Sie haben jetzt ein Sammlerportal auf der Flow-Blockchain erstellt und es im Testnetz bereitgestellt. Was kommt als nächstes? Jetzt können Sie an der Erstellung des Frontends arbeiten, das wir in Teil 2 dieser Serie behandeln werden.


Ich wünsche Ihnen einen wirklich tollen Tag!


Auch hier veröffentlicht