機能

キャンディガード

キャンディマシンの動作とロード方法を理解したので、パズルの最後のピースについて話す時が来ました:ガード。

ガードとは何ですか?

ガードは、キャンディマシンのミントへのアクセスを制限し、さらに新しい機能を追加できるモジュラーなコードです!

選択できる大きなガードのセットがあり、それぞれ自由に有効化および設定できます。

このドキュメントの後で利用可能なすべてのガードについて触れますが、これを説明するためにここでいくつかの例を見てみましょう。

  • 開始日ガードが有効になると、事前設定された日付前のミントが禁止されます。指定された日付後のミントを禁止する終了日ガードもあります。
  • SOL支払いガードが有効になると、ミントウォレットは設定された宛先ウォレットに設定された金額を支払う必要があります。トークンや特定のコレクションのNFTで支払う類似のガードが存在します。
  • トークンゲートNFTゲートガードは、それぞれ特定のトークン保有者とNFT保有者にミントを制限します。
  • 許可リストガードは、ウォレットが事前定義されたウォレットのリストの一部である場合にのみミントを許可します。ミント用のゲストリストのようなものです。

ご覧のように、各ガードは一つの責任のみを処理し、それらを組み合わせ可能にします。言い換えると、完璧なキャンディマシンを作成するために必要なガードを選んで選択できます。

キャンディガードアカウント

キャンディマシンアカウントの内容を覚えている場合、そこにガードの兆候はありません。これは、ガードがキャンディガードプログラムによって作成されるキャンディガードアカウントと呼ばれる別のアカウントに存在するためです。

各キャンディマシンアカウントは通常、保護レイヤーを追加する独自のキャンディガードアカウントと関連付けられるべきです。

これは、キャンディガードアカウントを作成し、それをキャンディマシンアカウントのミント権限にすることで機能します。そうすることで、キャンディマシンコアプログラムとして知られるメインのキャンディマシンプログラムから直接ミントすることはもはや不可能になります。代わりに、すべてのガードが正常に解決された場合、ミントプロセスを完了するためにキャンディマシンコアプログラムに委譲するキャンディガードプログラム経由でミントする必要があります。

キャンディマシンとキャンディガードアカウントが連携して動作するため、SDKはそれらを一つのエンティティとして扱うことに注意してください。SDKでキャンディマシンを作成すると、関連するキャンディガードアカウントもデフォルトで作成されます。ガードを同時に更新できるため、キャンディマシンを更新する際も同じです。このページで具体的な例を見てみましょう。

なぜ別のプログラムなのか?

ガードがメインのキャンディマシンプログラムに存在しない理由は、アクセス制御ロジックをNFTをミントするというメインのキャンディマシンの責任から分離するためです。

これにより、ガードはモジュラーだけでなく拡張可能になります。誰でも、残りすべてについてキャンディマシンコアプログラムに依存しながら、カスタムガードを作成するために独自のキャンディガードプログラムを作成・デプロイできます。

SDKは、独自のキャンディガードプログラムとそのカスタムガードを登録する方法も提供しているため、フレンドリーなAPIを活用し、ガードを他の人と簡単に共有できることに注意してください。

利用可能なすべてのガード

よし、ガードが何かを理解したので、利用可能なデフォルトガードを見てみましょう。

以下のリストでは、各ガードの簡単な説明と、より高度な読み物のための専用ページへのリンクを提供します。

  • アドレスゲート: ミントを単一のアドレスに制限します。
  • 許可リスト: ウォレットアドレスリストを使用して誰がミントを許可されているかを決定します。
  • ボット税: 無効なトランザクションに請求する設定可能な税。
  • 終了日: ミントを終了する日付を決定します。
  • フリーズSOL支払い: フリーズ期間付きでミントの価格をSOLで設定します。
  • フリーズトークン支払い: フリーズ期間付きでミントの価格をトークン量で設定します。
  • ゲートキーパー: ゲートキーパーネットワーク経由でミントを制限します(例:Captcha統合)。
  • ミント制限: ウォレットごとのミント数の制限を指定します。
  • NFTバーン: ミントを指定されたコレクションの保有者に制限し、NFTのバーンを要求します。
  • NFTゲート: ミントを指定されたコレクションの保有者に制限します。
  • NFT支払い: ミントの価格を指定されたコレクションのNFTとして設定します。
  • 引き換え済み量: 総ミント量に基づいてミントの終了を決定します。
  • SOL支払い: ミントの価格をSOLで設定します。
  • 開始日: ミントの開始日を決定します。
  • サードパーティ署名者: トランザクションに追加の署名者を要求します。
  • トークンバーン: ミントを指定されたトークンの保有者に制限し、トークンのバーンを要求します。
  • トークンゲート: ミントを指定されたトークンの保有者に制限します。
  • トークン支払い: ミントの価格をトークン量で設定します。

ガード付きキャンディマシンの作成

これまで作成したキャンディマシンには、有効なガードがありませんでした。利用可能なすべてのガードを理解したので、いくつかのガードを有効にして新しいキャンディマシンを設定する方法を見てみましょう。

具体的な実装は使用しているSDKによって異なりますが(下記参照)、主要なアイデアは、必要な設定を提供してガードを有効にすることです。設定されていないガードは無効になります。

ガード付きキャンディマシンの作成

Umiライブラリを使用してガードを有効にするには、create関数にguards属性を提供し、有効にしたい各ガードの設定を渡すだけです。none()に設定されたり提供されなかったりしたガードは無効になります。

import { some, sol, dateTime } from '@metaplex-foundation/umi'
await create(umi, {
// ...
guards: {
botTax: some({ lamports: sol(0.01), lastInstruction: true }),
solPayment: some({ lamports: sol(1.5), destination: treasury }),
startDate: some({ date: dateTime('2023-04-04T16:00:00Z') }),
// 他のすべてのガードは無効...
},
}).sendAndConfirm(umi)

APIリファレンス: create, DefaultGuardSetArgs

ガードの更新

ガードで何か間違いを設定しましたか?ミント価格について考えが変わりましたか?ミントの開始を少し遅らせる必要がありますか?心配無用、ガードは作成時に使用したのと同じ設定で簡単に更新できます。

設定を提供して新しいガードを有効にしたり、空の設定を与えて現在のガードを無効にしたりできます。

ガードの更新

キャンディマシンのガードを作成したのと同じ方法で更新できます。つまり、updateCandyGuard関数のguardsオブジェクト内で設定を提供することです。none()に設定されたり提供されなかったりしたガードは無効になります。

guardsオブジェクト全体が更新されることに注意してください。つまり、既存のすべてのガードを上書きします

したがって、設定が変更されていない場合でも、有効にしたいすべてのガードの設定を提供してください。まずキャンディガードアカウントを取得して、現在のガードにフォールバックしたい場合があります。

import { some, none, sol } from '@metaplex-foundation/umi'
const candyGuard = fetchCandyGuard(umi, candyMachine.mintAuthority)
await updateCandyGuard(umi, {
candyGuard: candyGuard.publicKey,
guards: {
...candyGuard.guards,
botTax: none(),
solPayment: some({ lamports: sol(3), destination: treasury }),
},
})

APIリファレンス: updateCandyGuard, CandyGuard, DefaultGuardSetArgs

キャンディマシンのガード表示

キャンディマシンでガードを設定したら、提供されたすべての設定をキャンディガードアカウントで誰でも取得・表示できます。

ガードの取得

キャンディマシンアカウントのmintAuthority属性でfetchCandyGuard関数を使用して、キャンディマシンに関連するキャンディガードにアクセスできます。

import {
fetchCandyMachine,
fetchCandyGuard,
} from '@metaplex-foundation/mpl-candy-machine'
const candyMachine = await fetchCandyMachine(umi, candyMachineAddress)
const candyGuard = await fetchCandyGuard(umi, candyMachine.mintAuthority)
candyGuard.guards // すべてのガード設定。
candyGuard.guards.botTax // ボット税設定。
candyGuard.guards.solPayment // SOL支払い設定。
// ...

create関数を使用する際、関連するキャンディガードアカウントが各キャンディマシンに対して自動的に作成され、そのアドレスが決定的であることに注意してください。したがって、この場合、以下のように1つのRPC呼び出しのみを使用して両方のアカウントを取得できます。

import { assertAccountExists } from '@metaplex-foundation/umi'
import {
findCandyGuardPda,
deserializeCandyMachine,
deserializeCandyGuard,
} from '@metaplex-foundation/mpl-candy-machine'
const candyGuardAddress = findCandyGuardPda(umi, { base: candyMachineAddress })
const [rawCandyMachine, rawCandyGuard] = await umi.rpc.getAccounts([
candyMachineAddress,
candyGuardAddress,
])
assertAccountExists(rawCandyMachine)
assertAccountExists(rawCandyGuard)
const candyMachine = deserializeCandyMachine(umi, rawCandyMachine)
const candyGuard = deserializeCandyGuard(umi, rawCandyGuard)

APIリファレンス: fetchCandyGuard, findCandyGuardPda, CandyGuard, DefaultGuardSetArgs

キャンディガードアカウントの手動ラップとアンラップ

これまでキャンディマシンとキャンディガードアカウントを一緒に管理してきました。これはほとんどのプロジェクトにとって最も理にかなっているからです。

しかし、SDKを使用しても、キャンディマシンとキャンディガードは異なるステップで作成・関連付けできることに注意することが重要です。

まず2つのアカウントを別々に作成し、手動で関連付け/関連付け解除する必要があります。

キャンディマシンからのガードの関連付けと関連付け解除

Umiライブラリのcreate関数は、作成された各キャンディマシンアカウントに対して真新しいキャンディガードアカウントの作成と関連付けを既に処理しています。

しかし、それらを別々に作成し、手動で関連付け/関連付け解除したい場合、以下のようにします。

import { some, percentAmount, sol, dateTime } from '@metaplex-foundation/umi'
// キャンディガードなしでキャンディマシンを作成します。
const candyMachine = generateSigner(umi)
await (await createCandyMachineV2(umi, {
candyMachine,
tokenStandard: TokenStandard.NonFungible,
collectionMint: collectionMint.publicKey,
collectionUpdateAuthority: umi.identity,
itemsAvailable: 100,
sellerFeeBasisPoints: percentAmount(1.23),
creators: [
{ address: umi.identity.publicKey, verified: false, percentageShare: 100 },
],
configLineSettings: some({
prefixName: 'My NFT #',
nameLength: 3,
prefixUri: 'https://example.com/',
uriLength: 20,
isSequential: false,
}),
})).sendAndConfirm(umi)
// キャンディガードを作成します。
const base = generateSigner(umi)
const candyGuard = findCandyGuardPda(umi, { base: base.publicKey })
await createCandyGuard(umi, {
base,
guards: {
botTax: { lamports: sol(0.01), lastInstruction: false },
solPayment: { lamports: sol(1.5), destination: treasury },
startDate: { date: dateTime('2022-10-17T16:00:00Z') },
},
}).sendAndConfirm(umi)
// キャンディガードをキャンディマシンに関連付けます。
await wrap(umi, {
candyMachine: candyMachine.publicKey,
candyGuard,
}).sendAndConfirm(umi)
// 関連付けを解除します。
await unwrap(umi, {
candyMachine: candyMachine.publicKey,
candyGuard,
}).sendAndConfirm(umi)

APIリファレンス: createCandyMachineV2, createCandyGuard, wrap, unwrap

まとめ

ガードはキャンディマシンの重要なコンポーネントです。ミントプロセスの設定を簡単にしながら、誰でもアプリケーション固有のニーズに対して独自のガードを作成できます。次のページでは、ガードグループを使用してさらに多くのミントシナリオを作成する方法を見てみましょう!