---
title: "NFTミンターチュートリアル:フルスタックdAppの作り方"
description: "NFT Minter Tutorialで、フルスタックdAppの作り方を学び、デジタルアセットのミントを始めましょう。"
---

# NFTミンターチュートリアル:フルスタックdAppの作り方

このチュートリアルでは、NFTミンターを構築し、MetamaskとWeb3ツールを使ってスマートコントラクトをReactフロントエンドに接続する方法を学びながら、フルスタックdAppの作り方を学びます。

さらに、NFTチュートリアルシリーズの他の記事もぜひチェックしてください：

- 🌟  [Web3.jsを使ってNFTをミントする方法](https://www.alchemy.com/blog/how-to-mint-an-nft-using-web3-js)
- 🪄  [Ether.jsを使ってNFTをミントする方法](https://www.alchemy.com/blog/how-to-mint-an-nft-with-ethers-js)
- 👛  [モバイルウォレットでNFTを表示する方法](https://www.alchemy.com/blog/how-to-view-your-nft-in-your-mobile-wallet)
- 💸  [NFTに価格を設定する方法](https://www.alchemy.com/blog/how-to-set-a-price-on-an-nft)

Web2出身の開発者にとって最大の課題の一つが、スマートコントラクトをフロントエンドプロジェクトに接続し、それとやり取りする方法を理解することです。

NFTミンター（デジタルアセットへのリンク、タイトル、説明を入力できるシンプルなUI）を構築することで、次のことを学びます：

- フロントエンドプロジェクトからMetamaskに接続する
- フロントエンドからスマートコントラクトのメソッドを呼び出す
- Metamaskを使ってトランザクションに署名する

このチュートリアルでは、フロントエンドフレームワークとして[React](https://reactjs.org/)を使用します。このチュートリアルは主に[Web3開発](https://www.alchemy.com/overviews/how-to-learn-web3-development)に焦点を当てているため、Reactの基礎を詳しく解説することはしません。代わりに、プロジェクトに機能を持たせることに重点を置きます

<CalloutBlock>

前提条件として、Reactの初級レベルの理解（コンポーネント、props、useState/useEffect、基本的な関数呼び出しの仕組み）が必要です。これらの用語を聞いたことがない場合は、この[Reactの入門チュートリアル](https://reactjs.org/tutorial/tutorial.html)をチェックすることをおすすめします。より視覚的に学びたい方には、Net Ninjaによるこの優れた[Full Modern React Tutorial](https://www.youtube.com/playlist?list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d)ビデオシリーズを強くおすすめします。

</CalloutBlock>

それでは、早速始めましょう！

## ステップ0：NFT作成の基礎

コードを見る前に、NFTの作成がどのように機能するか理解しておくことが重要です。これには2つのステップがあります：

1\) NFTスマートコントラクトをEthereumブロックチェーン上に公開します。通常、これは[ERC-721](https://eips.ethereum.org/EIPS/eip-721)または[ERC-1155](https://eips.ethereum.org/EIPS/eip-1155)スマートコントラクトです。

<CalloutBlock>

この2つのNFTスマートコントラクト規格の最大の違いは、ERC-1155がマルチトークン規格でバッチ機能を含んでいるのに対し、ERC-721はシングルトークン規格であり、一度に1つのトークンしか転送できないという点です。

</CalloutBlock>

2\) そのNFTスマートコントラクトのミント関数を呼び出してNFTをミントします。_ミント_とは、単に非代替性トークンの一意のインスタンスをブロックチェーン上に公開する行為です。

通常、このミント関数には2つの変数をパラメータとして渡す必要があります。1つ目は受取人で、新しくミントされたNFTを受け取るアドレスを指定します。2つ目はNFTのtokenURIで、NFTのメタデータを記述するJSONドキュメントに解決される文字列です。

<CalloutBlock>

NFTのメタデータこそが、名前、説明、画像（または他のデジタルアセット）、その他の属性といったプロパティを持たせ、NFTに命を吹き込むものです。こちらは[tokenURIの例](https://gateway.pinata.cloud/ipfs/QmSvBcb4tjdFpajGJhbFAWeK3JAxCdNQLQtr6ZdiSi42V2)で、NFTのメタデータを含んでいます。

</CalloutBlock>

このチュートリアルでは、パート2、つまりReact UIを使って既存のNFTスマートコントラクトのミント関数を呼び出すことに焦点を当てます。

このチュートリアルで呼び出すERC-721 NFTスマートコントラクトへの[リンクはこちら](https://sepolia.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE)です。作り方を学びたい場合は、私たちの別のチュートリアル「[NFTの作り方](https://www.alchemy.com/blog/how-to-create-an-nft)」をチェックすることを強くおすすめします。

よし、これでNFT作成の仕組みが理解できたので、スターターファイルをクローンしましょう！

## ステップ1：スターターファイルをクローンする

まず、[nft-minter-tutorial](https://github.com/alchemyplatform/nft-minter-tutorial) githubリポジトリにアクセスして、このプロジェクトのスターターファイルを取得してください。このリポジトリをローカル環境にクローンします。

<CalloutBlock>

リポジトリのクローン方法がわからない場合は、Githubの[このガイド](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository)をチェックしてください。

</CalloutBlock>

クローンした**nft-minter-tutorial**リポジトリを開くと、**minter-starter-files**と**nft-minter**という2つのフォルダが含まれていることがわかります。

- **minter-starter-files**には、このプロジェクトのスターターファイル（実質的にReact UI）が含まれています。このチュートリアルでは、**このディレクトリで作業を進めます**。EthereumウォレットとNFTスマートコントラクトに接続することで、このUIに命を吹き込む方法を学びます。
- **nft-minter**には、完成したチュートリアル全体が含まれており、**行き詰まった場合の参照用**です。

次に、**minter-starter-files**のコピーをお好みのコードエディタ（Alchemyでは[VSCode](https://code.visualstudio.com/download)のファンです）で開き、**src**フォルダに移動します：

**src**フォルダの中で作業を進めます

<ImageBlock
  src="https://media.alchemy.com/1704629644-open-minter-starter-files-in-editor.png"
  alt="minter-starter-filesプロジェクトを開いたVSCode、srcフォルダを表示"
  width={2880}
  height={1798}
  caption="minter-starter-filesを好きなエディタで開く"
/>

これから書くコードはすべて**src**フォルダの下に置かれます。**Minter.js**コンポーネントを編集し、プロジェクトにWeb3機能を持たせるための追加のjavascriptファイルを書いていきます。

## ステップ2：スターターファイルを確認する

コーディングを始める前に、スターターファイルにすでに用意されているものを確認しておくことが重要です。

#### Reactプロジェクトを実行する

まず、ブラウザでReactプロジェクトを実行してみましょう。Reactの良いところは、一度ブラウザでプロジェクトが実行されていれば、保存した変更がブラウザ上でリアルタイムに更新されることです。

プロジェクトを実行するには、**minter-starter-files**フォルダのルートディレクトリに移動し、ターミナルで`npm install`を実行してプロジェクトの依存関係をインストールします：

インストールが完了したら、ターミナルで`npm start`を実行します：

これを行うと、ブラウザで[http://localhost:3000/](http://localhost:3000/)が開き、プロジェクトのフロントエンドが表示されます。3つのフィールドがあるはずです：NFTのアセットへのリンクを入力する場所、NFTの名前を入力する場所、そして説明を入力する場所です。

<ImageBlock
  src="https://media.alchemy.com/1704629829-frontend-for-our-project.png"
  alt="アセットリンク、名前、説明のフィールドを持つNFTミンターフロントエンド"
  width={2876}
  height={1606}
  caption="プロジェクトUIの見た目"
/>

「Connect Wallet」や「Mint NFT」ボタンをクリックしてみると、動作しないことに気づくでしょう。これはまだ機能をプログラムしていないからです！:\)

#### minter.jsコンポーネント

<CalloutBlock>

**注：** **minter-starter-files**フォルダにいることを確認してください。**nft-minter**フォルダではありません！

</CalloutBlock>

エディタで**src**フォルダに戻り、**Minter.js**ファイルを開きましょう。このファイルの内容をすべて理解することが非常に重要です。これが、これから作業する主要なReactコンポーネントだからです。

このファイルの先頭には、特定のイベント後に更新するステート変数があります。

<CalloutBlock>

Reactのステート変数やステートフックを聞いたことがない場合は、[こちら](https://reactjs.org/docs/hooks-state.html)のドキュメントをチェックしてください。

</CalloutBlock>

それぞれの変数が表すものは次の通りです：

- **walletAddress** - ユーザーのウォレットアドレスを保存する文字列
- **status** - UIの下部に表示するメッセージを含む文字列
- **name** - NFTの名前を保存する文字列
- **description** - NFTの説明を保存する文字列
- **url** - NFTのデジタルアセットへのリンクである文字列

ステート変数の後に、3つの未実装の関数、`useEffect`、`connectWalletPressed`、`onMintPressed`があります。これらの関数がすべて**async**であることに気づくでしょう。それは、その中で非同期API呼び出しを行うからです！名前はそれぞれの機能を表しています：

- [**useEffect**](https://reactjs.org/docs/hooks-effect.html)- これはコンポーネントがレンダリングされた後に呼び出されるReactフックです。空の配列**\[\]**がpropとして渡されているため（3行目参照）、コンポーネントの_最初の_レンダリング時にのみ呼び出されます。ここでは、ウォレットリスナーと、ウォレットがすでに接続されているかどうかをUIに反映させる別のウォレット関数を呼び出します。
- **connectWalletPressed** - この関数は、ユーザーのMetamaskウォレットをdAppに接続するために呼び出されます。
- **onMintPressed** - この関数は、ユーザーのNFTをミントするために呼び出されます。

このファイルの終わり近くに、コンポーネントのUIがあります。このコードを注意深く見ると、対応するテキストフィールドの入力が変化したときに、`url`、`name`、`description`のステート変数を更新していることがわかります。

また、**mintButton**と**walletButton**というIDを持つボタンがそれぞれクリックされたときに、`connectWalletPressed`と`onMintPressed`が呼び出されることもわかります。‍

最後に、このMinterコンポーネントがどこに追加されているかを確認しましょう。

**App.js**ファイル（Reactの主要コンポーネントで、他のすべてのコンポーネントのコンテナとして機能する）を見ると、Minterコンポーネントが7行目で挿入されているのがわかります。

**このチュートリアルでは、Minter.jsファイルの編集と、srcフォルダ内へのファイルの追加のみを行います。**

作業対象の内容が理解できたので、Ethereumウォレットを設定しましょう！

## ステップ3：Ethereumウォレットを設定する

ユーザーがスマートコントラクトとやり取りできるようにするには、EthereumウォレットをあなたのdAppに接続する必要があります。

#### MetaMaskをダウンロードする

このチュートリアルでは、Ethereumアカウントアドレスを管理するためのブラウザ内仮想ウォレットであるMetamaskを使用します。Ethereumのトランザクションの仕組みについて詳しく知りたい場合は、Ethereum財団の[このページ](https://ethereum.org/en/developers/docs/transactions/)をチェックしてください。

Metamaskアカウントは[こちら](https://metamask.io/download.html)から無料でダウンロード・作成できます。アカウントを作成する際、またはすでにアカウントを持っている場合は、右上で「Ropsten Test Network」に切り替えてください（実際のお金を扱わないようにするためです）。

<ImageBlock
  src="https://media.alchemy.com/1704630094-sample-metamask-wallet.png"
  alt="Ropsteテストネットワークに切り替えたMetaMaskウォレット"
  width={712}
  height={1194}
  caption="MetaMaskウォレットのサンプル"
/>

#### フォーセットからetherを追加する

NFTをミントする（あるいはEthereumブロックチェーン上で何らかのトランザクションに署名する）には、偽のEthが必要です。Ethを取得するには、[Sepoliaフォーセット](/faucets/ethereum-sepolia)にアクセスし、Ropstenアカウントアドレスを入力して「Send Ropsten Eth」をクリックしてください。しばらくすると、Metamaskアカウントにethが表示されるはずです！

#### 残高を確認する

残高があるか再確認するために、[Alchemyのコンポーザーツール](https://www.alchemy.com/composer/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D)を使って`eth_getBalance`リクエストを行いましょう。これにより、ウォレット内のEthの量が返されます。Metamaskアカウントアドレスを入力し、「Send Request」をクリックすると、次のようなレスポンスが表示されるはずです：

<CalloutBlock>

**注：** この結果はethではなくweiで表示されています。weiはetherの最小単位として使われます。weiからethへの変換は次の通りです：1 eth = 10¹⁸ wei。したがって、0xde0b6b3a7640000を10進数に変換すると1\*10¹⁸となり、これは1 ethに等しくなります。

</CalloutBlock>

ふう！偽のお金がすべてそこにあります！🤑

## ステップ4：MetaMaskをUIに接続する

Metamaskウォレットの設定が完了したので、dAppをそれに接続しましょう！

[M-V-C](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)パラダイムに従いたいため、dAppのロジック、データ、ルールを管理する関数を含む別のファイルを作成し、それらの関数をフロントエンド（Minter.jsコンポーネント）に渡します。

#### connectWallet関数

そのために、**src**ディレクトリに**utils**という新しいフォルダを作成し、その中に**interact.js**というファイルを追加しましょう。このファイルには、ウォレットとスマートコントラクトのやり取りに関するすべての関数が含まれます。

**interact.js**ファイルの中に、`connectWallet`関数を書きます。これを後で**Minter.js**コンポーネントにインポートして呼び出します。

**interact.js**ファイルに、以下を追加してください

このコードが何をしているか分解してみましょう：

まず、この関数はブラウザで`window.ethereum`が有効になっているかをチェックします。

<CalloutBlock>

window.ethereumは、Metamaskや他のウォレットプロバイダーによって注入されるグローバルAPIで、ウェブサイトがユーザーのEthereumアカウントをリクエストできるようにします。承認されると、ユーザーが接続しているブロックチェーンからデータを読み取り、ユーザーにメッセージやトランザクションへの署名を提案できます。詳しくは[Metamaskのドキュメント](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents)をチェックしてください！

</CalloutBlock>

`window.ethereum`が存在_しない_場合、それはMetamaskがインストールされていないことを意味します。この場合、JSONオブジェクトが返され、**address**は空の文字列、**status**のJSXオブジェクトはユーザーにMetamaskのインストールが必要であることを伝えます。

<CalloutBlock>

**私たちが書くほとんどの関数は、ステート変数やUIを更新するために使えるJSONオブジェクトを返します。**

</CalloutBlock>

さて、`window.ethereum `が_存在する_場合、ここから面白くなってきます。

try/catchループを使って、[`window.ethereum.request\(\{ method: "eth\_requestAccounts" \}\);`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts)` `を呼び出すことでMetamaskへの接続を試みます。この関数を呼び出すと、ブラウザでMetamaskが開き、ユーザーにウォレットをdAppに接続するよう促されます。

- ユーザーが接続を選択すると、`method: "eth_requestAccounts"`は、dAppに接続されたユーザーのすべてのアカウントアドレスを含む配列を返します。全体として、`connectWallet`関数は、この配列の*最初*の`address`（9行目参照）と、ユーザーにスマートコントラクトへのメッセージの書き込みを促す`status`メッセージを含むJSONオブジェクトを返します。
- ユーザーが接続を拒否した場合、JSONオブジェクトには返された`address`として空の文字列と、ユーザーが接続を拒否したことを伝える`status`メッセージが含まれます。

#### connectWallet関数をminter.js UIコンポーネントに追加する

`connectWallet`関数を書いたので、これを**Minter.js**コンポーネントに接続しましょう。

まず、**Minter.js**ファイルの先頭に`import \{ connectWallet \} from "./utils/interact.js"`**;**を追加して、この関数をインポートする必要があります。**Minter.js**の最初の11行は、これで次のようになるはずです：

次に、`connectWalletPressed`関数の中で、インポートした`connectWallet`関数を次のように呼び出します：

**Minter.js**コンポーネントから機能の大部分が**interact.js**ファイルに抽象化されていることに気づきましたか？これはM-V-Cパラダイムに準拠するためです！

`connectWalletPressed`では、インポートした`connectWallet`関数への呼び出しをawaitするだけで、そのレスポンスを使って、ステートフックを通じて`status`と`walletAddress`変数を更新します。

それでは、両方のファイル（**Minter.js**と**interact.js**）を保存して、ここまでのUIをテストしてみましょう。

ブラウザで[http://localhost:3000/](http://localhost:3000/)ページを開き、ページ右上の「Connect Wallet」ボタンを押してください。

Metamaskがインストールされている場合、ウォレットをdAppに接続するよう促されるはずです。接続の招待を受け入れてください。

ウォレットボタンにアドレスが接続されたことが反映されるはずです！Yasssss 🔥

次に、ページを更新してみてください…これはおかしいですね。すでに接続されているにもかかわらず、ウォレットボタンがMetamaskへの接続を促しています…

<ImageBlock
  src="https://media.alchemy.com/1704630515-the-problem-on-page-reload.gif"
  alt="ページ再読み込み後にMetaMaskの再接続を誤って求めるウォレットボタン"
  width={946}
  height={480}
  caption="ページ再読み込み時の問題"
/>

でも心配いりません！`getCurrentWalletConnected`という関数を実装することで簡単に修正できます。これは、dAppにアドレスがすでに接続されているかをチェックし、それに応じてUIを更新します！

#### getCurrentWalletConnected関数

**interact.js**ファイルに、以下の`getCurrentWalletConnected`関数を追加してください：

このコードは、先ほど書いた`connectWallet`関数と_非常に_似ています。

主な違いは、ユーザーがウォレットを接続するためにMetamaskを開くメソッド`eth_requestAccounts`を呼び出す代わりに、ここではメソッド`eth_accounts`を呼び出す点です。これは、dAppに現在接続されているMetamaskアドレスを含む配列を単に返します。

この関数の動作を確認するために、**Minter.js**コンポーネントの`useEffect`関数の中でこれを呼び出しましょう。

`connectWallet`のときと同様に、**interact.js**ファイルからこの関数を**Minter.js**ファイルにインポートする必要があります：

さて、単純に`useEffect`関数の中でこれを呼び出します：

`getCurrentWalletConnected`への呼び出しのレスポンスを使って、`walletAddress`と`status`ステート変数を更新していることに気づいてください。

このコードを追加したら、ブラウザウィンドウを更新してみてください。ボタンには接続済みであることが表示され、接続済みウォレットのアドレスのプレビューが表示されるはずです — 更新後も！😅

#### addWalletListenerを実装する

dAppのウォレットセットアップの最後のステップは、ウォレットリスナーを実装することです。これにより、ユーザーが切断したりアカウントを切り替えたりしたときなど、ウォレットの状態が変化したときにUIが更新されます。

**Minter.js**ファイルに、次のような`addWalletListener`関数を追加してください：

ここで何が起きているか簡単に分解してみましょう：

まず、この関数は`window.ethereum`が有効になっているか（つまり、Metamaskがインストールされているか）をチェックします。

- 有効でない場合、単に`status`ステート変数を、ユーザーにMetamaskのインストールを促すJSX文字列に設定します。
- 有効な場合、3行目でリスナー`window.ethereum.on("accountsChanged")`を設定します。これは、Metamaskウォレットの状態変化をリッスンします。これには、ユーザーがdAppに別のアカウントを接続した場合、アカウントを切り替えた場合、またはアカウントを切断した場合が含まれます。少なくとも1つのアカウントが接続されている場合、`walletAddress`ステート変数は、リスナーによって返された`accounts`配列の最初のアカウントとして更新されます。そうでない場合、`walletAddress`は空の文字列に設定されます。

最後に、これを`useEffect`関数の中で呼び出す必要があります：

そしてこれで完了です！ウォレット機能のプログラミングがすべて完了しました！ウォレットのセットアップが終わったので、次はNFTをミントする方法を見ていきましょう！

## ステップ5：NFTメタデータの基礎

このチュートリアルのステップ0で話したNFTメタデータを覚えていますか？これはNFTに命を吹き込み、デジタルアセット、名前、説明、その他の属性といったプロパティを持たせるものです。

このメタデータをJSONオブジェクトとして構成し、それを保存する必要があります。これにより、スマートコントラクトの`mintNFT`関数を呼び出す際に`tokenURI`パラメータとして渡すことができます。

「Link to Asset」「Name」「Description」フィールドのテキストが、NFTメタデータのさまざまなプロパティを構成します。このメタデータをJSONオブジェクトとしてフォーマットしますが、このJSONオブジェクトをどこに保存するかにはいくつかの選択肢があります：

- Ethereumブロックチェーン上に保存することもできますが、Ethereumの性質上、これは非常に高価になります（数百ドル以上の話をしています）。❌
- AWSやFirebaseのような中央集権型サーバーに保存することもできますが、それでは私たちの分散化の理念に反してしまいます。❌
- IPFS、つまり分散ファイルシステムでデータを保存・共有するための分散プロトコルおよびピアツーピアネットワークを使うこともできます。このプロトコルは分散型で無料なので、これが最良の選択肢です！✅

メタデータをIPFSに保存するために、便利なIPFS APIおよびツールキットである[Pinata](https://pinata.cloud/)を使用します。次のステップで、その具体的な方法を説明します！

## ステップ6：Pinataを使ってメタデータをIPFSにピン留めする

Pinataアカウントをお持ちでない場合は、[こちら](https://app.pinata.cloud/register)から無料アカウントにサインアップし、メールとアカウントの確認手順を完了してください。

#### Pinata APIキーを作成する

[https://app.pinata.cloud/developers/api-keys](https://app.pinata.cloud/developers/api-keys)ページに移動し、上部の「New Key」ボタンを選択し、Adminウィジェットを有効にして、キーに名前を付けます。

<ImageBlock
  src="https://media.alchemy.com/1704630785-create-your-pinata-api-key.png"
  alt="Pinata APIキーページ：Adminウィジェットを有効にして新しいキーを作成"
  width={2880}
  height={1644}
  caption="Pinata APIキーを作成する"
/>

その後、API情報が記載されたポップアップが表示されます。これを安全な場所に保管してください。

<ImageBlock
  src="https://media.alchemy.com/1704630855-save-your-api-key-and-secret.png"
  alt="APIキーとシークレットは必ず安全な場所に保存してください"
  width={2880}
  height={1650}
  caption="APIキーとシークレットは必ず安全な場所に保存してください"
/>

キーの設定が完了したので、これをプロジェクトに追加して使えるようにしましょう。

#### .envファイルを作成する

Pinataのキーとシークレットは、環境ファイルに安全に保存できます。プロジェクトディレクトリに[dotenvパッケージ](https://www.npmjs.com/package/dotenv)をインストールしましょう。

ターミナルで新しいタブを開き（ローカルホストを実行しているタブとは別に）、**minter-starter-files**フォルダにいることを確認してから、ターミナルで次のコマンドを実行してください：

次に、ターミナルで次のコマンドを実行して、**minter-starter-files**のルートディレクトリに**.env**ファイルを作成します：

これにより、**.env**ファイルがvim（テキストエディタ）で開きます。保存するには、キーボードで「esc」+「:」+「q」をこの順番で押してください。

次に、VSCodeで.envファイルに移動し、次のようにPinata APIキーとAPIシークレットを追加します：

ファイルを保存すれば、JSONメタデータをIPFSにアップロードする関数を書く準備が整いました！

#### pinJSONToIPFSを実装する

幸いなことに、Pinataには[JSONデータをIPFSにアップロードするための専用API](https://docs.pinata.cloud#PinJSONToIPFS)があり、少し修正すれば使える便利なaxiosを使ったJavaScriptの例もあります。

utilsフォルダに、pinata.jsという別のファイルを作成し、.envファイルからPinataのシークレットとキーを次のようにインポートしましょう：

次に、以下の追加コードをpinata.jsファイルに貼り付けてください。心配しないでください、すべての意味を分解して説明します！

では、このコードは正確には何をしているのでしょうか？

まず、ブラウザとnode.js向けのpromiseベースのHTTPクライアントである[axios](https://www.npmjs.com/package/axios)をインポートします。これをPinataへのリクエストに使用します。

次に、非同期関数`pinJSONToIPFS`があります。これは入力として`JSONBody`を受け取り、ヘッダーにPinataのapiキーとシークレットを含めて、彼らの`pinJSONToIPFS` APIへPOSTリクエストを行います。

- このPOSTリクエストが成功すると、この関数は`success`ブール値をtrueとし、メタデータがピン留めされた`pinataUrl`を含むJSONオブジェクトを返します。この返された`pinataUrl`を、スマートコントラクトのmint関数への`tokenURI`入力として使用します。
- このPOSTリクエストが失敗すると、この関数は`success`ブール値をfalseとし、エラーを伝える`message`文字列を含むJSONオブジェクトを返します。

`connectWallet`関数の戻り値の型と同様に、ステート変数やUIを更新するために使えるJSONオブジェクトを返しています。

## ステップ7：スマートコントラクトを読み込む

pinJSONToIPFS関数によってNFTメタデータをIPFSにアップロードする方法ができたので、次に、mintNFT関数を呼び出せるようにスマートコントラクトのインスタンスを読み込む方法が必要です。

<CalloutBlock>

前述の通り、このチュートリアルでは[この既存のNFTスマートコントラクト](https://sepolia.etherscan.io/address/0x4C4a07F737Bf57F6632B6CAB089B78f62385aCaE)を使用しますが、作り方を学びたい、または自分で作ってみたい場合は、私たちの別のチュートリアル「[NFTの作り方](https://www.alchemy.com/blog/how-to-create-an-nft)」をチェックすることを強くおすすめします。

</CalloutBlock>

#### コントラクトABI

ファイルを注意深く確認していれば、**src**ディレクトリに**contract-abi.json**ファイルがあることに気づいたでしょう。ABIは、コントラクトがどの関数を呼び出すかを指定するため、また関数が期待される形式でデータを返すことを保証するために必要です。

また、Ethereumブロックチェーンに接続してスマートコントラクトを読み込むために、Alchemy APIキーとAlchemy Web3 APIも必要になります。

#### Alchemy APIキーを作成する

まだAlchemyアカウントをお持ちでない場合は、[こちらで無料サインアップ](https://alchemy.com/?r=affiliate:d8895272-924f-412b-b63c-60124deb9357)してください。

Alchemyアカウントを作成したら、アプリを作成することでAPIキーを生成できます。これにより、Ropstenテストネットワークにリクエストを行えるようになります。

Alchemyダッシュボードのナビゲーションバーで「Apps」にホバーして「Create App」をクリックし、「Create App」ページに移動します

<ImageBlock
  src="https://media.alchemy.com/1704631152-create-a-new-app.jpg"
  alt="AlchemyダッシュボードのAppsメニューから新しいアプリを作成"
  width={2880}
  height={1640}
  caption="新しいアプリを作成する"
/>

アプリに名前を付け（私たちは「My First NFT!」を選びました）、短い説明を入力し、Environmentには「Staging」（アプリの管理用）を選択し、ネットワークには「Ropsten」を選んでください。

<ImageBlock
  src="https://media.alchemy.com/1704631219-configure-your-app-details.png"
  alt="Alchemyダッシュボード：アプリ名、説明、Ropstenネットワークを設定"
  width={2880}
  height={1640}
  caption="アプリの詳細を設定する"
/>

「Create app」をクリックすれば完了です！アプリが下の表に表示されるはずです。

素晴らしい、HTTP Alchemy API URLを作成できたので、これをクリップボードにコピーしましょう…

<ImageBlock
  src="https://media.alchemy.com/1704631290-copy-your-alchemy-api-key.gif"
  alt="Alchemyダッシュボード：.envファイル用にアプリのHTTP API URLをコピー"
  width={843}
  height={480}
  caption="Alchemy APIキーをコピーする"
/>

…そしてこれを**.env**ファイルに追加しましょう。全体として、.envファイルは次のようになるはずです：

コントラクトABIとAlchemy APIキーが揃ったので、[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)を使ってスマートコントラクトを読み込む準備が整いました。

#### Alchemy Web3エンドポイントとコントラクトを設定する

まず、まだインストールしていない場合は、ターミナルでホームディレクトリ**nft-minter-tutorial**に移動して[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)をインストールする必要があります：

次に、**interact.js**ファイルに戻りましょう。ファイルの先頭に、以下のコードを追加して.envファイルからAlchemyキーをインポートし、Alchemy Web3エンドポイントを設定します：

<CalloutBlock>

[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3)は[Web3.js](https://web3js.readthedocs.io/en/v1.2.9/)のラッパーで、拡張されたAPIメソッドや、web3開発者としての作業をより楽にするための他の重要な利点を提供します。最小限の設定で済むよう設計されているので、すぐにアプリで使い始めることができます！

</CalloutBlock>

次に、コントラクトABIとコントラクトアドレスをファイルに追加しましょう。

両方が揃ったら、mint関数のコーディングを始める準備が整いました！

## ステップ8：mintNFT関数を実装する

**interact.js**ファイルの中で、関数**mintNFT**を定義しましょう。この名前の通り、NFTをミントします。

多数の非同期呼び出し（メタデータをIPFSにピン留めするためのPinata、スマートコントラクトを読み込むためのAlchemy Web3、トランザクションに署名するためのMetamaskへの呼び出し）を行うため、この関数も非同期になります。

この関数への3つの入力は、デジタルアセットの`url`、`name`、`description`です。`connectWallet`関数の下に、以下の関数シグネチャを追加してください：

#### 入力エラーハンドリング

当然ながら、関数の開始時に何らかの入力エラーハンドリングを行い、入力パラメータが正しくない場合はこの関数を終了するのが理にかなっています。関数の中に、以下のコードを追加しましょう：

基本的に、入力パラメータのいずれかが空の文字列であれば、`success`ブール値がfalseで、`status`文字列がUI内のすべてのフィールドを入力する必要があることを伝えるJSONオブジェクトを返します。

#### メタデータをIPFSにアップロードする

メタデータが適切にフォーマットされていることがわかったら、次のステップはそれをJSONオブジェクトに包み、書いた`pinJSONToIPFS`を通じてIPFSにアップロードすることです！

そのために、まず`pinJSONToIPFS`関数を**interact.js**ファイルにインポートする必要があります。**interact.js**の一番上に、以下を追加しましょう：

思い出してください、`pinJSONToIPFS`はJSONボディを受け取ります。ですから、これを呼び出す前に、`url`、`name`、`description`パラメータをJSONオブジェクトにフォーマットする必要があります。

コードを更新して、`metadata`というJSONオブジェクトを作成し、この`metadata`パラメータを使って`pinJSONToIPFS`を呼び出しましょう：

`pinJSONToIPFS(metadata)`への呼び出しのレスポンスを`pinataResponse`オブジェクトに保存していることに気づいてください。その後、このオブジェクトをエラーがないか解析します。

エラーがあれば、`success`ブール値がfalseで、`status`文字列が呼び出しの失敗を伝えるJSONオブジェクトを返します。そうでなければ、`pinataResponse`から`pinataURL`を抽出し、`tokenURIvariable`として保存します。

さて、ファイルの先頭で初期化したAlchemy Web3 APIを使ってスマートコントラクトを読み込む時です。`mintNFT`関数の末尾に次のコード行を追加し、`window.contract`グローバル変数にコントラクトを設定します：

`mintNFT`関数に追加する最後のものは、Ethereumトランザクションです：

すでにEthereumトランザクションに詳しい方なら、その構造がこれまで見てきたものとかなり似ていることに気づくでしょう。

まず、トランザクションのパラメータを設定します。

- `to`は受取人アドレス（私たちのスマートコントラクト）を指定します
- `from`はトランザクションの署名者（Metamaskに接続されたユーザーのアドレス：`window.ethereum.selectedAddress`）を指定します`\)`
- `data`には、スマートコントラクトの`mintNFT`メソッドへの呼び出しが含まれており、入力として`tokenURI`とユーザーのウォレットアドレス`window.ethereum.selectedAddress`を受け取ります

その後、awaitで`window.ethereum.request`を呼び出し、Metamaskにトランザクションへの署名を依頼します。このリクエストでは、ethメソッド（`eth\_SentTransaction`）を指定し、`transactionParameters`を渡していることに気づいてください。この時点で、Metamaskがブラウザに開き、ユーザーにトランザクションへの署名または拒否を促します。

- トランザクションが成功すると、関数はブール値`success`がtrueに設定され、`status`文字列がトランザクションの詳細についてEtherscanを確認するようユーザーに促すJSONオブジェクトを返します。
- トランザクションが失敗すると、関数は`success`ブール値がfalseに設定され、`status`文字列がエラーメッセージを伝えるJSONオブジェクトを返します。

全体として、`mintNFT`関数は次のようになるはずです：

これは巨大な関数です！さて、あとは`mintNFT`関数を**Minter.js**コンポーネントに接続するだけです…

## ステップ9：mintNFTをminter.jsフロントエンドに接続する

**Minter.js**ファイルを開き、先頭の`import \{ connectWallet \} from "./utils/interact.js"`；行を次のように更新してください：

最後に、`onMintPressed`関数を実装して、インポートした`mintNFT`関数へのawait呼び出しを行い、トランザクションが成功したか失敗したかを反映するよう`status`ステート変数を更新します：

## ステップ10：NFTをライブウェブサイトにデプロイする

‌ユーザーがやり取りできるよう、プロジェクトを本番公開する準備はできましたか？ミンターをライブウェブサイトにデプロイするための[チュートリアル](https://app.gitbook.com/@alchemyapi/s/alchemy/tutorials/nft-minter/how-do-i-deploy-nfts-online)をチェックしてください：

## ステップ11：ブロックチェーンの世界に旋風を巻き起こそう 🚀

冗談です、チュートリアルの最後まで到達しました！おさらいすると、NFTミンターを構築することで、次のことを学びました：

- フロントエンドプロジェクトからMetamaskに接続する
- フロントエンドからスマートコントラクトのメソッドを呼び出す
- Metamaskを使ってトランザクションに署名する

おそらく、dAppを通じてミントしたNFTをウォレットで見せびらかしたいと思うでしょう — [How to View Your NFT in Your Wallet](/blog/how-to-view-your-nft-in-your-mobile-wallet)の短いチュートリアルをぜひチェックしてください！

そして、いつものように、何かご質問があれば、[Alchemyサポートセンター](https://www.alchemy.com/support)をご覧ください。このチュートリアルの概念を今後のプロジェクトにどう応用するか、楽しみにしています！🧙‍♂️
