【thirdweb】NFT の作り方 ~みんなで NFT を作って売買してみよう~
この記事は NBU アプリ開発プロジェクト Advent Calendar 2023 の 12月11日の記事です。
はじめに
今年、HOPTER TECH SCHOOL × 名古屋文理大学 アプリ開発プロジェクト の共同チーム「Chicks」が制作した作品「Fri+Lenz」がNagoya Web3 Hackathon 2023で最優秀賞を受賞しました。
こちらの作品は、友達との思い出の写真の NFT をキーホルダーに保存し、写真を見るときは、友達全員のキーホルダーが無いと見られないというものです。めちゃくちゃエモくないですか?
ハッカソンめちゃ楽しかったです!Chicksの皆さん、Nagoya Blockchainの皆さん、ありがとうございました!
NFT とは、このような技術です。
つまり、NFT は「その人しか持っていない」、「別のものに置き換えられない」、「存在が絶対的に証明される」ということが特徴で、いろいろなところに活用されているようです。
NFT(New Future Technology)―新しい未来の技術―ではないでしょうか。
この記事では、この NFT のエモさを皆さんにご体感していただくべく、画像の NFT の作成・販売・購入を行う手順をご紹介したいと思います。
準備
MetaMask のセットアップ
MetaMask を Chrome にインストールします。MetaMask のアカウントを持っていない人は、アカウント作成画面に飛ばされると思うので、アカウントを作成してください。
MetaMask はブロックチェーン上のウォレットと呼ばれるもので、ウォレットアドレスという一意のアドレスを持っています。NFT をこのウォレットアドレスと紐づけることで、誰が所有している NFT かを識別します。
test-MATIC の入手
test-MATIC というブロックチェーン上のお金(トークン)を入手します。
ブロックチェーン上で取引などをおこなった際に発生するネットワーク手数料(ガス代)を支払うために使用します。
それでは、https://faucet.polygon.technology/ にアクセスします。
Connect to Discord で Discord アカウントに接続します。
Discord を開くと Polygon サーバから招待が来ているので参加します。
ネットワークは Mumbai を選択
トークンは MATIC を選択
test-MATIC を受け取るウォレットアドレスを入力
ウォレットアドレスは MetaMask の場合、以下で確認できます。
Submit → confirm
少し経つと 0.2 MATIC が追加されていると思います。
NFT の作成
thirdweb のセットアップ
https://thirdweb.com/dashboard にアクセスします。
Connect Wallet → MetaMask → Sign in
MetaMask が立ち上がるので「署名」を押下
thirdweb アカウントの作成を求められるので、指示に従って作成します。
以上で、thirdweb のセットアップは完了です。
NFT Collection コントラクト作成
コントラクトとは、主にスマートコントラクトのことで、ブロックチェーン上で実行される自己実行型のプログラムです。このプログラムが実行されると、実行結果がブロックチェーン上に書き込まれます。
例えば、「NFT を作成する」ということは、「NFT を作成するためのコントラクトを実行する」ということです。
コントラクトは、自分でコードを書いて作成しなくてはなりません。しかし、thirdweb を使用すれば、あらかじめよく使われるコントラクトが既に揃っているので、それらを利用すればコードを書くことなくコントラクトを作成できます。
今回は、NFT を作成するコントラクトである NFT Collection コントラクトを作成します。
Dashboard ページの Contracts に遷移します。
Deploy contract を押下
NFTs の中の NFT Collenction を押下
Deploy now を押下
以下のように入力します。
Image: 好きな画像をアップロード(コントラクトのサムネイルになります。アップロードしなくてもOK)
Name: testnftcol(コントラクトの名前です。任意の名前を付けられます。)
Symbol: tnc(トークンの単位になります。任意の単位を付けられます。)
Network / Chain が Mumbai になっていることを確認します。
その他入力欄はデフォルトのままにします。
Deploy Now を押下
MetaMask が立ち上がるので、「確認」を押下
もう一度 MetaMask が立ち上がるので、「署名」を押下
これで、NFT を作成するためのコントラクトが作成できました。
NFT の Mint
Mint(ミント)とは、新しい NFT を作成し、その NFT 対する所有権を確立するプロセスです。
NFT を作成することは、一般的に Mint することを言います。
NFT の Mint は thirdweb 上で GUIを使って簡単に出来ます。しかし、NFT をプロダクトに組み込むときは、Mint をプログラムで自動化すると思うので、その方法を紹介します。
thirdweb には SDK があるので、これを使用すればコード上で簡単に Mint ができます。
thirdwebSDK が対応している言語には
JavaScript ( Node.js )
React
React Native
Python
Go
Unity
があります。
※ 私は、Python と JavaScript で使用したことがありますが、言語によって SDK の完成度が異なるらしく、JavaScript では使えるのに Python では使えないメソッドがありました。最低限のメソッドを使う分にはどの言語でも良いと思いますが、複雑な実装を行う場合は thirdwebSDK の完成度とプロジェクトの要件に合わせて、適切な言語を選択した方が良さそうです。
今回は、JavaScript を使用していきます。
実行環境は、
node: v21.4.0
npm: 10.2.5
です。
まずは、thirdwebSDK をインストールします。
npm install @thirdweb-dev/sdk ethers@5
package.json の中身をこのように変更します。
{
"type": "module", // この行を追加
"dependencies": {
"@thirdweb-dev/sdk": "^4.0.19",
"ethers": "^5.7.2"
}
}
次に、Mint する関数を書きます。<この中身>は下記の方法で取得してペーストしてください。名前、説明、画像の URL は好きなものに設定してください。
// index.js
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
// チェーンを設定
const CHAIN = "mumbai";
// プライベートキー設定
const PRIVATE_KEY = "<プライベートキー>";
// シークレットキー設定
const SECRET_KEY = "<シークレットキー>";
// NFT Collectionのコントラクトアドレス
const NFT_COLLECTION_CONTRACT_ADDRESS = "<NFT Collectionのコントラクトアドレス>";
// SDK オブジェクト生成
const sdk = ThirdwebSDK.fromPrivateKey(
PRIVATE_KEY,
CHAIN,
{
secretKey: SECRET_KEY,
}
);
// NFT Collectionのコントラクトオブジェクト生成
const contractNftCollection = await sdk.getContract(NFT_COLLECTION_CONTRACT_ADDRESS);
/**
* メイン関数
*/
const main = async () => {
mint("テスト", "このNFTはテストです", "https://pbs.twimg.com/media/GAbydfNbIAAaJap?format=jpg&name=large");
}
/**
* ミントする関数
* @param {string} name - 名前
* @param {string} description - 説明
* @param {string} image - 画像のURL
* @returns {int} - NFT Collection コントラクトでのトークンID(10進数文字列)
*/
const mint = async (name, description, image) => {
// Custom metadata of the NFT, note that you can fully customize this metadata with other properties.
const metadata = {
name: name,
description: description,
image: image,
external_url: image,
background_color: "FFF",
customImage: image
// ... Any other metadata you want to include
};
const txResult = await contractNftCollection.erc721.mint(metadata);
return parseInt(txResult.id._hex, 16).toString();
}
main();
シークレットキーを取得する方法は、thirdweb Dashboard の Settings ページの API Keys の Create API key で key name を入力し、Allow all domains にチェックを入れて Next → Proceed で secret_key が表示されるのでコピーしてどこかにメモしておきます。このシークレットキーは二度と表示されないため、失くしてしまったら新しく作成する必要があります。
プライベートキーを取得する方法は、MetaMask を開き、三点リーダーを押下 → アカウントの詳細 → 秘密鍵を表示 で確認できます。プライベートキーは流出すると、ウォレット内の資産が盗まれる危険があるので取り扱いには十分に注意してください。資産を既に運用している方は、プログラム実行用の新しいウォレットアカウントを作成することをお勧めします。
NFT Collection のコントラクトアドレスは、thirdweb Dashboard の Contracts の CONTRACT ADDRESS 欄からコピーできます。
※ このように、APIキー等をコード内に直接書くのは良くありません。本番では環境変数を使用しましょう。コードを GitHub に上げるときに痛い目に遭います。私は完全にやらかしました。
それでは、Mint する関数を実行します。
node index.js
thirdweb Dashboard の Contracts にある作成したコントラクトをクリックし、Overview を見るとこのように NFT が作成されていると思います。
これで、NFT の Mint は出来ました。
NFT の販売
Marketplace コントラクト作成
NFT を販売するには、NFT を販売するコントラクト(Marketplace コントラクト)を作成しなければなりません。
これも、先ほどと同じように thirdweb を使って作成します。
Dashboard ページの Contracts に遷移します。
Deploy contract を押下
Marketplaces の中の MarketplaceV3 を押下
Deploy now を押下
以下のように入力します。
Image: 好きな画像をアップロード(コントラクトのサムネイルになります。アップロードしなくてもOK)
Name: testnftmkp(コントラクトの名前です。任意の名前を付けられます。)
Symbol: tnm(トークンの単位になります。任意の名前を付けられます。)
Network / Chain が Mumbai になっていることを確認します。
その他入力欄はデフォルトのままにします。
Deploy Now を押下
例の如く、MetaMask で2回承認します。
これで、Marketplace コントラクトが作成できました。
NFT の Direct Listing を作成
作成した NFT を Marketplace コントラクトに紐づけることで NFT を販売できます。これを 「Direct Listing を作成する」と言います。
先ほどのプログラムに Direct Listing を作成する関数を追加します。
// index.js
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
// チェーンを設定
const CHAIN = "mumbai";
// プライベートキー設定
const PRIVATE_KEY = "<プライベートキー>";
// シークレットキー設定
const SECRET_KEY = "<シークレットキー>";
// NFT Collectionのコントラクトアドレス
const NFT_COLLECTION_CONTRACT_ADDRESS = "<NFT Collectionのコントラクトアドレス>";
// Marketplaceのコントラクトアドレス // 追加
const MARKETPLACE_CONTRACT_ADDRESS = "<Marketplaceのコントラクトアドレス>"; // 追加
// SDK オブジェクト生成
const sdk = ThirdwebSDK.fromPrivateKey(
PRIVATE_KEY,
CHAIN,
{
secretKey: SECRET_KEY,
}
);
// NFT Collectionのコントラクトオブジェクト生成
const contractNftCollection = await sdk.getContract(NFT_COLLECTION_CONTRACT_ADDRESS);
// Marketplaceのコントラクトオブジェクト生成 // 追加
const contractMarketplace = await sdk.getContract(MARKETPLACE_CONTRACT_ADDRESS); // 追加
/**
* メイン関数
*/
const main = async () => {
// mint("テスト", "このNFTはテストです", "https://pbs.twimg.com/media/GAbydfNbIAAaJap?format=jpg&name=large"); // 変更
directListing(0); // 追加
}
/**
* ミントする関数
* @param {string} name - 名前
* @param {string} description - 説明
* @param {string} image - 画像のURL
* @returns {int} - NFT Collection コントラクトでのトークンID(10進数文字列)
*/
const mint = async (name, description, image) => {
// Custom metadata of the NFT, note that you can fully customize this metadata with other properties.
const metadata = {
name: name,
description: description,
image: image,
external_url: image,
background_color: "FFF",
customImage: image
// ... Any other metadata you want to include
};
const txResult = await contractNftCollection.erc721.mint(metadata);
return parseInt(txResult.id._hex, 16).toString();
}
// ==== ↓追加↓ ====
/**
* マーケットに登録する関数
* @param {int} nftCollectionId - NFT CollectionコントラクトでのトークンID(10進数文字列)
* @returns {int} - MarketplaceコントラクトでのトークンID(10進数文字列)
*/
const directListing = async (nftCollectionId) => {
const txResult = await contractMarketplace.directListings.createListing({
assetContractAddress: NFT_COLLECTION_CONTRACT_ADDRESS, // Required - smart contract address of NFT to sell
tokenId: nftCollectionId, // Required - token ID of the NFT to sell
pricePerToken: "0.001", // Required - price of each token in the listing
quantity: "1", // Optional - number of tokens to sell (1 for ERC721 NFTs)
startTimestamp: new Date(), // Optional - when the listing should start (default is now)
endTimestamp: new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000), // Optional - when the listing should end (default is 7 days from now)
});
return parseInt(txResult.id._hex, 16).toString();
}
// ==== ↑追加↑ ====
main();
実行すると、先ほど作成した NFT の Direct Listing が作成されています。
そして、この NFT の販売サイトはもう thirdweb が作成してくれているんです。
thirdweb Dashboard ページの作成した Marketplace コントラクトの Embed の Embed Code にある src="https://… にアクセスすると販売サイトにアクセスできます。
Buy をクリックすると MetaMask が立ち上がり、NFT を購入できます。
そして、この URL は "&directListingId=0" ここを変えると別の NFT も販売できるので、このようなコードを書いて、directListingId をフロントに渡せば全自動的に NFT を作成・販売するサイトが作れそうです。
index.js
// 省略
/**
* メイン関数
*/
const main = async () => {
const nftCollectionId = await mint("テスト2", "このNFTはテスト2です", "https://pbs.twimg.com/media/GAbydfNbIAAaJap?format=jpg&name=large");
const directListingId = await directListing(nftCollectionId);
console.log(directListingId);
}
// 省略
購入した NFT の確認方法
https://testnets.opensea.io/ja にアクセスして、MetaMask を接続し、プロフィールを見ると、購入した NFT を確認できます。
自分で作成・販売している NFT は誰かに購入されるまで、自分のものになっています。
まとめ
このように、thirdweb を使えば NFT を簡単に作成することが出来ます。
thirdwebSDK には、他にも様々なメソッドがあるので、NFT を取り入れたいプロジェクトがあった際は、ぜひ使ってみてください。
ご精読いただきありがとうございました。
この記事が参加している募集
この記事が気に入ったらサポートをしてみませんか?