Metaplex BubblegumのCompressed NFTで「DasApiError: Asset not found」エラー

現象

CompressedNFTで getAsset を実行すると以下のエラー。

DasApiError: Asset not found: FWiZYQHfASrwZ2YeActdVi4VPX8KM8mAeuKg7VcMUcTz
    at Object.getAsset (metaplex/bubblegum_CompressedNFT/node_modules/@metaplex-foundation/digital-asset-standard-api/src/decorator.ts:75:23)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async fetchCNFT (metaplex/bubblegum_CompressedNFT/src/fetchCNFT.ts:58:20)
sxuser@SX-MacBook-Pro-13-Mid-2018 bubblegum_CompressedNFT % ts-node src/fetchCNFT.ts
DasApiError: Asset not found: FWiZYQHfASrwZ2YeActdVi4VPX8KM8mAeuKg7VcMUcTz
    at Object.getAsset (metaplex/bubblegum_CompressedNFT/node_modules/@metaplex-foundation/digital-asset-standard-api/src/decorator.ts:75:23)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async fetchCNFT (metaplex/bubblegum_CompressedNFT/src/fetchCNFT.ts:58:20)
sxuser@SX-MacBook-Pro-13-Mid-2018 bubblegum_CompressedNFT % ts-node src/fetchCNFT.ts
DasApiError: No assets found for owner: HXtBm8XZbxaTt41uqaKhwUAa6Z1aPyvJdsZVENiWsetg
    at Object.getAssetsByOwner (metaplex/bubblegum_CompressedNFT/node_modules/@metaplex-foundation/digital-asset-standard-api/src/decorator.ts:176:13)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async fetchCNFT (metaplex/bubblegum_CompressedNFT/src/fetchCNFT.ts:60:31)

ソース

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

// Metaplex
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults';
import {
  keypairIdentity,
  publicKey,
} from '@metaplex-foundation/umi';
import { dasApi } from '@metaplex-foundation/digital-asset-standard-api';
const getAsset = async () => {
  // ----------------------------------------------------
  //  Setup
  // ----------------------------------------------------
  dotenv.config();

  const endpoint = 'https://api.devnet.solana.com';

  // 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));

  // -------------------------------------
  //  Get an Asset
  // -------------------------------------
  const assetId = publicKey('CjBKALu6F1CERdXmyJVfKRXviBQWAcgYGPejyuQpgGb8');
  const asset = await umi.rpc.getAsset(assetId);

  console.log('assetId =>', assetId);
  console.log('asset =>', asset);
};

getAsset();

原因

今回のケースでは、DASの対象外となっていたRPC(Public RPCのDevnet)を使っていたことが原因だった。

Metaplexが提供しているCompressed NFTのget系は、Digital Asset Standard (DAS) APIの利用が必要。
SolanaのPublic RPCは、Devnetでは動かないっぽい。

もし、Mainnetでも本現象が出たら、裏側でタイムアウトしていると思われるため(しかもその旨を教えてくれない)、何回か実行すると通ることがある。

対応

対応表

整理するとDASが利用可能になるRPCは以下になる。

RPC Devnet Mainnet
Solana Public RPC Unavailable OK
サードパーティ OK OK

【参考】
SolanaのPublic RPC

  • Devnet: https://api.devnet.solana.com
  • Mainnet: https://api.mainnet-beta.solana.com

対応1 サードパーティ

DevnetのDASに対応しているサードパーティのRPCを利用する。

Metaplex DAS API RPCs一覧 から確認できる。

個人的には、Heliusを利用して簡単に取得できた。以下のようにRPCを設定して使うだけでよい。

~~~

const endpoint = 'https://devnet.helius-rpc.com/?api-key=<HELIUS_API_KEY>';
const umi = createUmi(endpoint).use(dasApi());

~~~

const assetId = publicKey('CjBKALu6F1CERdXmyJVfKRXviBQWAcgYGPejyuQpgGb8');
const asset = await umi.rpc.getAsset(assetId); // ← RPCセットすると動く

対応2 Mainnetを使う

Devnetは使わず、Mainnetを使う。コストが安いので、ちょっとした開発・検証ぐらいなら、あまりコストインパクトはないはず。
(補足:その場合は、Merkle Tree作成で、サイズを小さくしておくこと。ここでコストを持っていかれるため)

対応3 DASの構築

ハードルが非常に高いがDASインフラを構築する。以下参照。

Metaplex digital-asset-rpc-infrastructure