機能
プログラマブルNFT(pNFT)
概要ページで述べられているように、プログラマブルNFT(pNFT)は、作成者が特定の操作にカスタムルールを定義し、サードパーティの権限により細かく委任できる新しいアセット標準です。
Token Metadataのバイパスの廃止
Token MetadataプログラムはSPL Tokenプログラムの上に構築されているため、任意の所有者またはspl-token委任がSPL Tokenプログラムと直接やり取りし、転送やバーンなどの重要な操作でToken Metadataプログラムをバイパスできます。これはプログラム間の優れた構成可能性パターンを作成しますが、Token Metadataプログラムが作成者の代わりにルールを強制できないことも意味します。
これが問題となる良い例は、Token Metadataがセカンダリセールのロイヤルティを強制できないことです。ロイヤルティの割合がMetadataアカウントに保存されていても、転送を実行するユーザーまたはプログラムがそれを尊重するかどうかを決定するのは彼ら次第です。これについて、およびpNFTがこの問題をどのように解決するかについては、以下のセクションで詳しく説明します。
プログラマブルNFTは、作成者がアセットの認証層をカスタマイズできる柔軟な方法でこの問題を解決するために導入されました。
プログラマブルNFTは以下のように動作します:
- pNFTのTokenアカウントは、pNFTが委任されているかどうかに関係なく、SPL Tokenプログラムで常にフリーズされています。これにより、誰もSPL Tokenプログラムと直接やり取りしてToken Metadataプログラムをバイパスできないことが保証されます。
- pNFTのTokenアカウントで操作が実行されるたびに、Token Metadataプログラムはアカウントを解凍し、操作を実行し、再度アカウントをフリーズします。これはすべて同じ命令でアトミックに発生します。このようにして、SPL Tokenプログラムで実行可能なすべての操作はpNFTでも利用できますが、常にToken Metadataプログラムを通じて実行されます。
- Token委任がpNFTに設定されると、情報はToken Recordアカウントに保存されます。pNFTはSPL Tokenプログラムで常にフリーズされているため、pNFTが実際にロックされているかどうかを追跡するのはToken Recordアカウントの責任です。
- pNFTに影響を与えるすべての単一操作がToken Metadataプログラムを通過する必要があるため、これらの操作に認証ルールを強制できるボトルネックが作成されました。これらのルールは、Token Auth Rulesプログラムによって管理されるRule Setアカウントで定義されます。
本質的に、これによりpNFTは以下の能力を持ちます:
- より細かい委任を持つ。
- あらゆる操作にルールを強制する。
これら2つの能力についてより詳しく見てみましょう。
より細かい委任
すべてのpNFT操作がToken Metadataプログラムを通過する必要があるため、spl-token委任の上に新しい委任システムを作成できます。これはより細かく、pNFT所有者がサードパーティに委任したい操作を選択できるようにします。
この新しい委任システムの情報は、pNFTのMintアカウントとTokenアカウントの両方から派生する特別なToken Record PDAに保存されます。新しい委任権限がpNFTに割り当てられると、Token MetadataプログラムはTokenアカウントとToken Recordアカウントの両方でその情報を同期します。
これらの委任については、委任された権限ページの「Token委任」セクションでより詳しく説明します。
追加アカウント
pNFTはほとんどの操作で追加のアカウントを必要とし、これらにはtokenRecord、authorizationRules、authorizationRulesProgramが含まれます。
Token Record
tokenRecordアカウントは、delegatesやそのlock状態などのトークンとその状態に関する詳細を保持する責任があります。
tokenRecordアカウントにアクセスする方法がいくつかあり、それはmetadata、token account、token recordを含む必要なすべてのアカウントを返すfetchDigitalAssetWithAssociatedTokenを使用するか、findTokenRecordPda関数を使用してmint IDとtoken accountアドレスでtoken record PDAアドレスを生成する方法です。
アセットとトークン
fetchDigitalAssetWithAssociatedToken関数を使用してすべてのアカウントを取得できます。これはpNFT metadataアカウント、token account、token recordアカウントなどのデータを返します。
1import { publicKey } from '@metaplex-foundation/umi';
2import { fetchDigitalAssetWithAssociatedToken } from '@metaplex-foundation/mpl-token-metadata';
3
4const mint = publicKey('11111111111111111111111111111111');
5const owner = publicKey('22222222222222222222222222222222');
6
7const assetWithToken = await fetchDigitalAssetWithAssociatedToken(
8 umi,
9 mint,
10 owner
11);
12
13console.log('Metadata:', assetWithToken.metadata.name);
14console.log('Token Record:', assetWithToken.tokenRecord);
1import { address } from '@solana/addresses';
2import { fetchDigitalAssetWithAssociatedToken } from '@metaplex-foundation/mpl-token-metadata-kit';
3
4const mint = address('11111111111111111111111111111111');
5const owner = address('22222222222222222222222222222222');
6
7const assetWithToken = await fetchDigitalAssetWithAssociatedToken(
8 rpc,
9 mint,
10 owner
11);
12
13console.log('Metadata:', assetWithToken.metadata.name);
14console.log('Token Record:', assetWithToken.tokenRecord);
Token Record PDA
mintIdとpNFTアセットが保存されているウォレットのtokenAccountを使用して、tokenRecordアカウントのPDAアドレスを生成します。
1import { publicKey } from '@metaplex-foundation/umi';
2import { findTokenRecordPda } from '@metaplex-foundation/mpl-token-metadata';
3
4const mint = publicKey('11111111111111111111111111111111');
5const token = publicKey('22222222222222222222222222222222');
6
7const tokenRecordPda = findTokenRecordPda(umi, {
8 mint,
9 token,
10});
11
12console.log('Token Record PDA:', tokenRecordPda);
1import { address } from '@solana/addresses';
2import { findTokenRecordPda } from '@metaplex-foundation/mpl-token-metadata-kit';
3
4const mint = address('11111111111111111111111111111111');
5const token = address('22222222222222222222222222222222');
6
7const [tokenRecordPda] = await findTokenRecordPda({
8 mint,
9 token,
10});
11
12console.log('Token Record PDA:', tokenRecordPda);
RuleSet
metadataアカウントデータが利用可能な場合、metadataアカウントのprogrammableConfigフィールドを確認してルールセットを取得できます。
1import { unwrapOptionRecursively } from '@metaplex-foundation/umi';
2
3// Assuming assetWithToken was fetched using fetchDigitalAssetWithAssociatedToken
4
5const ruleSet = unwrapOptionRecursively(
6 assetWithToken.metadata.programmableConfig
7)?.ruleSet;
8
9console.log('Rule Set:', ruleSet);
1// No additional imports needed - programmableConfig is directly on metadata
2
3// Assuming assetWithToken was fetched using fetchDigitalAssetWithAssociatedToken
4
5// In Kit, options are represented as { __option: 'Some', value: ... } or { __option: 'None' }
6const programmableConfig = assetWithToken.metadata.programmableConfig;
7const ruleSet = programmableConfig.__option === 'Some'
8 ? programmableConfig.value.ruleSet
9 : null;
10
11console.log('Rule Set:', ruleSet);
Authorization Rules Program
pNFTアセットにruleSetが設定されている場合、ruleSetを検証できるようにAuthorization Rules Program IDを渡す必要があります。
1import { getMplTokenAuthRulesProgramId } from '@metaplex-foundation/mpl-token-auth-rules';
2
3const authorizationRulesProgram = getMplTokenAuthRulesProgramId(umi);
4
5console.log('Auth Rules Program:', authorizationRulesProgram);
1import { address } from '@solana/addresses';
2
3// Token Auth Rules Program ID
4const authorizationRulesProgram = address('auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg');
5
6console.log('Auth Rules Program:', authorizationRulesProgram);
Authorization Data
検証に追加データが必要なruleSetがpNFTアセットにある場合、命令パラメータでauthorizationData: { payload: ... }として渡します。
あらゆる操作へのルール強制
プログラマブルNFTの最も重要な機能の1つは、それらに影響を与えるあらゆる操作に一連のルールを強制できる能力です。認証層全体は、Token Auth Rulesと呼ばれる別のMetaplexプログラムによって提供されます。このプログラムはpNFTをプログラマブルにするために使用されますが、あらゆる用途の認証ルールを作成および検証するために使用できる汎用プログラムです。
pNFTの場合、以下の操作がサポートされています:
| 操作 | 説明 |
|---|---|
Transfer:Owner | pNFTの所有者によって開始された転送 |
Transfer:SaleDelegate | Sale委任によって開始された転送 |
Transfer:TransferDelegate | TransferまたはLocked Transfer委任によって開始された転送 |
Transfer:MigrationDelegate | Migration委任によって開始された転送(pNFT移行期間中に使用されたレガシー委任) |
Transfer:WalletToWallet | ウォレット間の転送(現在未使用) |
Delegate:Sale | Sale委任の承認 |
Delegate:Transfer | Transfer委任の承認 |
Delegate:LockedTransfer | Locked Transfer委任の承認 |
Delegate:Utility | Utility委任の承認 |
Delegate:Staking | Staking委任の承認 |
作成者はこれらの操作のいずれかにカスタムルールを割り当てることができます。その操作が実行されると、Token Metadataプログラムは操作を許可する前にルールが有効であることを確認します。利用可能なルールはToken Auth Rulesプログラムによって直接文書化されていますが、2種類のルールがあることに注意する価値があります:
- プリミティブルール:これらのルールは操作が許可されているかどうかを明示的に示します。例:
PubkeyMatchルールは、指定されたフィールドの公開鍵が指定された公開鍵と一致する場合にのみパスします。ProgramOwnedListは、指定されたフィールドのアカウントを所有するプログラムが指定されたプログラムリストの一部である場合にのみパスします。Passルールは常にパスします。など。 - 複合ルール:これらのルールは複数のルールを集約して、より複雑な認証ロジックを作成します。例:
Allルールは、含まれるすべてのルールがパスする場合にのみパスします。Anyルールは、含まれるルールの少なくとも1つがパスする場合にのみパスします。Notルールは、含まれるルールがパスしない場合にのみパスします。など。
操作のすべてのルールが定義されたら、Token Auth RulesプログラムのRule Setアカウントに保存できます。このRule Setに変更が必要な場合、新しいRule Set RevisionがRule Setアカウントに追加されます。これにより、特定のリビジョン内に現在ロックされているpNFTが、最新のリビジョンに移行する前にロック解除できることが保証されます。
使用例:ロイヤルティの強制
pNFTについてより理解できたところで、pNFTで解決できる具体的な使用例を見てみましょう:ロイヤルティの強制。
上記で述べたように、pNFTがなければ、誰でもSPL Tokenプログラムと直接やり取りすることで、Metadataアカウントに保存されているロイヤルティパーセンテージをバイパスできます。これは、作成者がアセットとやり取りするユーザーやプログラムの善意に依存しなければならないことを意味します。
しかし、pNFTを使用すれば、作成者はロイヤルティを強制しないプログラムがアセットの転送を実行することを禁止する Rule Setを設計できます。ニーズに応じて、許可リストまたは拒否リストを作成するためにルールの組み合わせを使用できます。
さらに、Rule Setは複数のpNFT間で共有および再利用できるため、作成者はコミュニティRule Setを作成および共有して、ロイヤルティのサポートを停止するプログラムが、そのようなコミュニティRule Setを使用するすべてのpNFTとのやり取りから即座に禁止されるようにできます。これは、プログラムがロイヤルティをサポートする強力なインセンティブを作成します。そうしなければ、多数のアセットとのやり取りから禁止されることになるからです。
