paint-brush
フローとケイデンスを使用してデジタル グッズ ポータルを構築する方法 (パート 2)@johnjvester
222 測定値

フローとケイデンスを使用してデジタル グッズ ポータルを構築する方法 (パート 2)

John Vester15m2024/02/27
Read on Terminal Reader

長すぎる; 読むには

Flow ブロックチェーン上に Collectibles ポータルがあり、テストネットにデプロイされているため、このシリーズの最後では、React を使用したフロントエンドの作成に集中できます。
featured image - フローとケイデンスを使用してデジタル グッズ ポータルを構築する方法 (パート 2)
John Vester HackerNoon profile picture
0-item


コレクティブル ポータル作成の最終ステップへようこそ! (パート 1 については、こちらを参照してください)


このパートでは、パズルの最後のピースであるフロントエンドの構築に焦点を当てます。


達成することは次のとおりです。


  1. フローウォレットを接続します。
  2. アカウントを初期化し、NFTを鋳造します。
  3. コレクション内の NFT ID を確認してください。
  4. コレクションにある NFT ID を使用して NFT を表示します。


Next.js を使用してフロントエンドを構築します。


始めましょう!


1. インストール

セットアップ

プロジェクトのflow-collectible-portalディレクトリを開きます。それから、走ってください
ターミナルでnpx create-next-app@latest frontendと入力し、 enterを押します。


これにより、いくつかのオプションが提供されます。このチュートリアルでは、 Typescript 、 ESLint 、またはTailwindCSSを使用せず、この記事の時点ではsrcディレクトリと App ルーターを使用します。


これで、新しい Web アプリが準備できました。

フロントエンド フォルダーは次のようになります。



2. 構成

Flow ブロックチェーンと対話するには、Flow クライアント ライブラリ (FCL) を使用してウォレット接続を管理し、スクリプトを実行し、アプリケーションでトランザクションを送信します。これにより、完全な Cadence 関数を作成し、JavaScript 関数として実行できるようになります。


まず、次のコマンドを実行してアプリの FCL をインストールしましょう。


 npm install @onflow/fcl --save


FCL をインストールした後、それを構成する必要があります。行う必要があるのは次のとおりです。


  1. appフォルダー内にflowという名前の新しいフォルダーを作成し、 config.jsという名前のファイルを追加します。
  2. このファイルでは、アクセス ノードとウォレット検出エンドポイントの指定など、FCL の構成をセットアップします。これは、テストネットを使用するかローカル エミュレーターを使用するかを選択するのに役立ちます。
  3. パート 1 で展開した Collectibles コントラクトのアドレスも指定する必要があります。


次のコードをconfig.jsファイルに追加します。


 import { config } from "@onflow/fcl"; config({ "app.detail.title": "Flow Name Service", "app.detail.icon": "https://placekitten.com/g/200/200", "accessNode.api": "https://rest-testnet.onflow.org", "discovery.wallet": "https://fcl-discovery.onflow.org/testnet/authn", "0xCollectibles": "ADD YOUR CONTRACT ACCOUNT ADDRESS", "0xNonFungibleToken": "0x631e88ae7f1d7c20", });


これで、アプリで FCL を使用するための設定がすべて完了しました。


3. 認証

アプリでユーザーの ID を確認するには、いくつかの関数を使用できます。


  1. ログインするには、 fcl.logIn()を呼び出します。
  2. サインアップするには、 fcl.signUp()を呼び出します。
  3. ログアウトするには、 fcl.unauthenticate()を呼び出します。


これらのfcl関数をフロントエンドに実装する方法を学びましょう。


まず、app ディレクトリ内のpage.jsファイルに次のコードを追加します。これにより、いくつかの依存関係がインポートされ、アプリの一部に初期useStateが設定され、基本的な UI が構築されます。


見栄えを良くするには、アプリ ディレクトリ内のpage.module.cssファイルを削除し、代わりに page.css というファイルを作成します。次に、このファイルの内容をその中に貼り付けます。これで、最初のページを書き出すことができます。


 "use client"; import React, { useState, useEffect, useRef } from "react"; import * as fcl from "@onflow/fcl"; import "./page.css"; import "./flow/config"; export default function Page() { const [currentUser, setCurrentUser] = useState({ loggedIn: false, addr: undefined, }); const urlInputRef = useRef(); const nameInputRef = useRef(); const idInputRef = useRef(); const [isInitialized, setIsInitialized] = useState(); const [collectiblesList, setCollectiblesList] = useState([]); const [loading, setLoading] = useState(false); const [ids, setIds] = useState([]); const [nft, setNFT] = useState({}); useEffect(() => fcl.currentUser.subscribe(setCurrentUser), []); function handleInputChange(event) { const inputValue = event.target.value; if (/^\d+$/.test(inputValue)) { idInputRef.current = +inputValue; } else { console.error("Invalid input. Please enter a valid integer."); } } return ( <div> <div className="navbar"> <h1>Flow Collectibles Portal</h1> <span>Address: {currentUser?.addr ?? "NO Address"}</span> <button onClick={currentUser.addr ? fcl.unauthenticate : fcl.logIn}> {currentUser.addr ? "Log Out" : "Connect Wallet"} </button> </div> {currentUser.loggedIn ? ( <div className="main"> <div className="mutate"> <h1>Mutate Flow Blockchain</h1> <form onSubmit={(event) => { event.preventDefault(); }} > <input type="text" placeholder="enter name of the NFT" ref={nameInputRef} /> <input type="text" placeholder="enter a url" ref={urlInputRef} /> <button type="submit">Mint</button> </form> <mark>Your Collection will be initialized while minting NFT.</mark> </div> <div className="query"> <h1>Query Flow Blockchain</h1> <mark>Click below button to check 👇</mark> <button>Check Collection</button> <p> Is your collection initialized: {isInitialized ? "Yes" : "No"} </p> <button onClick={viewIds}> View NFT IDs you hold in your collection </button> <p>NFT Id: </p> </div> <div className="view"> <h1>View Your NFT</h1> <input type="text" placeholder="enter your NFT ID" onChange={handleInputChange} /> <button>View NFT</button> <div className="nft-card"> <p>NFT id: </p> <p>NFT name: </p> <img src="" alt="" /> </div> </div> </div> ) : ( <div className="main-2"> <h1>Connect Wallet to mint NFT!!</h1> </div> )} </div> ); }


このコードを追加した後、 npm run dev実行して、すべてが正しく読み込まれることを確認します。


4. Flowブロックチェーンのクエリ

fclを使用して Flow ブロックチェーンをクエリする方法を詳しく説明する前に、 page.jsファイルのhandleInput関数の後に次の Cadence スクリプト コードを追加します。


 const CHECK_COLLECTION = ` import NonFungibleToken from 0xNonFungibleToken import Collectibles from 0xCollectibles pub fun main(address: Address): Bool? { return Collectibles.checkCollection(_addr: address) }` const GET_NFT_ID = ` import NonFungibleToken from 0xNonFungibleToken import Collectibles from 0xCollectibles pub fun main(user: Address): [UInt64] { let collectionCap = getAccount(user).capabilities.get <&{Collectibles.CollectionPublic}>(/public/NFTCollection) ?? panic("This public capability does not exist.") let collectionRef = collectionCap.borrow()! return collectionRef.getIDs() } ` const GET_NFT = ` import NonFungibleToken from 0xNonFungibleToken import Collectibles from 0xCollectibles 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) }


Cadence スクリプトの準備が整ったので、いくつかの Javascript 関数を宣言し、Cadence 定数を`fcl`クエリに渡すことができます。


 async function checkCollectionInit() { const isInit = await fcl.query({ cadence: CHECK_COLLECTION, args: (arg,t) => [arg(currentUser?.addr, t.Address)], }); console.log(isInit); } async function viewNFT() { console.log(idInputRef.current); const nfts = await fcl.query({ cadence: GET_NFT, args: (arg,t) => [arg(currentUser?.addr,t.Address), arg(idInputRef.current, t.UInt64)] }); setNFT(nfts); console.log(nfts); } async function viewIds() { const ids = await fcl.query({ cadence: GET_NFT_ID, args: (arg,t) => [arg(currentUser?.addr,t.Address)] }); setIds(ids); console.log(ids); }


それでは、作成したすべての関数を見てみましょう。注意すべき点が 2 つあります。


  1. fcl.query
  2. そしてargs: (arg,t) => [arg(addr,t.Address)],行。


スクリプトは Solidity のview関数に似ており、実行にガス料金を必要としないため、基本的にはブロックチェーンにクエリを実行するだけです。そこで、 fcl.queryを使用して Flow 上でスクリプトを実行します。


何かをクエリするには、引数を渡す必要があります。そのために、引数を表す文字列値を取る関数である arg と、Cadence が持つさまざまなデータ型をすべて含むオブジェクトであるtを使用します。したがって、渡す引数をエンコードおよびデコードする方法をargに伝えることができます。

5. Flowブロックチェーンの変異

以前の関数は単なる「読み取り専用」でしたが、次の関数にはブロックチェーンの状態を変更して書き込みできるアクションが含まれます。別名「NFTのミント」。


これを行うには、定数として別の Cadence スクリプトを作成します。


 const MINT_NFT = ` import NonFungibleToken from 0xNonFungibleToken import Collectibles from 0xCollectibles transaction(name:String, image:String){ let receiverCollectionRef: &{NonFungibleToken.CollectionPublic} prepare(signer:AuthAccount){ // initialise account 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) } //takes the receiver collection refrence 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) } }


次に、 page.jsファイルのトランザクション コードの後に以下の関数を追加します。


 async function mint() { try{ const txnId = await fcl.mutate({ cadence: MINT_NFT, args: (arg,t) => [arg(name,t.String), arg(image, t.String)], payer: fcl.authz, proposer: fcl.authz, authorizations: [fcl.authz], limit:999,}); } catch(error){ console.error('Minting failed:' error) } console.log(txnId); }


関数に関しては、 fcl.mutate構文はfcl.queryと同じです。ただし、次のような追加のパラメーターがいくつか提供されています。


 payer: fcl.authz, proposer: fcl.authz, authorizations: [fcl.authz], limit: 50,


  • これらは、どのアカウントがトランザクションの支払いを行うか (支払者)、トランザクションをブロードキャストするか (提案者)、および承認が必要なアカウントを定義するフロー固有のものです。 (アカウントに複数のキーがアタッチされている場合、マルチシグ ウォレットのように動作する可能性があります。)
  • fcl.authz現在接続されているアカウントを指します。
  • limit 、イーサリアムの世界における GasLimit に似ており、最大計算量に上限を設けます。計算が制限を超えると、トランザクションは失敗します。


先ほど作成したmintNFT関数を呼び出して処理する関数をもう 1 つ追加する必要があります。


 const saveCollectible = async () => { if (urlInputRef.current.value.length > 0 && nameInputRef.current.value.length > 0) { try { setLoading(true); const transaction = await mintNFT(nameInputRef.current.value, urlInputRef.current.value); console.log('transactionID:', transaction); // Handle minting success (if needed) } catch (error) { console.error('Minting failed:', error); // Handle minting failure (if needed) } finally { setLoading(false); } } else { console.log('Empty input. Try again.'); } };


6. 最終コード

主要な関数を配置したら、それらを UI にプラグインできるようになります。


ただし、その前に、初期状態を読み込むのに役立つuseEffect呼び出しをいくつか追加します。これらは、既存のuseEffect呼び出しのすぐ上に追加できます。


 useEffect(() => { checkCollectionInit(); viewNFT(); }, [currentUser]); useEffect(() => { if (currentUser.loggedIn) { setCollectiblesList(collectiblesList); console.log('Setting collectibles...'); } }, [currentUser]);


UI を含むreturnセクションに戻り、アプリの適切な部分に関数を追加できます。


 return ( <div> <div className="navbar"> <h1>Flow Collectibles Portal</h1> <span>Address: {currentUser?.addr ?? "NO Address"}</span> <button onClick={currentUser.addr ? fcl.unauthenticate : fcl.logIn}> {currentUser.addr ? "Log Out" : "Connect Wallet"} </button> </div> {currentUser.loggedIn ? ( <div className="main"> <div className="mutate"> <h1>Mutate Flow Blockchain</h1> <form onSubmit={(event) => { event.preventDefault(); saveCollectible(); }} > <input type="text" placeholder="enter name of the NFT" ref={nameInputRef} /> <input type="text" placeholder="enter a url" ref={urlInputRef} /> <button type="submit">Mint</button> </form> <mark>Your Collection will be initialized while minting NFT.</mark> </div> <div className="query"> <h1>Query Flow Blockchain</h1> <mark>Click below button to check 👇</mark> <button onClick={checkCollectionInit}>Check Collection</button> <p> Is your collection initialized: {isInitialized ? "Yes" : "No"} </p> <button onClick={viewIds}> View NFT IDs you hold in your collection </button> <p>NFT Id: </p> {ids.map((id) => ( <p key={id}>{id}</p> ))} </div> <div className="view"> <h1>View Your NFT</h1> <input type="text" placeholder="enter your NFT ID" onChange={handleInputChange} /> <button onClick={viewNFT}>View NFT</button> <div className="nft-card"> <p>NFT id: {nft.id}</p> <p>NFT name: {nft.name}</p> <img src={nft.image} alt={nft.name} /> </div> </div> </div> ) : ( <div className="main-2"> <h1>Connect Wallet to mint NFT!!</h1> </div> )} </div> );


最終的なコードをここで確認してください。


アプリが完成したので、使い方を見ていきましょう。


まず、右上の「ウォレットを接続」ボタンをクリックしてウォレットを接続します。


これでNFTを鋳造できるようになりました! NFT の名前を入力し、使用する画像へのリンクを貼り付けます。 「ミント」をクリックすると、ウォレットでのトランザクションに署名するよう求められます。


トランザクションが完了するまでに少し時間がかかる場合があります。完了したら、下のボタンをクリックして NFT の ID を表示できるようになります。初めての場合は、ID は「1」だけにしてください。


これで、NFT の ID をコピーし、[表示] セクションに貼り付けて、[NFT を表示] をクリックできます。


結論

よくやった! Collectibles ポータル プロジェクトのパート 2 が完了しました。要約すると、私たちは Collectibles ポータルのフロントエンドの構築に重点を置きました。


これは次のようにして行いました。


  • Next.js を使用したアプリの作成
  • フローウォレットの接続
  • 鋳造用に独自の NFT を作成する
  • NFT の表示


本当に素晴らしい一日をお過ごしください!