FlowとipfsでNBA TOP SHOTのようなNFTを作成する方法
FlowTimes福洛时代
2021-03-16 12:28
本文约9781字,阅读全文需要约39分钟
非常に基本的な例を構築し、NFT のメタデータを IPFS にバックアップします。

非代替トークン(NFT)市場とはクライマックスに達する、比較的初期のNFTを振り返って思い出しますCryptoKitties挑戦は楽しいです。これは、Dapper Labsチームによって構築された最初の大規模なユースケースにより、イーサリアムは初めてトラフィックのプレッシャーにさらされました。

そしてRaribleOpenSeaFoundationそしてSorareこのようなプラットフォームが登場し始めました。これらのプラットフォームには毎月数百万ドルの資金が流れていますが、そのほとんどはイーサリアム ブロックチェーン上で発生します。しかし、Dapper Labs のチームが CryptoKitties の開発経験を積むと、次のことに着手しました。新しいパブリック チェーンを作成する、パブリックチェーンは普遍的ですが、NFTの開発にも非常に適しています。この目的は、イーサリアム上の NFT で発生する多くの問題を解決しながら、この分野の開発者とコレクターにより良いエクスペリエンスを提供することです。彼らの新しいブロックチェーンである Flow は、いくつかの有名ブランドとのパートナーシップを獲得できることをすでに証明しています。例えばNBA、UFC、さらにはドクター・スースもその流れに乗っています。

私たちは最近について書きましたIPFS 上の組み込みアセットサポートを使用して NFT を作成するこの記事では、NFT 分野における責任の問題と、IPFS がどのように役立つと考えているかについて説明します。ここで、IPFS 駆動フローで nft を作成する方法について説明します。 Flow ブロックチェーンの主要な初期アプリケーションの 1 つは次のとおりです。NBA Top Shot。非常に基本的な例を構築し、NFT のメタデータを IPFS にバックアップします。

私たちは好きだからpiñatas、NBA のハイライト ビデオではなく、取引可能なピニャータがパーティーで粉砕されるビデオを作成します。

これは 3 部構成のチュートリアルです。
1. コントラクトを作成し、トークンを鋳造する
2.本契約により作成されたNFTを閲覧するためのアプリを作成する
3. NFTを他者に移転するための市場を作成し、このNFTの原資産もIPFS上に移転します

最初のチュートリアルを始めましょう。

構成

Flow CLIをインストールする必要があります。 Flow のドキュメントにはいくつかの優れたインストール手順が記載されていますが、ここに再掲します。

アップルシステム
brew install flow-cli

Linux

sh -ci “$(curl -fsSL https://storage.googleapis.com/flow-cli/install.sh)"

Windows

iex “& { $(irm ‘https://storage.googleapis.com/flow-cli/install.ps1') }”

アセットファイルはIPFSに保存します。物事を単純化するために、次のように使用できますPinata。ここからサインアップできます無料アカウントをクリックして、ここで API キーを取得します。このチュートリアルの 2 番目の記事では、API, ただし、この記事では Pinata の Web サイトを使用します。

また、Flow スマート コントラクト コードを強調表示するために、NodeJS とテキスト エディターをインストールする必要があります (次から始まります)Cadence言語) 構文。ここでNodeをインストールできます。 Visual Studio コードには、ケイデンス拡張機能のサポート

プロジェクトを開始するためのディレクトリを作成しましょう。

mkdir pinata-party

そのディレクトリに移動し、新しいフロー プロジェクトを初期化します。

cd pinata-party
flow project init

次に、お気に入りのコード エディターでプロジェクトを開き (ここでも、Visual Studio Code を使用している場合は、Cadence 拡張機能をインストールします)、開発を開始します。

flow.json ファイルが表示されます。これはすぐに使用します。まず、「cadence」というフォルダーを作成します。そのフォルダー内に、contracts という名前の別のフォルダーを追加します。最後に、契約フォルダーに PinataPartyContract.cdc というファイルを作成します。

先に進む前に、今後 Flow ブロックチェーンで行うことはすべてエミュレーター上で行われることを指摘しておくことが重要です。ただし、プロジェクトをテストネットまたはメインネットにデプロイするのは、flow.json ファイルの構成設定を更新するだけで簡単です。次に、このファイルをエミュレータ環境用にセットアップして、コントラクトの作成を開始しましょう。

flow.json のコントラクトを次のように更新します。

"contracts": {
    "PinataPartyContract": "./cadence/contracts/PinataPartyContract.cdc"
}

次に、flow.json のデプロイメントを次のように更新します。

"deployments": {
    "emulator": {
         "emulator-account": ["PinataPartyContract"]
    }
}

これは実際には、Flow CLI にエミュレーターを使用してコントラクトをデプロイするように指示しており、(エミュレーター上の) アカウントとこれから作成するコントラクトも参照します。

契約

契約

Flow は、NFT コントラクトの作成に関する優れたチュートリアルを提供します。参考にはなりますが、流れとしては指摘されたように、彼らはまだNFTメタデータの問題に対処していません。彼らはメタデータをオンチェーンに保存したいと考えています。それは良いアイデアであり、彼らは間違いなく論理的なアプローチを思いつくでしょう。ただし、ここではメタデータを含むいくつかのトークンを作成する必要があり、NFT に関連付けられたメディア ファイルが必要です。メタデータは 1 つのコンポーネントにすぎません。また、トークンが最終的にどのメディア ファイルを表すかを示す必要もあります。

イーサリアム ブロックチェーン上の NFT に精通している場合は、これらのトークンによって返される資産の多くが次の場所に保存されていることをご存知でしょう。従来のデータ ストレージおよびクラウド サービス プロバイダー真ん中。落ちない限りは大丈夫です。私たちは過去に、従来のクラウド プラットフォームとブロックチェーンでのコンテンツの検索と保存について書きました。それは次の 2 つの点に要約されます。

  • アセットは検証可能である必要があります

  • ストレージの転送は簡単であるべきです

IPFS両方の側面が考慮されます。 Pinata は、コンテンツを IPFS に長期保存するための簡単な方法で階層化されます。それはまさに、NFTをサポートしたいメディアに必要なことですよね?私たちは、所有権を証明し (NFT)、NFT に関するデータを提供できることを確認し、レプリカではなく基礎となる資産 (IPFS) (メディア ファイルなど) を確実に制御できるようにしたいと考えています。これらすべてを念頭に置いて、NFT を作成し、メタデータを NFT に関連付け、メタデータが IPFS に保存されている基礎となる資産を指すようにするコントラクトを作成しましょう。

PinataPartyContract.cdc を開いて作業を始めましょう。

pub contract PinataPartyContract {
 pub resource NFT {
   pub let id: UInt64
   init(initID: UInt64) {
     self.id = initID
   }
 }
}

最初のステップは、契約を定義することです。これにさらに追加しますが、最初に PinataPartyContract を定義し、その中にリソースを作成します。リソースはユーザー アカウントに保存されているアイテムであり、アクセス制御を通じてアクセスできます。この場合、NFT リソースは、NFT を表すために使用されるものを所有することによって最終的に所有されます。 NFT は一意に識別可能である必要があります。 id 属性を使用すると、トークンを識別できます。

次に、他の人 (つまり、契約の所有者ではない人) が利用できる機能を定義するために使用されるリソース インターフェイスを作成する必要があります。

pub resource interface NFTReceiver {
 pub fun deposit(token: @NFT, metadata: {String : String})
 pub fun getIDs(): [UInt64]
 pub fun idExists(id: UInt64): Bool
 pub fun getMetadata(id: UInt64) : {String : String}
}

NFTリソースコードの下に置きます。 NFTReceiver インターフェイスは、リソースにアクセスできると定義した人が次のメソッドを呼び出すことができることを意味します。

  • deposit

  • getIDs

  • idExists

  • getMetadata

次に、トークン収集インターフェースを定義する必要があります。ユーザーのすべての NFT を保持するウォレットと考えてください。

pub resource Collection: NFTReceiver {
   pub var ownedNFTs: UInt64: NFT}
   pub var metadataObjs: {UInt64: { String : String }}

   init () {
       self.ownedNFTs <- {}
       self.metadataObjs = {}
   }

   pub fun withdraw(withdrawID: UInt64): @NFT {
       let token <- self.ownedNFTs.remove(key: withdrawID)!

       return <-token    }

   pub fun deposit(token: @NFT, metadata: {String : String}) {
       self.ownedNFTs[token.id] <-! token    }

   pub fun idExists(id: UInt64): Bool {
       return self.ownedNFTs[id] != nil    }

   pub fun getIDs(): [UInt64] {
       return self.ownedNFTs.keys    }

   pub fun updateMetadata(id: UInt64, metadata: {String: String}) {
       self.metadataObjs[id] = metadata    }

   pub fun getMetadata(id: UInt64): {String : String} {
       return self.metadataObjs[id]!
   }

   destroy() {
       destroy self.ownedNFTs    }}

このリソースでは多くのことが行われています。まず、ownedNFTs という変数があります。これはとても簡単です。その契約においてユーザーが所有するすべての NFT を追跡します。

次に、metadataObjs という変数があります。これは、Flow NFT コントラクト機能を拡張して各 NFT のメタデータ マッピングを保存するという点で少し独特です。この変数は、トークン ID を関連するメタデータにマップします。つまり、トークン ID を設定する前に、トークン ID を設定する必要があります。

次に、変数を初期化します。これは、フロー内のリソースで定義された変数に必要です。

最後に、NFT コレクション リソースで利用できるすべての機能が揃っています。これらの機能のすべてが利用できるわけではないことに注意してください。思い出していただければ、NFTReceiver リソース インターフェイスで誰でも利用できる機能を以前に定義しました。

私はデポジット機能を指摘したいと思います。デフォルトの Flow NFT コントラクトを拡張して、metadataObjs マップを含めたのと同じように、追加のパラメーター メタデータを取得できるようにデフォルトのデポジット関数も拡張しています。なぜここでこんなことをするのか?トークンの作成者だけがそのメタデータをトークンに追加できるようにする必要があります。プライバシーを維持するために、ミント実行へのメタデータの最初の追加を制限します。

契約コードはほぼ完成しました。したがって、Collection リソースの下に以下を追加します。

pub fun createEmptyCollection(): @Collection {
   return <- create Collection()}pub resource NFTMinter {
   pub var idCount: UInt64

   init() {
       self.idCount = 1
   }

   pub fun mintNFT(): @NFT {
       var newNFT <- create NFT(initID: self.idCount)

       self.idCount = self.idCount + 1 as UInt64        return <-newNFT    }}

まず、呼び出されると空の NFT コレクションを作成する関数があります。このようにして、初めてコントラクトを操作するユーザーは、定義したリソースのコレクション内に保存場所が作成されます。

その後、別のリソースを作成します。これがなければトークンを鋳造できないため、これは重要です。 NFTMinter リソースには、NFT に重複した ID が存在しないようにするためにインクリメントされる idCount が含まれています。実際にNFTを作成する機能もあります。

NFTMinter リソースの下に、メイン コントラクト初期化子を追加します。

init() {
      self.account.save(<-self.createEmptyCollection(), to: /storage/NFTCollection)
       self.account.link<&{NFTReceiver}>(/public/NFTReceiver, target: /storage/NFTCollection)
      self.account.save(<-create NFTMinter(), to: /storage/NFTMinter)
      }

この初期化関数は、コントラクトがデプロイされるときにのみ呼び出されます。次の 3 つのことを行います。
1. コレクションのデプロイヤー用に空のコレクションを作成します。これにより、契約の所有者が契約の NFT を作成し、NFT を所有できるようになります。
2.コレクションリファレンス NFTReceiver 最初に作成したインターフェースであり、このリソースは公開された場所に公開されています。これは、 NFTReceiver で定義された関数を誰でも呼び出すことができることをコントラクトに伝える方法です。
3. NFTMinter リソースがアカウント ストレージ契約作成者に保存されます。これは、コントラクトの作成者だけがトークンを鋳造できることを意味します。

契約を完了するここで見つけることができます。

契約の準備ができたので、それをデプロイしましょう。そうですね、私たちはおそらく次にいるはずですFlow Playgroundでテストしてください。そこに移動し、左側のサイドバーにある最初のアカウントをクリックします。サンプル コントラクト内のすべてのコードをコントラクト コードに置き換えて、[デプロイ] をクリックします。すべてがうまくいけば、画面下部のログ ウィンドウに次のようなログが表示されるはずです。

16:48:55 Deployment Deployed Contract To: 0x01

これで、ローカルで実行されているエミュレータにコントラクトをデプロイする準備が整いました。コマンドラインで次のコマンドを実行します。
flow project start\-emulator

これで、エミュレーターが実行され、flow.json ファイルが適切に構成されたので、コントラクトをデプロイできます。次のコマンドを実行するだけです。
flow project deploy

すべてがうまくいけば、次のような出力が表示されるはずです。
アカウントの 1 つのコントラクトをデプロイします: エミュレーター アカウント
Deploying 1 contracts for accounts: emulator-account
PinataPartyContract -> 0xf8d6e0586b0a20c7
NFTの鋳造

NFTの鋳造

このチュートリアルの 2 番目の記事では、アプリケーションとユーザー インターフェイスを通じてキャスト プロセスをより使いやすくすることに取り組みます。フロー上の NFT でメタデータがどのように機能するかを図示して示すために、Cadence スクリプトとコマンド ラインを使用します。
pinata-party プロジェクトのルートに新しいディレクトリを作成し、それをトランザクションと呼びましょう。フォルダーを作成したら、その中に MintPinataParty.cdc という名前の新しいファイルを作成します。

トランザクションを記述するには、NFT に提供されるメタデータ内のファイルを参照する必要があります。これを行うには、Pinata 経由でファイルを IPFS にアップロードします。このチュートリアルでは、NFT はパーティーで砕かれたピニャータの取引可能なビデオに焦点を当てているため、誕生日パーティーで子供がピニャータを叩いているビデオをアップロードします。必要なビデオ ファイルをアップロードできます。実際には、任意のアセット ファイルをアップロードして NFT に関連付けることができますが、このチュートリアル シリーズの 2 番目の記事ではビデオ コンテンツを楽しみにしています。ビデオファイルを再生する準備ができたら、ここにアップロードしてください。ファイルをアップロードすると、IPFS ハッシュ (コンテンツ識別子または CID と呼ばれることが多い) が与えられます。このハッシュはミントプロセス中に使用するのでコピーします。

ここで、MintPinataParty.cdc ファイルに以下を追加します。

import PinataPartyContract from 0xf8d6e0586b0a20c7transaction {
 let receiverRef: &{PinataPartyContract.NFTReceiver}
 let minterRef: &PinataPartyContract.NFTMinter

 prepare(acct: AuthAccount) {
     self.receiverRef = acct.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)
         .borrow()
         ?? panic("Could not borrow receiver reference")

     self.minterRef = acct.borrow<&PinataPartyContract.NFTMinter>(from: /storage/NFTMinter)
         ?? panic("could not borrow minter reference")
 }

 execute {
     let metadata : {String : String} = {
         "name": "The Big Swing",
         "swing_velocity": "29",
         "swing_angle": "45",
         "rating": "5",
         "uri": "ipfs://QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6"
     }
     let newNFT <- self.minterRef.mintNFT()

     self.receiverRef.deposit(token: <-newNFT, metadata: metadata)

     log("NFT Minted and deposited to Account 2's Collection")
 }}

これは非常に単純な作業ですが、作業を簡単にするために Flow が行った作業のおかげも少なからずありますが、順に見ていきましょう。まず、上部にある import ステートメントに注目してください。思い出してください。契約を展開するときに、アカウントを受け取ります。それが私たちが参照する必要があるものです。したがって、0xf8d6e0586b0a20c7 を展開内のアカウント アドレスに置き換えます。

次にトランザクションを定義します。ここで起こることはすべて、私たちが実行する予定のトランザクションに関連しています。

トランザクションで最初に行うことは、receiverRef と minterRef という 2 つの参照変数を定義することです。この場合、私たちはNFTの受信者であり、NFTの作成者でもあります。これら 2 つの変数は、契約で作成したリソースを参照します。トランザクションを実行する人がリソースにアクセスできない場合、トランザクションは失敗します。

次に、準備関数があります。この関数は、トランザクションを実行しようとしている人のアカウント情報を取得し、いくつかの検証を行います。定義した NFTMinter と、両方のリソースで利用可能な関数 NFTReceiver を「借用」しようとします。トランザクションを実行する人がそれらのリソースにアクセスできない場合、処理は失敗します。

最後に、実行関数があります。この機能では、NFT のメタデータを構築し、NFT を作成し、NFT をアカウントに入金する前にメタデータを関連付けます。お気づきかと思いますが、メタデータ変数を作成しました。その変数に、トークンに関する情報を追加しました。私たちのトークンはパーティーでピザを割るイベントを表しており、NBA トップショットで見られるもののほとんどを再現しようとしているため、メタデータにいくつかの統計を定義しました。子供はスティックを振ってピニャータの速度、振り角度、勾配を決めます。私はこれらの統計をいじってるだけです。ただし、トークンにとって意味のある情報は同様の方法で入力します。

URI メタデータにも属性を定義していることに気づくでしょう。これは、NFT に関連付けられたアセット ファイルをホストする IPFS ハッシュを指します。この場合、ピニャータが叩かれる実際のビデオです。このハッシュは、以前にファイルをアップロードした後に受け取ったハッシュに置き換えることができます。

ハッシュの前に ipfs:// を付けます。これは IPFS 上のファイルの適切な参照であり、デスクトップ クライアントと IPFS のブラウザ拡張機能の両方で使用できます。 Brave もサポートを提供しており、直接貼り付けることもできます。Brave ブラウザの場合

トークンを作成する mintNFT 関数を呼び出します。次に、デポジット関数を呼び出してアカウントに入金する必要があります。ここでメタデータを渡します。関連付けられたトークン ID にメタデータを追加する変数の関連付けをデポジット関数で定義したことを思い出してください。

これで、トランザクションを送信して NFT を作成する準備がほぼ整いました。ただし、まずアカウントを準備する必要があります。プロジェクトのルート フォルダーのコマンド ラインから、署名用の新しい秘密キーを作成しましょう。次のコマンドを実行します。

flow keys generate

これにより、公開キーと秘密キーが得られます。秘密キーを常に保護してください

トランザクションに署名するには秘密キーが必要なので、それを flow.json ファイルに貼り付けることができます。署名アルゴリズムも指定する必要があります。これは、ファイル flow.json 内のアカウント オブジェクトであり、次のようになります。

“ accounts”:{
 “ emulator-account”:{
"アドレス": "アカウントのアドレス",
"privateKey": "あなたの秘密鍵",
"chain": "ストリームエミュレータ",
    “ sigAlgorithm”:“ ECDSA_P256”,
    “ hashAlgorithm”:“ SHA3_256”
 }
},

このプロジェクトのいずれかを github またはリモート git リポジトリに保存する予定がある場合は、秘密キーを含めないように注意してください。 flow.json を .gitignore に追加できます。ローカル エミュレーターのみを使用している場合でも、キーを保護することをお勧めします。

更新したので、トランザクションを送信できるようになりました。これは、次のコマンドを実行するのと同じくらい簡単です。
flow transactions send --code ./transactions/MintPinataParty.cdc --signer emulator-account

flow.json から作成したトランザクション ファイルと署名者アカウントを参照します。すべてがうまくいけば、次のような出力が表示されるはずです。

Getting information for account with address 0xf8d6e0586b0a20c7 ...
Submitting transaction with ID
4a79102747a450f65b6aab06a77161af196c3f7151b2400b3b3d09ade3b69823 ...
Successfully submitted transaction with ID
4a79102747a450f65b6aab06a77161af196c3f7151b2400b3b3d09ade3b69823

ここで、最後に行う必要があるのは、トークンがアカウントに存在することを確認し、メタデータを取得することです。これを行うには、非常に単純なスクリプトを作成し、コマンド ラインから呼び出します。

プロジェクトのルートに、scripts という名前の新しいフォルダーを作成します。その中に CheckTokenMetadata.cdc という名前のファイルを作成します。そのファイルに次の内容を追加します。

import PinataPartyContract from 0xf8d6e0586b0a20c7pub fun main() : {String : String} {
   let nftOwner = getAccount(0xf8d6e0586b0a20c7)
   // log("NFT Owner")
   let capability = nftOwner.getCapability<&{PinataPartyContract.NFTReceiver}>(/public/NFTReceiver)

   let receiverRef = capability.borrow()
       ?? panic("Could not borrow the receiver reference")

   return receiverRef.getMetadata(id: 1)}

このスクリプトは、イーサリアム スマート コントラクトの読み取り専用メソッドと同様の方法で考えることができます。それらは無料で、契約のデータを返却するだけです。

スクリプトでは、デプロイされたアドレスからコントラクトをインポートします。次に、main 関数を定義します (これは、スクリプトを実行するために必要な関数の名前です)。この関数内で、次の 3 つの変数を定義します。

  • nftOwner: これは、NFT を所有するアカウントです。コントラクトもデプロイしたアカウントから NFT を鋳造したため、この例では 2 つのアドレスは同じです。将来の契約設計によっては、これが常に当てはまるとは限りません。

  • 能力: デプロイされたコントラクトから「借用」する必要があります。これらの関数はアクセス制御されているため、関数を借用しようとしているアドレスで関数が使用できない場合、スクリプトは失敗することに注意してください。 NFTReceiver リソースから借用しています。

  • receiverRef: この変数は単に私たちの能力を活用し、デプロイされたコントラクトから借用するようにスクリプトに指示します。

これで、関数(利用可能な関数)を呼び出すことができます。この場合、問題のアドレスが実際に鋳造した NFT を受信したことを確認してから、トークンに関連付けられたメタデータを確認したいと考えています。

スクリプトを実行して、何が得られるか見てみましょう。コマンドラインで次のコマンドを実行します。
flow scripts execute --code ./scripts/CheckTokenMetadata.cdc

メタデータ出力の場合、次のような出力が表示されるはずです。
{"name": "The Big Swing", "swing_velocity": "29", "swing_angle": "45", "rating": "5", "uri": "ipfs://QmRZdc3mAMXpv6Akz9Ekp1y4vDSjazTx2dCQRkxVy1yUj6"}

おめでとう!これで、Flow スマート コントラクトが正常に作成され、トークンとそのトークンに関連付けられたメタデータが作成され、トークンの基礎となるデジタル資産が IPFS に保存されました。チュートリアルの最初の部分としては悪くありません。

次に、フロントエンド React アプリの構築に関するチュートリアルがあります。メタデータを取得してそのメタデータを解析することで、NFT を表示できます。

FlowTimes福洛时代
作者文库