機能

特別なガード命令

前のページで見たように、ガードはキャンディマシンのミントプロセスをカスタマイズする強力な方法です。しかし、ガードが独自のカスタム命令を提供することもできることをご存知でしたか?

ルート命令

キャンディガードプログラムには**「ルート」命令**と呼ばれる特別な命令が付属しています。

この命令により、キャンディマシンから特定のガードを選択し、そのガードに固有のカスタム命令を実行できます。選択されたガードにリクエストをルーティングするため、「ルート」命令と呼んでいます。

この機能により、ガードは独自のプログラムロジックを含むことができるため、さらに強力になります。これにより、ガードは以下のことができます:

  • 重い操作について、検証プロセスをミントプロセスから分離する。
  • そうでなければカスタムプログラムのデプロイが必要なカスタム機能を提供する。

ルート命令を呼び出すには、どのガードにその命令をルーティングしたいかを指定し、そのガードが期待するルート設定を提供する必要があります。それをサポートしていないガードを選択して「ルート」命令を実行しようとすると、トランザクションは失敗することに注意してください。

キャンディガードプログラムで登録されたガードごとに「ルート」命令は1つしかないため、同じガードが提供する複数の機能を区別するためにルート設定でパス属性を提供することが一般的です。

例えば、フローズンNFT — ミントが終了してからのみ解凍できる — のサポートを追加するガードは、そのルート命令を使用してトレジャリーエスクローアカウントを初期化し、適切な条件下で誰でもミントされたNFTを解凍できるようにできます。前者には「init」、後者には「thaw」に等しいパス属性を使用してこれら2つの機能を区別できます。

それをサポートする各ガードのルート命令とその基本パスの詳細な説明は、それぞれのページで見つけることができます。

例を提供してルート命令の動作を説明するために少し時間を取りましょう。例えば、許可リストガードは、ミントウォレットが事前設定されたウォレットのリストの一部であることを検証するためにルート命令をサポートしています。

これはMerkle Treesを使用して行います。つまり、許可されたウォレットの全リストのハッシュを作成し、そのハッシュ — Merkle Rootとして知られる — をガード設定に保存する必要があります。ウォレットが許可リストにあることを証明するには、プログラムがMerkle Rootを計算し、それがガードの設定と一致することを確認できるハッシュのリスト — Merkle Proofとして知られる — を提供する必要があります。

したがって、許可リストガードはそのルート命令を使用して指定されたウォレットのMerkle Proofを検証し、成功した場合、ミント命令の検証証明として機能するブロックチェーン上の小さなPDAアカウントを作成します。

では、なぜミント命令内でMerkle Proofを直接検証できないのでしょうか?それは単純に、大きな許可リストの場合、Merkle Proofがかなり長くなる可能性があるからです。一定のサイズを超えると、既にかなりの量の命令を含むミントトランザクション内にそれを含めることが不可能になります。検証プロセスをミントプロセスから分離することで、許可リストを必要な大きさにすることが可能になります。

ガードのルート命令の呼び出し

Umiライブラリを使用して、route関数を使ってガードのルート命令を呼び出せます。guard属性経由でガードの名前を渡し、routeArgs属性経由でそのルート設定を渡す必要があります。

ミント前にウォレットのMerkle Proofを検証する許可リストガードを使用した例です。

import {
create,
route,
getMerkleProof,
getMerkleRoot,
} from '@metaplex-foundation/mpl-candy-machine'
// 許可リストを準備します。
// リストの最初のウォレットがMetaplexアイデンティティであると仮定しましょう。
const allowList = [
'GjwcWFQYzemBtpUoN5fMAP2FZviTtMRWCmrppGuTthJS',
'2vjCrmEFiN9CLLhiqy8u1JPh48av8Zpzp3kNkdTtirYG',
'AT8nPwujHAD14cLojTcB1qdBzA1VXnT6LVGuUd6Y73Cy',
]
const merkleRoot = getMerkleRoot(allowList)
// 許可リストガード付きキャンディマシンを作成します。
await create(umi, {
// ...
guards: {
allowList: some({ merkleRoot }),
},
}).sendAndConfirm(umi)
// 今ミントしようとすると、Merkle Proofを検証していないため失敗します。
// ルート命令を使用してMerkle Proofを検証します。
await route(umi, {
candyMachine: candyMachine.publicKey,
guard: 'allowList',
routeArgs: {
path: 'proof',
merkleRoot,
merkleProof: getMerkleProof(
allowList,
'GjwcWFQYzemBtpUoN5fMAP2FZviTtMRWCmrppGuTthJS'
),
},
}).sendAndConfirm(umi)
// 今ミントしようとすると、成功します。

APIリファレンス: route, DefaultGuardSetRouteArgs

グループ付きルート命令

ガードグループを使用しながらルート命令を呼び出す際、選択したいガードのグループラベルを指定することが重要です。これは、異なるグループ間で同じタイプの複数のガードを持つ可能性があり、プログラムがルート命令でどれを使用すべきかを知る必要があるからです。

例えば、一つのグループに厳選されたVIPウォレットの許可リストがあり、別のグループに抽選の当選者の別の許可リストがあったとします。その場合、許可リストガードのMerkle Proofを検証したいと言うだけでは不十分で、どのグループでその検証を実行すべきかも知る必要があります。

ルート命令を呼び出す際にグループでフィルタリング

グループを使用する際、Umiライブラリのroute関数は、選択したいグループのラベルに設定する必要があるOption<string>タイプの追加のgroup属性を受け入れます。

import {
create,
route,
getMerkleProof,
getMerkleRoot,
} from "@metaplex-foundation/mpl-candy-machine";
import { base58PublicKey, some } from "@metaplex-foundation/umi";
// 許可リストを準備します。
const allowListA = [...];
const allowListB = [...];
// 2つの許可リストガード付きキャンディマシンを作成します。
await create(umi, {
// ...
groups: [
{
label: "listA",
guards: {
allowList: some({ merkleRoot: getMerkleRoot(allowListA) }),
},
},
{
label: "listB",
guards: {
allowList: some({ merkleRoot: getMerkleRoot(allowListB) }),
},
},
],
}).sendAndConfirm(umi);
// どのグループを選択するかを指定してMerkle Proofを検証します。
await route(umi, {
candyMachine: candyMachine.publicKey,
guard: 'allowList',
group: some('listA'), // <- 「allowListA」を使用して検証しています。
routeArgs: {
path: 'proof',
merkleRoot: getMerkleRoot(allowListA),
merkleProof: getMerkleProof(
allowListA,
base58PublicKey(umi.identity),
),
},
}).sendAndConfirm(umi);

APIリファレンス: route, DefaultGuardSetRouteArgs

まとめ

ルート命令は、ガードが独自のカスタムプログラムロジックを含むことを可能にすることで、さらに強力にします。各ガードの完全な機能セットを確認するために、利用可能なすべてのガードの専用ページをチェックしてください。

キャンディマシンとそのガードの設定について知るべきことをすべて理解したので、ミントについて話すときが来ました。次のページでお会いしましょう!