Metaplex UmiでCompressed NFTを発行すると「0x178c」エラー

現象

実行すると下記のエラーが出る。

metaplex/umi/node_modules/@solana/web3.js/src/connection.ts:5922
      throw new SendTransactionError(
            ^
SendTransactionError: failed to send transaction: Transaction simulation failed: Error processing Instruction 0: custom program error: 0x178c
    at Connection.sendEncodedTransaction (metaplex/umi/node_modules/@solana/web3.js/src/connection.ts:5922:13)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Connection.sendRawTransaction (metaplex/umi/node_modules/@solana/web3.js/src/connection.ts:5881:20)
    at async Object.sendTransaction (metaplex/umi/node_modules/@metaplex-foundation/umi-rpc-web3js/src/createWeb3JsRpc.ts:327:25)
    at async TransactionBuilder.sendAndConfirm (metaplex/umi/node_modules/@metaplex-foundation/umi/src/TransactionBuilder.ts:359:23)
    at async mintToCollection (metaplex/umi/src/cNFT-mintToCollection.ts:39:18) {
  logs: [
    'Program BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY invoke [1]',
    'Program log: Instruction: MintToCollectionV1',
    'Program log: AnchorError occurred. Error Code: InvalidCollectionAuthority. Error Number: 6028. Error Message: Invalid collection authority.',
    'Program BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY consumed 33296 of 200000 compute units',
    'Program BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY failed: custom program error: 0x178c'
  ]
}

ソース

// Lib
import * as dotenv from 'dotenv';
import * as bs58 from 'bs58';

// Metaplex
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import {
  createSignerFromKeypair,
  keypairIdentity,
  publicKey,
} from '@metaplex-foundation/umi';
import { mintToCollectionV1 } from '@metaplex-foundation/mpl-bubblegum';

const mintToCollection = async () => {
  // ----------------------------------------------------
  //  Setup
  // ----------------------------------------------------
  dotenv.config();

  const endpoint = 'https://api.devnet.solana.com';
  const umi = createUmi(endpoint);

  // Set Payer
  const payerSecretKey = process.env.PAYER_SECRET_KEY;
  if (!payerSecretKey) throw new Error('payerSecretKey not found.');

  const secretKeyUInt8Array = new Uint8Array(JSON.parse(payerSecretKey));
  const payerKeypair =
    umi.eddsa.createKeypairFromSecretKey(secretKeyUInt8Array);

  umi.use(keypairIdentity(payerKeypair));

  // ----------------------------------------------------
  //  Minting without a Collection
  // ----------------------------------------------------
  // Replace to your Merkle Tree.
  const merkleTree = publicKey('B9bq2sirvRtgDfZdaTqPso3h6ghfWjXfx77CHdWKHEqT');
  // Replace to your Collection NFT.
  const collectionMint = publicKey(
    'CNKbk92ugTzDnqZNNttXGWbNmCmHptxctz8BuJYYp9Tx'
  );

  const result = await mintToCollectionV1(umi, {
    leafOwner: payerKeypair.publicKey,
    merkleTree,
    collectionMint,
    metadata: {
      name: 'My Compressed NFT',
      uri: 'https://example.com/my-cnft.json',
      sellerFeeBasisPoints: 500, // 5%
      collection: { key: collectionMint, verified: false },
      creators: [
        { address: umi.identity.publicKey, verified: false, share: 100 },
      ],
    },
  }).sendAndConfirm(umi);

  console.log('payer =>', payerKeypair.publicKey.toString());
  console.log('leafOwner =>', payerKeypair.publicKey.toString());
  console.log('merkleTree =>', merkleTree);
  console.log('collectionMint =>', collectionMint.toString());
  console.log('signature =>', bs58.encode(result.signature));
};

mintToCollection();

原因

変更権限がない。今回のケースでは、「mintToCollectionV1」を使ってCompressed NFTを指定したCollectionに追加する実装をしていたが、そのときにUpdate Authorityの権限が適切ではなかった。

「mintToCollectionV1」は、デフォルトだとumi.identityが利用されるため、もしumiで指定したKeypairに権限がなかった場合は、エラーになる。

対応

適切な権限をセットする。

  const collectionUpdateAuthority = createSignerFromKeypair(umi, <UPDATE_AUTHORITY_KEYPAIR>); // ← これを追加
  const result = await mintToCollectionV1(umi, {
    leafOwner: payerKeypair.publicKey,
    merkleTree,
    collectionMint,
    collectionAuthority: collectionUpdateAuthority, // ← これを追加
    metadata: {
      name: 'My Compressed NFT',
      uri: 'https://example.com/my-cnft.json',
      sellerFeeBasisPoints: 500, // 5%
      collection: { key: collectionMint, verified: false },
      creators: [
        { address: umi.identity.publicKey, verified: false, share: 100 },
      ],
    },
  }).sendAndConfirm(umi);