メインコンテンツまでスキップ

lesson-1_環境構築をする

💠 希少性を備えたジェネレーティブ NFT アートを作成する

Cryptopunks(クリプトパンクス)や Bored Ape Yacht Club(BAYC:ボアードエイプ・ヨットクラブ)などのNFTプロジェクトを知っていますか?

これらのプロジェクトは、数億ドルの収益を生み出し、所有者の一部は億万長者となっています。

Cryptopunks(クリプトパンクス)。

Bored Ape Yacht Club(BAYC:ボアードエイプ・ヨットクラブ)。

これらは、数量が限られたアバターのコレクションです。

各アバターは一意(ユニーク)であり、一連の特徴(肌の色、髪型など)を持っています。

さまざまな特徴を画像として作成した後、コードよってそれらを組み合わせ生成する NFT のことを Generative Art NFT と呼びます。

今回のレッスンでは環境構築をした後、CryptopunksやBAYCのような希少性を備えたGenerative ArtのNFTコレクションを作成する方法を学びます。

✍️: NFTに関する詳しい説明は、こちら をご覧ください。

💻 Python と pip をインストールする

🤩: 注意 このレッスンを進めるのに、Python やその他のプログラミング言語を知る必要はありません。

まず、こちら のWebサイトを参考に、最新版のPython3をダウンロードしてください。

ダウンロードが完了したら、ターミナルで下記を行して、Python3のバージョンを確認してください。

// Python のバージョンを確認
python3 - V;

下記のようにターミナルに出力されていれば、Pythonのダウンロードは成功です。

Python 3.10.2
  • 最新のバージョンでない場合は、warningが表示されるので、指示に従って、Python3を最新版に更新しましょう。

次に、ターミナルで下記を行して、pipのバージョンを確認してください。

// pip のバージョンを確認
python3 -m pip list

下記のようにターミナルに出力されていれば、pipのダウンロードは成功です。

Package    Version
---------- ---------
certifi 2021.10.8
pip 22.0.3
setuptools 58.1.0
  • 最新のバージョンでない場合は、warningが表示されるので、指示に従って、pipを最新版に更新しましょう。

最新版に更新する必要がある方は下のコマンドを実行してみてください。

python -m pip install --upgrade pip

次に、ターミナルで下記を実行して、Generative Artを生成する際に使用するライブラリをインストールしてください。

pip install Pillow pandas progressbar2

この処理により、generative-nft-libraryライブラリを動かすのに必要な下記3つのPython3パッケージがあなたの環境にインストールされます。

  • Pillow: 画像処理ライブラリで、特徴的な画像を合成するのに役立ちます。

  • Pandas: データ解析ライブラリで、画像のメタデータの生成と保存を支援します。

  • Progressbar: 画像生成の進捗状況を表示するライブラリです。

まず、node / yarnを取得する必要があります。お持ちでない場合は、こちらにアクセスしてください。

node v16をインストールすることを推奨しています。

それでは本プロジェクトで使用するフォルダーを作成してきましょう。作業を始めるディレクトリに移動したら、次のコマンドを実行します。

🍽 Git リポジトリをあなたの GitHub にフォークする

まだGitHubのアカウントをお持ちでない方は、こちら の手順に沿ってアカウントを作成してください。

GitHubのアカウントをお持ちの方は、下記の手順に沿ってプロジェクトの基盤となるリポジトリをあなたのGitHubにフォークしましょう。

  1. こちらからunchain-tech/ETH-NFT-Collectionリポジトリにアクセスをして、ページ右上のForkボタンをクリックします。

  1. Create a new forkページが開くので、「Copy the main branch only」という項目にチェックが入っていることを確認します

設定が完了したらCreate forkボタンをクリックします。あなたのGitHubアカウントにPolygon-Generative-NFTリポジトリのフォークが作成されたことを確認してください。

それでは、フォークしたリポジトリをローカル環境にクローンしましょう。

まず、下図のように、CodeボタンをクリックしてSSHを選択し、Gitリンクをコピーしましょう。

ターミナル上で作業を行う任意のディレクトリに移動し、先ほどコピーしたリンクを用いて下記を実行してください。

git clone コピーした_github_リンク

無事に複製されたらローカル開発環境の準備は完了です。

🔍 フォルダ構成を確認する

実装に入る前に、フォルダ構成を確認しておきましょう。クローンしたスタータープロジェクトは下記のようになっているはずです。

Polygon-Generative-NFT
├── .git/
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── packages/
│ ├── client/
│ └── contract/
│ └── library/
└── yarn.lock

スタータープロジェクトは、モノレポ構成となっています。モノレポとは、コントラクトとクライアント(またはその他構成要素)の全コードをまとめて1つのリポジトリで管理する方法です。

packagesディレクトリの中には、clientcontractlibraryという3つのディレクトリがあります。

package.jsonファイルの内容を確認してみましょう。

モノレポを作成するにあたり、パッケージマネージャーの機能であるWorkspacesを利用しています。

workspacesの定義をしている部分は以下になります。

"workspaces": {
"packages": [
"packages/*"
]
},

この機能により、yarn installを一度だけ実行すれば、すべてのパッケージ(今回はコントラクトのパッケージとクライアントのパッケージ)を一度にインストールできるようになります。

ターミナル上でPolygon-Generative-NFTディレクトリ下に移動して下記を実行しましょう。

yarn install

yarnコマンドを実行することで、JavaScriptライブラリのインストールが行われます。

📺 フロントエンドの動きを確認する

次に、下記を実行してみましょう。

yarn client start

あなたのローカル環境で、Webサイトのフロントエンドが立ち上がりましたか?

例)ローカル環境で表示されているWebサイト

上記のような形でフロントエンドが確認できれば成功です。

これからフロントエンドの表示を確認したい時は、ターミナルに向かい、Polygon-Generative-NFTディレクトリ上で、yarn client startを実行します。これからも必要となる作業ですので、よく覚えておいてください。

ターミナルを閉じるときは、以下のコマンドが使えます ✍️

  • Mac: ctrl + c
  • Windows: ctrl + shift + w

👏 コントラクトを作成する準備をする

本プロジェクトではコントラクトを作成する際にHardhatというフレームワークを使用します。

packages/contractディレクトリにいることを確認し、次のコマンドを実行します。

npx hardhat init

hardhatがターミナル上で立ち上がったら、それぞれの質問を以下のように答えていきます。

・What do you want to do? →「Create a JavaScript project」を選択
・Hardhat project root: →「'Enter'を押す」 (自動で現在いるディレクトリが設定されます。)
・Do you want to add a .gitignore? (Y/n) → 「y」

(例)

$ npx hardhat init

888 888 888 888 888
888 888 888 888 888
888 888 888 888 888
8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888
888 888 "88b 888P" d88" 888 888 "88b "88b 888
888 888 .d888888 888 888 888 888 888 .d888888 888
888 888 888 888 888 Y88b 888 888 888 888 888 Y88b.
888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888

👷 Welcome to Hardhat v2.13.0 👷‍

✔ What do you want to do? · Create a JavaScript project
✔ Hardhat project root: · /Polygon-Generative-NFT/packages/contract
✔ Do you want to add a .gitignore? (Y/n) · y

✨ Project created ✨

See the README.md file for some example tasks you can run

Give Hardhat a star on Github if you're enjoying it! 💞✨

https://github.com/NomicFoundation/hardhat

⚠️: 注意

Windows で Git Bash を使用してハードハットをインストールしている場合、このステップ (HH1) でエラーが発生する可能性があります。問題が発生した場合は、WindowsCMD(コマンドプロンプト)を使用して HardHat のインストールを実行してみてください。

この段階で、フォルダー構造は下記のようになっていることを確認してください。

Polygon-Generative-NFT
├── .gitignore
├── package.json
└── packages/
├── client/
├── library/
└── contract/
+ ├── .gitignore
+ ├── README.md
+ ├── contracts/
+ ├── hardhat.config.js
├── package.json
+ ├── scripts/
+ └── test/

次に、安全なスマートコントラクトを開発するために使用されるライブラリ OpenZeppelin と秘密鍵などのファイルを隠すためにdotenvというパッケージを追加します。

packages/contractディレクトリにいることを確認し、以下のコマンドを実行してください。

yarn add @openzeppelin/contracts@^4.8.2 dotenv@^16.0.3

OpenZeppelin はイーサリアムネットワーク上で安全なスマートコントラクトを実装するためのフレームワークです。

OpenZeppelinには非常に多くの機能が実装されておりインポートするだけで安全にその機能を使うことができます。

dotenvモジュールに関する詳しい説明は、こちらを参照してください。

それでは、packages/contractディレクトリ内のpackage.jsonファイルを更新しましょう。下記のように"private": true,の下に"scripts":{...}を追加してください。よく利用するコマンドを設定しておきます。

{
"name": "contract",
"version": "1.0.0",
"private": true,
"scripts": {
"run:script": "npx hardhat run scripts/run.js",
"deploy": "npx hardhat run scripts/deploy.js --network sepolia",
"test": "npx hardhat test"
},
"devDependencies": {

⭐️ 実行する

すべてが機能していることを確認するには、以下を実行します。

yarn test

次のように表示されます。

  Lock
Deployment
✔ Should set the right unlockTime (743ms)
✔ Should set the right owner
✔ Should receive and store the funds to lock
✔ Should fail if the unlockTime is not in the future
Withdrawals
Validations
✔ Should revert with the right error if called too soon
✔ Should revert with the right error if called from another account
✔ Shouldn't fail if the unlockTime has arrived and the owner calls it
Events
✔ Should emit an event on withdrawals
Transfers
✔ Should transfer the funds to the owner


9 passing (846ms)

ターミナル上でlsと入力してみて、下記のフォルダーとファイルが表示されていたら成功です。

README.md         cache             hardhat.config.js package.json      test
artifacts contracts node_modules scripts

ここまできたら、フォルダーの中身を整理しましょう。

まず、testの下のファイルLock.jsを削除します。

  1. testフォルダーに移動: cd test

  2. Lock.jsを削除: rm Lock.js

次に、上記の手順を参考にしてcontractsの下のLock.solを削除してください。実際のフォルダは削除しないように注意しましょう。

☀️ Hardhat の機能について

Hardhatは段階的に下記を実行しています。

1. Hardhat は、スマートコントラクトを Solidity からバイトコードにコンパイルしています。

  • バイトコードとは、コンピュータが読み取れるコードの形式のことです。

2. Hardhat は、あなたのコンピュータ上でテスト用の「ローカルイーサリアムネットワーク」を起動しています。

3. Hardhat は、コンパイルされたスマートコントラクトをローカルイーサリアムネットワークに「デプロイ」します。

これでプロジェクトの準備は整いました!

では次からはNFTに使用する画像を作成していきます!

🐿 Scrappy Squirrels を生成する

今回は、「Scrappy Squirrels」プロジェクトに使用されたデータを使って、Generative Artを生成していきます。

「Scrappy Squirrels」は85以上の特徴を用いて生成されています。

以下はそのサンプルです。

「Scrappy Squirrels」は、下記のようなPNG画像を重ねて生成されます。

上図の左上から時計回りに、画像を順番に重ねていくと、中央の画像が作成されます。

この処理を実行する上で、下記の点に注意しましょう。

  • 各特徴画像は(最終的なアバターも)同じ大きさである必要があります。

  • 背景の特徴(左上の画像)以外の特徴画像は、背景が透明である必要があります。

  • 正しいアバターを作るには、左上から時計回りに特徴画像を重ねる必要があります。

  • 特徴画像は、ほかの特徴画像とうまく重なるように描かれている必要があります。

  • どの特徴も同じカテゴリのほかの特徴と入れ替えることができます(たとえば、青い服を赤い服と入れ替える)。したがって、各カテゴリの特徴が10個ずつあれば、理論的には1億匹の異なるアバターを作り出すことができます。

オリジナルで画像を作成する場合、さまざまな特徴カテゴリを作成し、それに付随する画像を複数作成します。

ただし、特徴カテゴリの数が増えると、可能な組み合わせの数も指数関数的に増えていくことに注意してください。

「Scrappy Squirrels」プロジェクトでは、下記のように8つの特徴カテゴリを作成します。

各特徴のカテゴリごとに、特徴的な画像の数挟まざまです。

たとえば、特徴のカテゴリ「Shirt(シャツ)」には下記のように、複数の種類の画像を格納できます。

※ 現在のサンプルでは、簡単のためblue_dot.pngのみが格納されています。

今回使用する特徴カテゴリとそれに付随する画像は、packages/libraryassetフォルダの中にあります。

下記のディレクトリ構造を参考に、中身を確認してみてください。

library
|_ assets
|_ Background
|_ Expressions
|_ Head
:

🪄 config.pyファイルを設定する

アバターコレクションを生成する最後のステップです。library/config.pyを開き、以下の説明に従ってファイルを埋めていきましょう。

まず、config.pyの中身が下記のように始まることを確認してください。

CONFIG = [
{
'id': 1,
'name': 'background',
'directory': 'Background',
'required': True,
'rarity_weights': None,
},
:

config.pyファイルはCONFIGという1つのPython変数により作成されます。

CONFIG[]でカプセル化されているPythonのリストです。

積み重ねる特徴カテゴリの順番に沿って、カテゴリそれぞれのリストが含まれています。

順番は、assetsフォルダに格納されている特徴カテゴリフォルダの順番に起因しています。

ここでの順序は非常に重要です。

それでは、以下のように、config.pyを新しく設定していきましょう。

CONFIG = [
{
'id': 1,
'name': 'background',
'directory': 'Background',
'required': True,
'rarity_weights': None,
},
{
'id': 2,
'name': 'body',
'directory': 'Body',
'required': True,
'rarity_weights': None,
},
{
'id': 3,
'name': 'eyes',
'directory': 'Expressions',
'required': True,
'rarity_weights': None,
},
{
'id': 4,
'name': 'head_gear',
'directory': 'Head Gear',
'required': False,
'rarity_weights': 'random',
},
{
'id': 5,
'name': 'clothes',
'directory': 'Shirt',
'required': False,
'rarity_weights': None,
},
{
'id': 6,
'name': 'held_item',
'directory': 'Misc',
'required': True,
'rarity_weights': None,
},
{
'id': 7,
'name': 'hands',
'directory': 'Hands',
'required': True,
'rarity_weights': None,
},
{
'id': 8,
'name': 'wristband',
'directory': 'Wristband',
'required': False,
'rarity_weights': [100, 5, 5, 5, 15, 5, 1],
},
]

各特徴カテゴリ(例: Background)は{}でカプセル化されたPythonのdictionaryとして記載されています。

ここでは、特性カテゴリdictionaryCONFIGリストで順番に定義しています。

特性カテゴリdictionaryには5つのキーが必要です。

これらは、idnamedirectoryrequired、およびrarity_weightsです。

各キーについて詳しく見ていきましょう。

  • id : 重ねる画像レイヤを識別する番号です。たとえば、Backgroundが1番目に重ねる特性カテゴリ(=レイヤ)であれば、id1となります。 なお、レイヤはassetsフォルダに格納されている特徴カテゴリの並び順に沿って定義されるる必要があります。

  • name : 特性カテゴリの名前です。任意の名前を付けることができます。メタデータに表示されます。directoryの名前と一致される必要はありません。

  • directory: assets内のフォルダ名です。その特徴カテゴリに付随する画像が格納されています。

  • required : 任意の特徴カテゴリがすべての画像に必要である場合はTrue 、そうでない場合は、Falseを設定します。

    特定の特徴カテゴリ(BackgroundBody、など)はすべてのアバターに表示する必要があるので、Trueと設定しています。

    そのほかのカテゴリ(Head GearWristband、など)はオプションですので、Falseと設置しています。1 番目のレイヤのrequiredの値をTrueに設定することを強くお勧めします。

  • rarity_weights: 任意の特徴カテゴリがどの程度「希少」であるかを決定します。後に詳しく説明していきます。

⚠️: 注意

オリジナルで特徴カテゴリや画像を設定する場合、新しいレイヤーを作成するとき(または、既存のレイヤーを置き換えるとき)は、これらの 5 つのキーがすべて定義されていることを確認しましょう。

💎 特徴の希少性を設定する

rarity_weightsキーは下記3つの値を取ることができます。

  • None'random'、Pythonリスト

それぞれの値を1つずつ見ていきましょう。

1 . None

  • rarity_weightsの値をNoneに設定すると、各特徴に等しい重みが割り当てられます。

  • したがって、8つの特徴カテゴリが存在する場合、requiredTruerarity_weightsNoneとした特徴カテゴリはおよそ全体の12.5% のアバターに現れることになります。

    100 (%) / 8 (特徴カテゴリ)= 12.5 (特徴カテゴリの反映率)

  • requiredFalseの場合、その特定の特徴をまったく得られない可能性も等しくなります。

  • 先ほどのケースで、requiredFalserarity_weightsNoneとした特徴カテゴリはおよそ11.1 %のアバターに出現することになります。

  • さらに11.1% のアバターには、その特徴がまったくないことになります。

2 .'random'

rarity_weights'random'(''は必須)を設定すると、各特徴カテゴリにランダムに重みが付けられます。

この機能は使用しないことを強くお勧めします。

⚠️: 注意

ここでは、ライブラリの仕様として'random'が存在することだけ紹介しています。

config.pyでは、ライブラリの動作を確認するために、特徴カテゴリー Head Gear'random'を設定しています。

3 . Python リスト

Pythonリストは、rarity_weightsの重みを割り当てる最も一般的な方法です。

それでは、assetsの中の特徴カテゴリフォルダWristbandsに下記のような6つの画像が格納されているのを確認しましょう。

これらの画像をNameで昇順(アルファベット順)にソートすると、次のようになります。

次に、config.pyWristbandsに定義したrarity_weightsを見てみましょう。

{
'id': 8,
'name': 'wristband',
'directory': 'Wristband',
'required': False,
'rarity_weights': [100, 5, 5, 5, 15, 5, 1]
},

'rarity_weights'に設定されているリスト[100, .., , 1]では、各数値(=重み)が、特徴カテゴリWristbandの中の画像に昇順で割り当てられています。

requiredTrueの場合、重みの数は、特徴カテゴリWristbandの画像の数と同じする必要があります。

✍️: requiredTrueの場合 特徴カテゴリー Wristbandの画像の数は 6 枚なので、

'rarity_weights': [リストの中には 6 つの重みが設定される]

requiredFalseに設定されている場合、重みの数は特徴の数に1を足した数になります。

  • 'required': Falseの場合、最初の重みは、 Wristbandsを持たない場合の希少性を示す重みとなります。

✍️: 要約

リストバンドが必須であれば( 'required': True )、リスト内に 6 個の重みを定義し、必須でなければ( 'required': False )、7 個の重みを定義することになります。

今回の例では、Wristbandは、'required': Falseと設定されているので、この特徴カテゴリは最終的に画像を生成する際、必須で表示される必要はありません。

よって、下記のように、7個の重み(6種類のリストバンド + 1)を設定しました。

'rarity_weights': [100, 5, 5, 5, 15, 5, 1]

最初の重み(100)は、リストバンドをつけない場合の重みになります。

2つ目の重みは黒(black.png)のバンド、3つ目の重みは白のバンド(dark-green.png)、といった具合に関連付けを行っています。

重みの値が大きいほど、特定の特徴がよく見られます。

✍️: 重みと希少性の感性は以下のようになります。 特徴画像の重みの値が大きい = その特徴を持つ画像の希少性が低い

この例では、「黒のバンド」は5、「リストバンドなし」は100の重みを持っています。

つまり、アバターが黒のリストバンドを持つことは、持たないことの 20 倍の希少価値があるということになります。

🍳 Generative Art を生成する

config.pyファイルの中身を更新したら、Generative Artを生成しましょう。

まず、ターミナル(またはコマンドプロンプト)を開き、Polygon-Generative-NFTフォルダに移動してください。

ここで、以下のコマンドを実行します。

yarn library generate:NFT

このコマンドを実行すると、画像生成プログラムが起動します。

このプログラムは、まずユーザーに作成したいアバターの数をターミナルに入力してもらいます。

その後、指定の数のアバターを生成したら、重複するものを排除します。

最終的には、ユニークなアバターのみをoutputフォルダに格納します。

以下のステップでプログラムが実行されるので、ターミナルに表示される指示に従いながら、アバターの生成を行ってください。

  • まず、nft.pyconfig.pyが有効かどうかをチェックします。

  • 次に、可能な組み合わせの総数が表示されます。

  • 次に、作成したいアバターの数を入力します。

  • 作成したいアバターの数より20%大きい数を入力すると、重複を排除した後でも十分余るのでお勧めです。

  • コレクションに任意の名前をつけます。これにより、アバターの生成プロセスが開始されます。

ターミナルに下記のような結果が表示されているのを確認しましょう。

Checking assets...
Assets look great! We are good to go!

You can create a total of 56 distinct avatars

How many avatars would you like to create? Enter a number greater than 0: 100
What would you like to call this edition?: first-collection
Starting task...
100% (100 of 100)

#| Elapsed Time: 0:00:10 Time: 0:00:10
Generated 100 images, 30 are distinct
Removing 70 images...
Saving metadata...
Task complete!

ここでは、まず、100体のアバターを生成することをターミナルに入力し、最終的に30体のユニークなアバターを取得しています。

70体のアバターは重複していたため、排除されました。

⚠️: 注意

下記のいずれかの数が増えるほど、画像生成プログラムの処理時間が長くなります。

  • 特徴カテゴリの
  • それぞれのカテゴリに格納する画像
  • 生成するアバター

1200 体のアバターを生成する場合は、約 30 分かかります。※ Mac のプロセッサー 2.3 GHz Quad-Core Intel Core i5の場合。

👀 生成されたアバターを確認する

packages/libraryに向かい、新しく作成されたoutputフォルダを見ていきましょう。

What would you like to call this edition?で命名したeditionは下記のように保存されています。

editionフォルダの中のimagesフォルダを開き、下記のように、ユニークな「Scrappy Squirrels」のアバターが格納されていることを確認しましょう。

あなたのコレクションの中にmetadata.csvが存在しているかと思います。

このCSVファイルは、下記のようになっています。

	,background	,body	,eyes		,head_gear, ...
0 ,white ,maroon ,standard ,none, ...
1 ,white ,maroon ,standard ,none, ...
2 ,blue ,maroon ,standard ,std_lord, ...
3 ,blue ,maroon ,standard ,std_lord, ...
:

metadata.csvを使えば、特徴カテゴリごとに、それぞれのアバターにどんな画像が紐づいているか調べることができます。

  • どの特徴が一番希少性が高いか、どの特徴の組み合わせが最も多いかなど、生成されたアバターを分析する際に役立ちます。

🙋‍♂️ 質問する

ここまでの作業で何かわからないことがある場合は、Discordの#polygonで質問をしてください。

ヘルプをするときのフローが円滑になるので、エラーレポートには下記の3点を記載してください ✨

1. 質問が関連しているセクション番号とレッスン番号
2. 何をしようとしていたか
3. エラー文をコピー&ペースト
4. エラー画面のスクリーンショット

Generative Artが作成できたら、次のレッスンに進みましょう 🎉