NFT マイニング Dapp を構築するための最初のステップは、アートワークを準備することです。アートワークがなければ、NFT プロジェクトを実現することはできません。
アートワークを前処理するもう 1 つの理由は、各画像のメタデータを生成するためです。このメタデータがなければ、Opensea などの大きな二次市場で NFT を販売することはできません。
たとえば、下の画像は Opensea マーケットプレイスの NFT で、いくつかのメタデータが含まれています。これは以下にも表示されます。
アートワーク、その詳細、特徴を含む上記の情報は、下のIPFS画像で見ることができます.
ターミナルを開き、プロジェクト ディレクトリに移動するか、特定の場所にプロジェクト フォルダーを作成します。たとえば、端末で**mkdir preprocessor**
を実行すると、指定した場所に「 preprocessor 」というフォルダーが作成されます。
次に、ターミナルで次のコマンドを実行します。
cd preprocessor npm init -y npm install sharp @faker.js/faker --save-dev
上記のコマンドは、シャープとフェイカーの両方のライブラリをプロジェクトにインストールします。フェイカー ライブラリは、ランダムな情報を生成するのに役立ちます。一方、sharp ライブラリは、画像を特定の次元、品質、および形式に処理するのに役立ちます。
次に、 arts
というプロジェクト内のフォルダーと、 outputs
という別のフォルダーを作成します。 「arts」フォルダに加工用の画像を全て入れます。
上記の手順が完了したら、「VS コード」でプロジェクトを開きます。プロジェクト構造は次のようになります。
- preprocessor/ - arts/ - node_modules/ - outputs/ - package.json - package-lock.json
では、画像処理を担当するエンジンのコーディングに移りましょう。
このチュートリアルを完了するには、コンピューターに次のものがインストールされている必要があります。
プロジェクトのルートに**imagify.js**
というファイルを作成し、次のコードを貼り付けます
const fs = require('fs') const path = require('path') const sharp = require('sharp') const { faker } = require('@faker-js/faker') const input = './arts' const output = './outputs' let img_counter = 1 const imgSize = { width: 500, height: 500 } const desired_ext = '.webp' const base_url = 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/' const attributes = { weapon: [ 'Stick', 'Knife', 'Blade', 'Clube', 'Ax', 'Sword', 'Spear', 'Gun', 'Craft', ], environment: [ 'Space', 'Sky', 'Desert', 'Forest', 'Grassland', 'Moiuntains', 'Oceans', 'Rainforest', ], rarity: Array.from(Array(10).keys()), } fs.readdirSync(input).forEach((file) => { const orginal_ext = path.extname(file) const orginal_file_name = path.basename(file).split('.')[0] if (['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(orginal_ext)) { const id = img_counter const metadata = { id, name: `Adulam NFT #${id}`, description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: base_url + id + desired_ext, demand: faker.random.numeric({ min: 10, max: 100 }), attributes: [ { trait_type: 'Environment', value: attributes.environment.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Weapon', value: attributes.weapon.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Rarity', value: attributes.rarity.sort(() => 0.5 - Math.random())[0], max_value: 10, }, { display_type: 'date', trait_type: 'Created', value: Date.now(), }, { display_type: 'number', trait_type: 'generation', value: 1, }, ], } if (fs.existsSync(`${input}/${orginal_file_name + orginal_ext}`)) { sharp(`${input}/${orginal_file_name + orginal_ext}`) .resize(imgSize.height, imgSize.width) .toFile(`${output}/images/${id + desired_ext}`, (err, info) => console.log(err), ) fs.writeFileSync(`${output}/metadata/${id}.json`, JSON.stringify(metadata), { encoding: 'utf-8', flag: 'w', }) } console.log(metadata) img_counter++ } })
次の手順は、このメタデータ処理エンジンがどのように機能するかを理解するのに役立ちます。
必須ライブラリのインポート
const fs = require('fs') const path = require('path') const sharp = require('sharp') const { faker } = require('@faker-js/faker') const input = './arts' const output = './outputs'
fs
はファイル システムを表し、NodeJs に付属する組み込みモジュールです。マシンでのファイルの読み取りおよび書き込みアクティビティを管理する責任があります。
path
は、マシン上のディレクトリ構造をナビゲートするのに役立つ別のノード モジュールです。これは、画像が保存されている場所を特定するのに役立ちます。
Sharp は、サイズ変更や別のファイル タイプへの変換など、画像を処理するために使用するモジュールです。
フェイカーを使用して乱数を生成します。
最後に、 input
変数には、処理される画像が配置される場所と、処理された画像が保存される場所へのoutput
ポイントが含まれます。
重要な変数の定義
let img_counter = 1 const imgSize = { width: 500, height: 500 } const desired_ext = '.webp' const base_url = 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/' const attributes = { weapon: [ 'Stick', 'Knife', 'Blade', 'Clube', 'Ax', 'Sword', 'Spear', 'Gun', 'Craft', ], environment: [ 'Space', 'Sky', 'Desert', 'Forest', 'Grassland', 'Moiuntains', 'Oceans', 'Rainforest', ], rarity: Array.from(Array(10).keys()), }
上記のコードには、メタデータを生成する過程で使用される重要な変数が含まれています。
**Image_counter**
は、現在のイテレーションと一貫して画像に番号を付けるのに役立ちます。**ImgSize**
は、処理する各画像の幅と高さの寸法を定義します。**Desired_ext**
は、処理済みの画像に使用するファイル形式を表します。**Base_url**
は、イメージが IPFS に保存される場所を指定します。**Attributes**
には、各画像のメタデータに関する詳細情報が保持されます。
再帰タスクの実行
fs.readdirSync(input).forEach((file) => { if(['.jpg', '.jpeg', '.png', '.gif', '.webp'].includes(orginal_ext)) { // Images and metadata tasks are recursively performed here... } })
上記のコード ブロックでは、ファイル システム ライブラリ (fs) を使用して**input**
の場所 (arts) にあるすべての画像をループ処理しました。また、各画像について、承認された拡張子のリストからエンジンが画像のみを選択していることを確認しました。
メタデータ タスクの実行
const id = img_counter const metadata = { id, name: `Adulam NFT #${id}`, description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: base_url + id + desired_ext, demand: faker.random.numeric({ min: 10, max: 100 }), attributes: [ { trait_type: 'Environment', value: attributes.environment.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Weapon', value: attributes.weapon.sort(() => 0.5 - Math.random())[0], }, { trait_type: 'Rarity', value: attributes.rarity.sort(() => 0.5 - Math.random())[0], max_value: 10, }, { display_type: 'date', trait_type: 'Created', value: Date.now(), }, { display_type: 'number', trait_type: 'generation', value: 1, }, ], }
上記のコード ブロックでは、各メタデータ スペースに値を指定しました。たとえば、環境、武器、およびすべての特性値は、ランダムかつ動的に提供されます。
画像変換タスクの実行
if (fs.existsSync(`${input}/${orginal_file_name + orginal_ext}`)) { sharp(`${input}/${orginal_file_name + orginal_ext}`) .resize(imgSize.height, imgSize.width) .toFile(`${output}/images/${id + desired_ext}`, (err, info) => console.log(err), ) fs.writeFileSync(`${output}/metadata/${id}.json`, JSON.stringify(metadata), { encoding: 'utf-8', flag: 'w', }) } console.log(metadata) img_counter++
上記のスニペットでは、ファイル システム モジュールを再度使用して、最初に各アートワークを特定し、指定したサイズ (500 x 500) にサイズ変更しました。また、現在のイテレーションに合わせて新しい名前を付け、目的の拡張子 (webp) を付けました。
画像のサイズを変更してwebp
に変換すると、アートワークが驚くほどの高さに最適化されました。
たとえば、では、この画像前処理エンジンを合計111MB
のサイズの99
の画像に適用しました。サイズは、 .png
拡張子の場合は62MB
、 .webp
拡張子の場合は驚くべき4.5MB
にまで減少しました。この大幅なサイズの縮小は、私の画像で構築された Minting Web サイトの読み込み時間の大きな飛躍を説明しています。
最後に、上記のコード ブロックから、処理された各画像のJSON
メタデータを作成しました。このメタデータには、同じ名前と、画像の場所を指す URL の両方が含まれています。このメタデータは、画像の処理後に IPFS にデプロイするものです。
次に、以下のコマンドを実行して、画像を変換します。プロジェクトフォルダーにいることを確認してください。
node imagify.js
この時点で、画像エンジンの使用は完了です。結果として、出力フォルダーは次のファイル構造を持つはずです。
- output/ - images - 1.webp - 2.webp - ...... - metadata - 1.json - 2.json - ......
IPFS は惑星間ファイル システムの略で、ピアツーピアで分散化されています。 IPFS に保存されたデータを引き出す簡単な方法はないため、メディア コンテンツを保存するためのブロックチェーン アプリケーションと一緒に使用するのにほぼ完璧なピアです。
簡単で混乱の少ない方法を使用するには、IPFS デスクトップ アプリのインストール ページに移動し、そこに指定されている指示に従います。
インストールが成功したら、IPFS アプリを開いて最初にアップロードします。繰り返しますが、最初に画像フォルダーをアップロードします。
一意の CID (コンテンツ識別) 文字列がフォルダ名の一部として生成されます。下の画像を参照してください。
ここで、上の画像からわかるように画像フォルダー CID をコピーし、 **imagify.js**
コードで置き換えます。以下のコードを参照してください。
const base_url = "https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/" //old string const base_url = "https://ipfs.io/ipfs/QmY1zrFibpdHQ7qcqZqq7THsqTremZYepXNWR5Au3MF1ST/" //new string
ここで、 **node imagify.js**
を再度実行して、各画像の正確な場所をJSONメタデータに含めます。 CID の置換前後で生成された JSON メタデータの例を参照してください。
このビデオを見て、完全な NFT ミンティング プロジェクトでこれらの画像とメタデータをどのように使用したかを理解できます。
CID交換前
{ id: 97, name: 'Adulam NFT #97', description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: 'https://ipfs.io/ipfs/REPLACE_WITH_IPFS_CID/97.webp', demand: '4', attributes: [ { trait_type: 'Environment', value: 'Forest' }, { trait_type: 'Weapon', value: 'Craft' }, { trait_type: 'Rarity', value: 4, max_value: 10 }, { display_type: 'date', trait_type: 'Created', value: 1664478034024 }, { display_type: 'number', trait_type: 'generation', value: 1 } ] }
CID 交換後
{ id: 97, name: 'Adulam NFT #97', description: 'AI Arts NFTs Collection, Mint and collect the hottest NFTs around.', price: 1, image: 'https://ipfs.io/ipfs/QmY1zrFibpdHQ7qcqZqq7THsqTremZYepXNWR5Au3MF1ST/97.webp', demand: '7', attributes: [ { trait_type: 'Environment', value: 'Moiuntains' }, { trait_type: 'Weapon', value: 'Clube' }, { trait_type: 'Rarity', value: 2, max_value: 10 }, { display_type: 'date', trait_type: 'Created', value: 1664478110287 }, { display_type: 'number', trait_type: 'generation', value: 1 } ] }
最後に、下の画像に示すように、images フォルダーと一緒にメタデータ フォルダーを IPFS にアップロードします。
素晴らしいです。では、ウェブにピン留めして世界中に公開しましょう。現在、両方のフォルダーがローカルの IPFS ノード (コンピューター) に置かれています。世界中からアクセスできるようにするには、 Pinataなどのピン留めサービスを使用する必要があります。
まず、 Pinata ピン マネージャーにアクセスし、サインアップしたことがない場合はサインアップします。次に、アカウント アイコンをクリックし、[API キー] を選択します。下の画像を参照してください。
キーの作成ページで、[新しいキーの作成] をクリックし、キーの名前を入力します。下の画像を見てください。
JWT キーをクリップボードにコピーします。これは、IPFS デスクトップを Pinata アカウントにリンクするために使用するものです。下の画像を参照してください。
次に、IPFS デスクトップ アプリケーションを開き、設定タブに移動して新しいサービスを追加し、Pinata を選択して、提供されたスペースに JWT トークンを貼り付けます。下の画像を参照してください。
最後に、以下の手順を使用して、実際にフォルダーを Pinata にピン留めします。
[ファイル] タブに移動し、三重の点線をクリックして、[固定の設定] を選択します。これは、下の画像にポップアップ表示されます。
ピニャータを選択して適用すると、画像フォルダーにグローバルにアクセスできるようになります。
この Web サイトにアクセスし、CID をコピーして IPFS 入力フィールドに貼り付け、キャッシュ ボタンをクリックします。これにより、公開されている IPFS ゲートウェイのセット全体がスキャンされ、イメージが検索されます。下の画像を参照してください。
上の画像の結果は、ローカル ノードで元のコピーを削除した場合でも、多くの IPFS ノードで images フォルダーのコピーが使用可能になり、グローバルにアクセスできることを示しています。
手順が明確に説明されているので、メタデータ フォルダーをピン留めして、オンラインで公開できるようにします。
これで、上の画像のリンクのいずれかをERC721トークンのベース URL として使用できます。下の画像を参照してください。
これで、アートワークを準備して IPFS にアップロードする方法がわかりました。
アートワークを前処理して IPFS にバッチ スケールでアップロードする方法を理解する必要が常にあります。
IPFS への画像の処理方法と処理方法を理解したら、特別な web3 プロジェクトで使用を開始できます。
次回まで、潰し続けてください!
Goerli テストネットで私の NFT プロジェクトのライブ デモの使用状況を参照してください。 ここでOpensea の場所を参照してください。私のYouTubeチャンネルでビデオバージョンを見ることができます。
私はソフトウェア開発業界で6+
年以上の経験を持つフルスタックのブロックチェーン開発者です。
ソフトウェア開発、執筆、教育を組み合わせることで、EVM 互換のブロックチェーン ネットワーク上で分散型アプリケーションを構築する方法を示します。
私のスタックには、 JavaScript
、 React
、 Vue
、 Angular
、 Node
、 React Native
、 NextJs
、 Solidity
などが含まれます。
私の YouTube チャンネルに登録して、Web3 アプリをゼロから構築する方法を学んでください。また、メンターからマンツーマンで学びたい真面目な人のために、プライベートで専門的なクラスも提供しています。
それでは、上記の画像とメタデータをコードで表現する方法を紹介しましょう。