NFTがどう発行されるのか理解したいからOpenSeaのERC721 Tutorialをやってみる (part1)

## はじめに

openseaのERC721 Tutorialをやっています。

https://docs.opensea.io/docs/getting-started

> OpenSeaで売買するためのカスタマイズ可能なマーケットプレイスの簡単なチュートリアルです。 
> 
> (OpenSea Developer Documentation の ERC721 Tutorialから引用 (DeepLで翻訳) )

その中の1つ目の「1. Structuring your smart contract」を補足を加えて、備忘録的にまとめていきます。
上記のチュートリアルの通りに進めているので、上記のチュートリアルと同時に参照してもらえるといいと思います。
場所によって、チュートリアルを補足してたりチュートリアルより情報が少なかったりします。

## 流れ

* GitHubからコード(スターターリポジトリ)を取得する
* Nodeのバージョンを12に合わせる
* Rinkebyにテスト資金を追加する
  * Metamaskにテストネットワークを追加する
* 環境変数を設定する
  * Alchemyアカウントを作成して、Alchemy API keyを取得する
  * Metamaskのニーモニックフレーズを取得する
* デプロイする
* デプロイしたコントラクトを確認する
* Mintする

## GitHubからコード(スターターリポジトリ)を取得する

GitHubリンク：https://github.com/ProjectOpenSea/opensea-creatures

上記のGitHubリンク(テンプレート)からリポジトリを作成しcloneしました。

## Nodeのバージョンを12に合わせる

自分は元々Nodeのバージョン16系を使っていたので、Nodeのバージョンを12に変更しました。

|package.jsonにあるengines要件に準拠したバージョンが必要|voltaで12に設定|
|-|-|
|![スクリーンショット 2022-08-28 16.17.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506867/4c9036a3-61ff-fec4-5cb3-a2776adc8b74.png)|![スクリーンショット 2022-08-28 16.18.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506867/3ac59af5-3825-c3ac-674f-c23c42b06a0e.png)|

## Rinkebyにテスト資金を追加する

方法1
[このサイト](https://rinkebyfaucet.com/)からテストネット用のETHを入手。
こちらは、アドレスを入力するだけで一瞬でETHを手に入れることが出来ました。

このサイトでは、0.1 ETHが貰えました。

参照
[YouTube - IT WORKS! - How to get test ETHER from Alchemy Rinkeby Faucet](https://youtu.be/C8bR4MMl0AA)

方法2
[このサイト](https://faucets.chain.link/)からからテストネット用のETHを入手。
MetaMaskと接続することでETHを手に入れることが出来ました。
このサイトでは、0.1ETHと 20LINKが貰えました。

※ 以下の情報で、MetaMaskにLINK のトークンを追加して確認することができます。
```
アドレス: 0x01BE23585060835E02B77ef475b0Cc51aA1e0709
シンボル: LINK
小数桁数: 18
```
参照
[Chainlink - LINK Token Contracts](https://docs.chain.link/docs/link-token-contracts/#rinkeby-testnet-deprecated)

方法3
[このサイト](https://faucet.rinkeby.io/)からテストネット用のETHを手に入れることができます。
TwittwrやFacebookに自分のアドレスを投稿して、その投稿のURLを貼り付けることで、入手できます。

参照
* [[Ethereum]各テストネットワークのEtherを取得する方法](https://qiita.com/biga816/items/ac762faf5d9334aeeabd)
* [Techpit - ブロックチェーンで動くTodoアプリを開発しよう！ - テストネットにデプロイする - Rinkeby用のETHを発行する](https://www.techpit.jp/courses/36/curriculums/37/sections/304/parts/1014)

自分はやってみたら、「Insufficient funds for gas * price + value」というエラーが出ました。

### Metamask上にRinkebyを追加する
```
メタマスクを開く → 設定をクリック → 高度な設定をクリック → 「テストネットワークを表示」をonにする
```
上記のようにすることで、いくつかのテストネットワークがmetamask上に表示されます。
これで、MetamaskにRinkebyが追加され、ETHが貰えたことを確認できます。

ちなみに、テストネットのRinkebyは廃止予定で非推奨みたいです。
参照
* [イーサリアムが3つのテストネット廃止へ、PoS移行後に](https://www.neweconomy.jp/posts/237671)
* [イーサリアム、PoS移行完了後3つのテストネットを閉鎖へ](https://coinpost.jp/?p=361661)

今回は、チュートリアルに従ってRinkebyで進めてみます。

## 環境変数に使う値を取得する


デプロイするためには、メタマスクのニーモニックとALCHEMY_KEY(or INFURA_KEY)が必要です。
![スクリーンショット 2022-08-28 16.26.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506867/6fad76b2-42aa-df2f-7bd1-a8de666820e8.png)

「Alchemy API key」と「Metamaskのニーモニックフレーズ」を取得していきます。


### Alchemyアカウントを作成して、Alchemy API keyを取得する

Googleアカウントを使ってログインし、プランなどを選択して進めていく。
Dashboardまで来たら、「+ Create App」をクリックし、CHAINは「Ethereum」、NETWORKは「Rinkeby」にしてAppを作成する
Appを作成したら、表の右にあるVIEW KEYをクリックしAPI KEYを取得する。

### Metamaskのニーモニックフレーズを取得する

```
メタマスクを開く → 設定をクリック → セキュリティとプライバシーをクリック → シークレットリカバリーフレーズを公開をクリック
```
上記のようにすることで、ニーモニックフレーズを取得できます。

ニーモニックフレーズがバレるとウォレットの中身はすべて抜き取られてしまう可能性があるので注意が必要です。絶対に公開しないようにする必要があります。
※ 自分はテスト用(開発用)のメタマスクアカウント作ってやってます。


## デプロイする

チュートリアルに従って、コントラクトをデプロイしていきます。
```
yarn install
export ALCHEMY_KEY="<Alchemy API key>"
export MNEMONIC="<Metamaskのニーモニックフレーズ>"
export NETWORK="rinkeby"
yarn truffle deploy --network rinkeby
```

エラーが発生しました

```
✔ Fetching solc version list from solc-bin. Attempt #1

ParserError: Expected primary expression.
  --> ~/opensea-erc721-tutorial/contracts/Creature.sol:21:16:
   |
21 |         return <contractUrlHere>;
   |                ^

```

コード(文字列)じゃなくて、プレースホルダーみたいです。

[これ](https://github.com/ProjectOpenSea/opensea-creatures/commit/8a9c0915ccaa1d13de0a71402183257c569eb28f)が原因みたいです。
一旦このURLに書き換え、このcommitの変更前の状態にして進めてみます。

`contracts/Creature.sol`を開いて編集します。

```diff
- return <contractUrlHere>;
+ return "https://creatures-api.opensea.io/contract/opensea-creatures"
```

再度、デプロイしてみます

```
% yarn truffle deploy --network rinkeby
.
.
.
> Compiled successfully using:
   - solc: ...
.
.
.
Summary
=======
> Total deployments:   2
> Final cost:          0.04154238 ETH

✨  Done in 164.38s.
```

成功しました！！！👏

※ 自分は、テスト資金の追加を方法1だけの状態でやったら、「insufficient funds for gas * price + value」というエラーが発生しました。方法2も行って、更にテスト資金を追加したらうまく行きました。

## デプロイしたコントラクトを確認する

`https://rinkeby.etherscan.io/address/<contract_address>`にアクセスすることで、デプロイしたコントラクトを確認することが出来ます。
`<contract_address>`はデプロイコマンドの出力で見ることが出来ます。
今回使うのは2_(下)の方です。

```
1_initial_migrations.js
=======================

   Deploying 'Migrations'
   --------------------
   .
   > Blocks: 0
   > contract address:    0......
   > block number:
   .
   .

2_deploy_contracts.js
=====================

   Deploying 'Creature'
   --------------------
   .
   > Blocks: 0
   > contract address:    <contract_address>
   > block number:
   .
   .
```

## Mintする

コントラクトのデプロイが完了したので、手順に従ってMintしてみます。
Mintとは、NFTを生成することです。

環境変数を設定し、Mintするスクリプトを実行します。
<my_address>はMetaMaskのアドレスです。
<deployed_contract_address>は先程確認したコントラクト(出力された2つの内の下の方)のアドレスです。

```
export OWNER_ADDRESS="<my_address>"
export NFT_CONTRACT_ADDRESS="<deployed_contract_address>"
node scripts/mint.js
```

scripts/mint.jsで実際にMinsするスクリプトを見るとcreatureを12体Mintするようです。
```.js
for (var i = 0; i < NUM_CREATURES; i++) {
      const result = await nftContract.methods
        .mintTo(OWNER_ADDRESS)
        .send({ from: OWNER_ADDRESS });
      console.log("Minted creature. Transaction: " + result.transactionHash);
    }
```

実行すると、`https://rinkeby.etherscan.io/address/<contract_address>`のTransactionsもどんどん増えていきます！
https://rinkeby.opensea.io/ にアクセスすることで生成したNFTを確認することが出来ました。

ただ、メタデータは設定していないので、何の情報もないNFTが作られたことだけが確認できます。

## おまけ

おまけとして、Etherscanでコントラクトの読み書きができる様にします。
チュートリアル外の内容になります。

EtherscanのContractを開くと以下のメッセージが表示されています。

> Are you the contract creator? Verify and Publish your contract source code today!

この状態では、このページでコントラクトの読み書きをすることはできないので、「Verify and Publish」という作業をしていきます。

[この記事](https://note.com/standenglish/n/n7680bdb2beaf)の様に単純なコントラクトなら、Verify and Publishをクリックして手動で検証するでもいいかも知れませんが、大変なのでコマンドラインから行っていきます。

このチュートリアルのスターターリポジトリには最初から、truffle-plugin-verifyがインストールされているので、インストール作業は不要です。
必要な値を設定して、コマンドを実行するだけで出来ます。

### 流れ

* Etherscan API keyを取得する
* Etherscan API keyを設定する
* 検証のコマンドを実行する

### Etherscan API keyを取得する

https://etherscan.io/apis にアクセスして、Etherscan API keyを取得します。
ログインしたら、My API Keysの横の「+ Add」をクリックし、プロジェクト名を入れてAPI Keyを作成します。
これで、Etherscan API keyを取得することが出来ました。

### Etherscan API keyを設定する

`truffle.js`ファイルのapi_keysにEtherscan API keyを設定します。

![スクリーンショット 2022-08-30 15.37.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506867/8f042e6e-0e13-e8c7-8405-1700abfccda8.png)

自分は環境変数として設定しました。

<details><summary>環境変数に設定</summary><div>

**環境変数を使ってapi_keysの設定**
```truffle.js
.
.
const isInfura = !!process.env.INFURA_KEY;
const ETHERSCAN_API_KEY_FOR_VERIFICATION = process.env.ETHERSCAN_API_KEY;
.
.
module.exports = {
  .
  .
  api_keys: {
    etherscan: ETHERSCAN_API_KEY_FOR_VERIFICATION
  }
};

```

**環境変数の設定**
```
export ETHERSCAN_API_KEY=<取得したEtherscan API key>
```

</div></details>

### 検証のコマンドを実行する

検証を実行していきます。
```
yarn truffle run verify Creature@0x0.... --network rinkeby
```

`@0x0....`には自分のコントラクトのアドレスを入力します。

```
Pass - Verified: https://rinkeby.etherscan.io/address/0x0....
Successfully verified 1 contract(s).
```
検証に成功しました。

### Etherscanを確認してみる

EtherscanのContractを開いて、`Contract Source Code Verified`と表示されていたら成功です！
これで、コントラクトの内容の確認などができる様になりました！

「Read Contract」タブを開きます。
コントラクトの読み取る処理が見れます。
baseTokenURIやcontractURIを見てみるとコードでreturnしてる値が表示されました。
totalSupplyを見てみると、発行したNFTの数が見れました。

「Write Contract」タブを開きます。
「Connect to Web3」からウォレットと接続します。

mintToを実行してみます。

![スクリーンショット 2022-08-30 15.47.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506867/75aca579-dc66-3e04-2a1b-77f54a91adb4.png)

mintToに引数の値を設定し、Writeをクリックしてみます。
引数の値は、自分のウォレットのアドレスです。

mintToは、[Mintする](#mintする)の所で実行していたコントラクトの処理です。
(scripts/mint.jsの中で実行していたコントラクトの処理)

トランザクションが成功すると13個目のNFTが作成されました。([Mintする](#mintする)の所で作成済み)
https://rinkeby.opensea.io/ でも1つ増えてるのが確認できます。

Etherscanで自分がデプロイしたコントラクトの読み書きができる様になりました。

## おわりに

これで、Rinkebyネットワーク上にスマートコントラクトをデプロイし、コントラクト上でいくつかの新しいNFTを生成することが出来ました!!👏
ここまでが、チュートリアルの1つ目の内容になります。

今回使ったコードなどを読んでみた後は、次のチュートリアルに進んでいこうと思います。
まだしっくり来ていない部分もあるので、チュートリアルを進めて理解を深めていくのが楽しみです！

## 参照

[OpenSea Developer Documentation - ERC721 Tutorial](https://docs.opensea.io/docs/getting-started)
[GitHub - ProjectOpenSea/opensea-creatures](https://github.com/ProjectOpenSea/opensea-creatures)
https://rinkebyfaucet.com/
https://faucets.chain.link/
https://faucet.rinkeby.io/
[YouTube - IT WORKS! - How to get test ETHER from Alchemy Rinkeby Faucet](https://youtu.be/C8bR4MMl0AA)
[Chainlink - LINK Token Contracts](https://docs.chain.link/docs/link-token-contracts/#rinkeby-testnet-deprecated)
[[Ethereum]各テストネットワークのEtherを取得する方法](https://qiita.com/biga816/items/ac762faf5d9334aeeabd)
[Techpit - ブロックチェーンで動くTodoアプリを開発しよう！ - テストネットにデプロイする - Rinkeby用のETHを発行する](https://www.techpit.jp/courses/36/curriculums/37/sections/304/parts/1014)
[イーサリアムが3つのテストネット廃止へ、PoS移行後に](https://www.neweconomy.jp/posts/237671)
[イーサリアム、PoS移行完了後3つのテストネットを閉鎖へ](https://coinpost.jp/?p=361661)
https://rinkeby.etherscan.io
https://rinkeby.opensea.io/
[コントラクトをEtherscanで最適化しよう。（verifyを行いましょう）](https://note.com/standenglish/n/n7680bdb2beaf)
[TruffleでEtherScan上のスマートコントラクトをVerifyしてみる](https://koogawa.hateblo.jp/entry/2022/08/02/000000)