初回ハイブリッドコレクションの作成

Last updated September 17, 2024

このガイドでは、ハイブリッドコレクションを完全にエンドツーエンドで作成する方法を実演します。必要なすべてのアセットを作成する方法から、エスクローの作成、代替可能トークンから非代替可能トークンへのスワップ、およびその逆のパラメータ設定まで!

MPL-Hybridとは何ですか?

MPL-Hybridは、デジタルアセット、web3ゲーム、オンチェーンコミュニティのための新しいモデルです。このモデルの中核は、固定数の代替可能アセットと非代替可能アセットを相互に取引するスワッププログラムです。

前提条件

  • 任意のコードエディタ(Visual Studio Code推奨)
  • Node 18.x.x以上。

初期セットアップ

このガイドでは、Javascriptを使用してハイブリッドコレクションを作成する方法を教えます!あなたのニーズに合わせて機能を変更・移動する必要があるかもしれません。

プロジェクトの初期化

任意のパッケージマネージャー(npm、yarn、pnpm、bun)で新しいプロジェクトを初期化し(オプション)、プロンプトが表示されたら必要な詳細を入力します。

npm init

必要なパッケージ

このガイドに必要なパッケージをインストールします。

npm i @metaplex-foundation/umi
npm i @metaplex-foundation/umi-bundle-defaults
npm i @metaplex-foundation/mpl-core
npm i @metaplex-foundation/mpl-hybrid
npm i @metaplex-foundation/mpl-token-metadata

準備

代替可能トークンを非代替可能トークン(NFT)に交換したりその逆を促進するMPL-Hybridプログラムのエスクローを設定する前に、Core NFTのコレクションと代替可能トークンの両方が既にミントされている必要があります。

これらの前提条件のいずれかが不足している場合でも心配いりません!各ステップを進めるために必要なすべてのリソースを提供します。

注意: 動作するためには、エスクローにNFT、代替可能トークン、またはその両方の組み合わせで資金提供する必要があります。エスクローのバランスを維持する最も簡単な方法は、一方のタイプのアセットで完全に満たし、もう一方を配布することです!

NFTコレクションの作成

MPL-Hybridプログラムでメタデータランダム化機能を利用するには、オフチェーンメタデータURIが一貫した増分構造に従う必要があります。このため、TurboSDKと組み合わせてArweaveのパスマニフェスト機能を使用します。

マニフェストにより、複数のトランザクションを単一のベーストランザクションID下でリンクし、人間が読める形式のファイル名を割り当てることができます:

  • https://arweave.net/manifestID/0.json
  • https://arweave.net/manifestID/1.json
  • ...
  • https://arweave.net/manifestID/9999.json

決定論的URIの作成に慣れていない場合は、詳細な手順についてこのガイドに従ってください。さらに、Hybridプログラムが機能するために必要なコレクションアセットの作成手順を見つけることができます。

注意: 現在、MPL-Hybridプログラムは提供されたmin/maxURIインデックス間の数をランダムに選択し、URIが既に使用されているかをチェックしません。そのため、スワッピングは誕生日パラドックスの影響を受けます。プロジェクトが十分なスワップランダム化の恩恵を受けるため、ランダムに選択できる最低250kのアセットメタデータを準備してアップロードすることをお勧めします。利用可能な潜在的アセットが多いほど良いです!

代替可能トークンの作成

MPL-Hybridエスクローには、NFTのリリースを償還または支払うために使用できる関連代替可能トークンが必要です。これは、既にミントされて流通している既存のトークンでも、完全に新しいトークンでも構いません!

トークンの作成に慣れていない場合は、このガイドに従って、Solanaで独自の代替可能トークンをミントする方法を学ぶことができます。

エスクローの作成

NFTコレクションとトークンの両方を作成した後、ついにエスクローを作成してスワッピングを開始する準備が整いました!

しかし、MPL-Hybridに関する関連情報に飛び込む前に、ガイド中に複数回実行することになるので、Umiインスタンスの設定方法を学ぶことをお勧めします。

Umiの設定

Umiを設定する際、さまざまなソースからキーペア/ウォレットを使用または生成できます。テスト用に新しいウォレットを作成し、ファイルシステムから既存のウォレットをインポートするか、ウェブサイト/dAppを作成している場合はwalletAdapterを使用できます。

注意: この例ではgeneratedSigner()でUmiを設定しますが、以下のすべての可能な設定を見つけることができます!

注意: walletAdapterセクションは、walletAdapterを既にインストールして設定していることを前提として、Umiに接続するために必要なコードのみを提供しています。包括的なガイドについては、これを参照してください

パラメータの設定

Umiインスタンスを設定した後、次のステップはMPL-Hybridエスクローに必要なパラメータを設定することです。

エスクロー契約の一般設定を定義することから始めます:

// エスクロー設定 - これらをあなたのニーズに変更してください
const name = "MPL-404 Hybrid Escrow";
const uri = "https://arweave.net/manifestId";
const max = 15;
const min = 0;
const path = 0;
パラメータ説明
Nameエスクロー契約の名前(例:"MPL-404 Hybrid Escrow")。
URINFTコレクションのベースURI。これは決定論的メタデータ構造に従う必要があります。
Max & Minコレクションのメタデータの決定論的URIの範囲を定義します。
Path2つのパス間で選択:0はスワップ時にNFTメタデータを更新、1はスワップ後もメタデータを変更しません。

次に、エスクローに必要なキーアカウントを設定します:

// エスクローアカウント - これらをあなたのニーズに変更してください
const collection = publicKey('<YOUR-COLLECTION-ADDRESS>');
const token = publicKey('<YOUR-TOKEN-ADDRESS>');
const feeLocation = publicKey('<YOUR-FEE-ADDRESS>');
const escrow = umi.eddsa.findPda(MPL_HYBRID_PROGRAM_ID, [
string({ size: 'variable' }).serialize('escrow'),
publicKeySerializer().serialize(collection),
]);
アカウント説明
Collectionスワップされるコレクション。これはNFTコレクションのアドレスです。
Tokenスワップされるトークン。これは代替可能トークンのアドレスです。
Fee Locationスワップからの手数料が送信されるアドレス。
Escrow派生エスクローアカウント。スワッププロセス中にNFTとトークンを保持する責任があります。

最後に、トークン関連のパラメータを定義し、小数点用にトークン量を調整するaddZeros()ヘルパー関数を作成します:

// トークンスワップ設定 - これらをあなたのニーズに変更してください
const tokenDecimals = 6;
const amount = addZeros(100, tokenDecimals);
const feeAmount = addZeros(1, tokenDecimals);
const solFeeAmount = addZeros(0, 9);
// 数値にゼロを追加する関数、小数点の正しい数を追加するために必要
function addZeros(num: number, numZeros: number): number {
return num * Math.pow(10, numZeros)
}
パラメータ説明
Amountスワップ中にユーザーが受け取るトークンの量、小数点で調整済み。
Fee AmountNFTにスワップする際にユーザーが支払うトークン手数料の量。
Sol Fee AmountNFTにスワップする際に請求される追加手数料(SOL単位)、Solanaの9桁小数点で調整済み。

エスクローの初期化

設定したすべてのパラメータと変数を渡して、initEscrowV1()メソッドを使用してエスクローを初期化できるようになりました。これにより独自のMPL-Hybridエスクローが作成されます。

const initEscrowTx = await initEscrowV1(umi, {
name,
uri,
max,
min,
path,
escrow,
collection,
token,
feeLocation,
amount,
feeAmount,
solFeeAmount,
}).sendAndConfirm(umi);
const signature = base58.deserialize(initEscrowTx.signature)[0]
console.log(`Escrow created! https://explorer.solana.com/tx/${signature}?cluster=devnet`)

注意: 前述の通り、単純にエスクローを作成するだけでは、スワッピングに「準備完了」にはなりません。エスクローにNFTまたはトークン(またはその両方)を投入する必要があります。方法は次のとおりです

完全なコード例

エスクロー作成の完全なコードを単純にコピー&ペーストしたい場合は、こちらです!

キャプチャ & リリース

アカウントの設定

Umiを設定した後(前のセクションで行ったように)、次のステップはキャプチャ & リリースプロセスに必要なアカウントを設定することです。これらのアカウントは以前に使用したものと似ており親しみやすく、両方の指示で同じです:

// ステップ2: エスクローアカウント - これらをあなたのニーズに変更してください
const collection = publicKey('<YOUR-COLLECTION-ADDRESS>');
const token = publicKey('<YOUR-TOKEN-ADDRESS>');
const feeProjectAccount = publicKey('<YOUR-FEE-ADDRESS>');
const escrow = umi.eddsa.findPda(MPL_HYBRID_PROGRAM_ID, [
string({ size: 'variable' }).serialize('escrow'),
publicKeySerializer().serialize(collection),
]);

注意: feeProjectAccountは最後のスクリプトのfeeLocationフィールドと同じです。

キャプチャ/リリースするアセットの選択

キャプチャおよびリリースするアセットの選択方法は、エスクロー作成時に選択したパスによります:

  • パス0: パスが0に設定されている場合、NFTメタデータはスワップ中に更新されるため、これは関係ないのでエスクローからランダムなアセットを取得できます。
  • パス1: パスが1に設定されている場合、NFTメタデータはスワップ後も同じままなので、ユーザーにスワップしたい特定のNFTを選択させることができます。

キャプチャの場合

NFTをキャプチャしている場合、エスクローが所有するランダムなアセットを選択する方法は次のとおりです:

// コレクション内のすべてのアセットを取得
const assetsListByCollection = await fetchAssetsByCollection(umi, collection, {
skipDerivePlugins: false,
})
// エスクローが所有するアセットを検索
const asset = assetsListByCollection.filter(
(a) => a.owner === publicKey(escrow)
)[0].publicKey

リリースの場合

NFTをリリースしている場合、通常はリリースしたいNFTをユーザーが選択します。しかし、この例では、ユーザーが所有するランダムなアセットを選択します:

// コレクション内のすべてのアセットを取得
const assetsListByCollection = await fetchAssetsByCollection(umi, collection, {
skipDerivePlugins: false,
})
// 通常はユーザーが交換対象を選択します
const asset = assetsListByCollection.filter(
(a) => a.owner === umi.identity.publicKey
)[0].publicKey

キャプチャ(代替可能から非代替可能)

最後に、キャプチャ指示について話しましょう。これは代替可能トークンをNFTにスワップするプロセスです(スワップに必要なトークン量はエスクロー作成時に設定されます)。

// 代替可能トークンをスワップしてNFTをキャプチャ
const captureTx = await captureV1(umi, {
owner: umi.identity.publicKey,
escrow,
asset,
collection,
token,
feeProjectAccount,
amount,
}).sendAndConfirm(umi);
const signature = base58.deserialize(captureTx.signature)[0];
console.log(`Captured! Check it out: https://explorer.solana.com/tx/${signature}?cluster=devnet`);

リリース(非代替可能から代替可能)

リリースはキャプチャの反対です—ここではNFTを代替可能トークンにスワップします:

// NFTをリリースして代替可能トークンを受け取る
const releaseTx = await releaseV1(umi, {
owner: umi.payer,
escrow,
asset,
collection,
token,
feeProjectAccount,
}).sendAndConfirm(umi);
const signature = base58.deserialize(releaseTx.signature)[0];
console.log(`Released! Check it out: https://explorer.solana.com/tx/${signature}?cluster=devnet`);

完全なコード例

キャプチャリリースの完全なコードは次のとおりです