Solana NFT Metaplex初期立ち上げのハマりポイント

Solanaブロックチェーン対応のNFTプラットフォーム Metaplex は手順通りにやると一発で立ち上がるものの、やりたいことや環境に応じていくつかハマりポイントあり。

init StoreするとStore is not initializedエラー

現象

Solana Metaplex で、Installing を実行したあとに、画面上でinit Storeを実行すると以下のエラーが表示される。

Store is not initialized

原因

ストアのオーナーアドレスを設定していないため。
初期状態だと、ここが設定されていないため、エラーになる。

対応(devnet)

metaplex/js/packages/web/.env の REACT_APP_STORE_OWNER_ADDRESS_ADDRESS が初期状態だと空白になっている。ここに、オーナードレスとして設定したいウォレットアドレスを記述する。

REACT_APP_STORE_OWNER_ADDRESS_ADDRESS=<ここに記述する>

SPL_TOKEN_MINTS=kinXdEcpDQeHPEuQnqmUgtYykqKGVFq6CeVX5iAHJq6,ETAtLmCmsoiEEKfNrHKJ2kYy3MoABhU6NQvpSfij5tDs,BLwTnYKqf7u4qjgZrrsKeNs2EzWkMLqVCu6j8iHyrNA3,ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
CG_SPL_TOKEN_IDS=kin,media-network,boring-protocol,star-atlas,usd-coin

補足

  • devnetの場合、画面上の右上「歯車」でdevnetに変更する
  • オーナーアドレスにSOLを入れる(CLIまたは「Solana Faucet」で検索してairdrop)
  • PhantomのNetworkをdevnetに変更する
  • Metaplex Docs で進めると、.envファイルのことも書いてあるため、GitHubではなく、こちらの参照がおすすめ

Sorry, there was an error! Failed to fetchエラー

現象

Create a new itemでNFT作成すると、トランザクションが走ったあと(PhantomでApproveが求められる)、以下のエラーが表示される。

Sorry, there was an error! Failed to fetch

原因

アップロードした画像が10MBを超えている。
(今回のケースは画像サイズだった)

対応

画像を10MB以下にして再アップロードする。

備考

戻るボタンで画像アップロードをやり直してもエラーになるため、1からやり直してアップロードすることを推奨。

ほかの人がCreator登録/NFT作成できない

現象

自分のメニューにCreateが表示されず、Creator登録やNFT作成ができない。

原因

初期状態だとWhitelistに設定した人しか登録できないようになっている。

対応

Admin画面( http://localhost:3000/#/admin )にアクセスして、右上の「Whitelist Only」を「Public」に変更し、「Submit」する。

補足

「Submit」でトランザクションが送信されるが、トランザクション処理されるまでに数秒かかる。DBを利用したWebサイトの管理画面のように、Submitを押した瞬間に内容が反映されるためではないため要注意。
反映されたかどうかを把握したい場合は、Solana Explorerなどでトランザクション処理状況を直接確認する必要あり。

GitHub Pagesにアップすると画像が404 Not Found

前提

Metaplex Deploy GitHub Pages の手順通りにGitHub Pagesにアップ。
ただし、カスタムドメインは使用せずに(つまり独自ドメインは使用しない)、GitHubデフォルトのままで利用。

自分の場合だと、「metaplex」という名前のレポジトリを作ったため、 https://256hax.github.io/metaplex/ でアクセスできるようになる。

現象

画像が404 Not Foundになる。左上のロゴや右上のメニューなどの画像が表示されない。

原因

Metaplexのソースコードの各パスが、独自ドメイン想定で組まれているため、GitHub Pagesの仕組みに適合していない。つまり、参照パスがあっていない。

GitHub PagesのURLは、 https://256hax.github.io/metaplex/ とサブディレクトリが切られる。そのままだと以下の「実際の画像URLの出力」で表示されてしまい、画像が404になる。

実際の画像URLの出力:https://256hax.github.io/metaplex-logo.svg
期待する画像URLの出力:https://256hax.github.io/metaplex/metaplex-logo.svg

対応

おそらく、独自ドメインを適用していれば正常に表示されると思われるため、それが早い。しかし、独自ドメインを使用せずに対応したい場合は、参照パスを変更すればよい。

【修正前】
js/packages/web/src/components/AppBar/index.tsx

export const LogoLink = () => {
  return (
    <Link to={`/`}>
      <img src={'/metaplex-logo.svg'} />
    </Link>
  );
};

js/packages/web/package.json

  "homepage": ".",

【修正後】
以下のようにGitHub Pagesの名前にあわせてパスを修正する。

js/packages/web/src/components/AppBar/index.ts

export const LogoLink = () => {
  return (
    <Link to={`/`}>
      <img src={'/metaplex/metaplex-logo.svg'} />
    </Link>
  );
};

js/packages/web/package.json

  "homepage": "https://256hax.github.io/metaplex/",

備考

独自ドメインの使用有無に問わず(=ディレクトリ階層に影響なく)、一発で対応できる方法がないか検証したが、結果うまくいかず。

【パスの検証】
絶対パス指定しか成功しなかった。

<img src={'/metaplex/metaplex-logo.svg'} /> => <img src="/metaplex/metaplex-logo.svg"> ← これだけ成功
<img src={'./metaplex-logo.svg'} /> => <img src="./metaplex-logo.svg">
<img src={'metaplex-logo.svg'} /> => <img src="metaplex-logo.svg">

【package.jsonのhomepage】
いずれも成功しなかった。

"homepage": ".",
"homepage": "./",
"homepage": "https://256hax.github.io/metaplex/",

参考

以下のようにコードを組めば対応できるが、カスタムしすぎるとMetaplexの変更マージが大変になるので要注意。Metaplexはimg srcを直書きしているため、全パス修正が必要になりそう。

Next.js の public 以下のファイルのパスを正しく扱う

URLに#が自動的に付与される

現象

Metaplexにアクセスすると、以下のように#が自動的に付与される。

http://localhost:3000/#/

原因

Metaplexで HashRouter を使用しているため、自動付与になる。

対応

BrowserRouterを使用すれば#が付与されなくなる。

【修正前】
js/packages/web/src/routes.tsx

<HashRouter basename={'/'}>
    〜〜〜省略〜〜〜
</HashRouter>

【修正後】

<BrowserRouter basename={'/'}>
    〜〜〜省略〜〜〜
</BrowserRouter>

備考

独自ドメインであれば#が付与されても問題ないが、独自ドメインなしでGitHub Pagesを使用すると、以下のように変な位置に#が入ってしまう。対応策がありそうだが未調査。

https://256hax.github.io/metaplex#/

yarn startでlocalhost起動してもhttps(SSL)で接続できない

現象

yarn start でlocalhost起動すると、http://localhost:3000 で接続できるようになる。しかし、このままだと、httpsにした https://localhost:3000 で接続はできない。

原因

yarn start (js/packages/web/package.json) は next dev が起動する仕組みになっているが、httpしかサポートしていないため、httpsに対応する設定が必要になる。

js/packages/web/package.json

    "start": "next dev",

対応

結論としては、 Next.js のローカル開発時に https を使う の手順通りでhttps対応ができる。

Metaplexには以下のように実装した。

opensslで生成した証明書と秘密鍵の設置

GitHubにファイル丸ごとアップしたため(以下リンク参照)、そのまま利用するもよし、opensslで生成するもよし。

js/packages/web/certificates

localhost.crt 
localhost.key

server.jsでhttps接続設定

ほぼ Next.js のローカル開発時に https を使う の記述どおりで、ポート番号だけ変更

js/packages/web/server.js

const express = require('express');
const next = require('next');
const https = require('https');
const fs = require('fs');

const port = parseInt(process.env.PORT || '3000');
const host = '0.0.0.0';

const app = next({
  dev: process.env.NODE_ENV !== 'production',
});
const handle = app.getRequestHandler();

(async () => {
  await app.prepare();
  const expressApp = express();

  expressApp.get('*', (req, res) => handle(req, res));

  // Use HTTPS if HTTPS option enabled
  const hasCertificates =
    fs.existsSync('./certificates/localhost.key') &&
    fs.existsSync('./certificates/localhost.crt');
  const useHttps =
    process.env.HTTPS === 'true' &&
    hasCertificates;

  if (useHttps) {
    const options = {
      key: fs.readFileSync('./certificates/localhost.key'),
      cert: fs.readFileSync('./certificates/localhost.crt'),
    };
    const server = https.createServer(options, expressApp);
    server.listen(port, host);
    console.log(`> Ready on https://localhost:${port}`);
  } else {
    expressApp.listen(port, host);
    console.log(`> Ready on http://localhost:${port}`);
  }
})();

httpsスタート用コマンド登録

以下を追記

js/packages/web/package.json

    "start:https": "HTTPS=true node ./server.js",

大元のjs直下package.jsonにもhttpsスタート用コマンド登録

以下を追記

js/package.json

    "start:https": "cross-env CI=true lerna run start:https --scope @oyster/common --stream --parallel --scope web",

https起動コマンド

以下コマンドを打つと https://localhost:3000 でアクセスできるようになる

% cd js
% yarn start:https

備考

  • mkcertという証明書発行パッケージもあるが、これで生成されたkey/certが利用できなかったため(自分の手順が悪い可能性あり)、opensslで発行するしかなかった。
  • httpsは自己署名証明書(通称「オレオレ証明書」と呼ばれる)になるため、ブラウザ上で「セキュリティ保護なし」の警告が表示される。試していないが、おそらく、このような設定が必要: Chrome: オレオレ証明書でもセキュリティ警告画面が出ないようにする方法 。1人でローカル開発する分には警告が出ても特に影響ないため、このまま放置。

売買指定トークンの選択リストを変更したい

やりたいこと

Sell -> Instant Sale -> Auction Mintで「SELECT A TOKEN AS YOUR AUCTION MINT」の画面で、売買するトークンの一覧が表示される。ここに表示されるトークンを変更したい(たとえば自分のトークンを表示するなど)。

対応(仮説)

未検証のため、以下仮説版。

  1. Solana公式からトークンリストの取得
    solana-labs/token-list から、表示したいトークンを検索して、addressとcoingeckoIdを取得する。

Orcaの場合

    {
      "chainId": 101,
      "address": "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE",
      "symbol": "ORCA",
      "name": "Orca",
      "decimals": 6,
      "logoURI": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE/logo.png",
      "extensions": {
        "coingeckoId": "orca",
        "discord": "https://discord.com/invite/nSwGWn5KSG",
        "medium": "https://orca-so.medium.com",
        "serumV3Usdc": "8N1KkhaCYDpj3awD58d85n973EwkpeYnRp84y1kdZpMX",
        "telegram": "https://t.me/orca_so",
        "twitter": "https://twitter.com/orca_so",
        "website": "https://orca.so"
      }
  1. Metaplexの.envに情報を記述
    metaplex/js/packages/web/.env
SPL_TOKEN_MINTS=orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE
CG_SPL_TOKEN_IDS=orca

備考

  • トークン表示方法は、 右上メニューの Sell -> Instant Sale で Auction Mint の以下をクリックするとトークンが表示される。
  • .envのCG_SPL_TOKEN_IDSの意味は、おそらく CoinGecko SPL Token ID と思われる。
  • Solana公式のトークンリストに掲載する場合は、SolanaのGitHubに申請が必要。

SPL Token(独自発行トークン)で販売するとError: Failed to creat

前提

Metaplexのおそらくv1.1.0から、独自発行したトークンで販売ができるようになった。
以下はSolana CLIで適当にトークン発行して、0.1トークンで販売している例。

現象

Metaplex右上メニューの Sell > Instant Sale > Auction mint でTokenアドレスをセットして、Sellの設定を進めていくと、進捗率99%の状態で止まって以下のエラーが表示される。(最初から表示されている KINやUSDCを選択しても同様)
環境はDevnet。

 1 of 1 unhandled error
Unhandled Runtime Error
Error: Failed to create
Source
src/actions/createAuctionManager.ts (380:45) @ createAuctionManager

 378 | }
 379 | 
> 380 | if (stopPoint < instructions.length) throw new Error('Failed to create');
 | ^
 381 | 
 382 | return { vault, auction, auctionManager };
 383 | }
Call Stack
async Object.createAuction
src/views/auctionCreate/index.tsx (513:24)
async func
src/views/auctionCreate/index.tsx (2040:6)

原因

存在しないトークンアドレスを選択しているため失敗している(仮説)。
以下が特にハマるポイント

  • 以下のように最初から表示されている KINやUSDCは、MainnetのアドレスでありDevnetではない
    ソース:metaplex/js/packages/web/.env
  • Devnetで適当に落ちているSPL Tokenを登録してもうまくいかない。DevnetのToken Facetを公開しているトークンもあるが、基本的に使わないほうがよい

対応

Devnet上で自分でSPL Tokenを発行してから、Auction mintに登録する。

独自トークンの発行

Solana Token Program を参考にトークンとトークンアカウントを発行する。

$ solana config set --url https://api.devnet.solana.com
$ spl-token create-token
Creating token [独自トークンアドレス]
$ spl-token create-account [独自トークンアドレス]
$ spl-token mint [独自トークンアドレス] 100

2. Phantomでトークン確認

Phantomで独自発行したトークンが表示されているか確認する。

3. Metaplexで販売

右上メニューからDevnetに切り替える
右上メニューの Sell -> Instant Sale で Auction Mint の Wrapped SOL をクリック

Go!ボタン横の入力フォームに独自トークンアドレスを入力

トークンのセットを確認

以降はSellのステップを進めて完了

備考

最初は NFTs With Kin を参考に進めていたが、これはMainnetしか動作しないっぽい。内容はDevnetで書かれているが、DevnetやTestnetではSellが成功しなかった。原因はここで紹介されているKINのアドレスがMainnetのものになっているため。ただし、Sellのトークン指定以外は成功するため、一通りの手順はこれを見るのがおすすめ。

Add another creatorに選択したいクリエイターが表示されない

現象

NFT作成(Create)で、使用料の分配(項目名:Royalty Percentage, Creators Split)をするために、クリエイターを追加しようとしたところ、指定したいクリエイターが表示されない。

原因

admin画面でクリエイター登録されていないため。

対応

admin画面(http://localhost:3000/#/admin)でクリエイターのアドレスを登録する。
注意事項として、「Activated」の項目が「Active」になっている必要あり。

Candy Machine v2で作成したNFTがMetaplexで販売できない(creatorのunverified/sign問題)

2022/5/19追記

Sign機能が実装されたようです(もしかして見落としていただけで最初から実装されていた? もしそうでしたらすみません)

Metaplex - Signing Your NFTs

以降は2022/1/21時点の情報です。

現象

Candy Machine v2 Tutorial のとおりに手順進めて、作成(Mint)まで完了させる。
Phantomを見ると、作成したNFTは自己所有物としてちゃんと表示される。
しかし、MetaplexのStorefrontで販売(Sell)しようとしても、自分が持っているNFTが選択できない(表示されない)。
Metaplex上でCreateしたNFTは問題なく販売できるが、 Candy Machine v2 で作成したNFTの場合は販売ができない。

原因

Creatorsが全員、verify(承認)になっていないため。
前提として、Metaplexで販売する場合は、Creators全員がverify状態になっている必要がある。
MetaplexのStorefrontだと、手順通りに進めると、Approve可否画面が表示されて承認するため、verify状態になる(ただし、1人のCreatorのみで複数人のCreatorの場合は非対応)。
しかし、Candy Machine v2 で作成した場合、verifyステップがないため、手動でverifiedにする必要がある。

対応

Creatorsを全員、verifyにする。具体的には、メタデータ上のverifiedを1にすればよい。
MetaplexのStorefrontでverifyにできればよいが、そのような機能は発見できなかったため、CLI経由しか実行できないものと思われる。

(方法1)Candy Machine v2 CLIを使う場合

CreatorsのMetadata Accountがわかればverifyにできるため、まずはAccountを取得する。

1. verify状況の確認

作成したNFTを Solsacn で確認すると、Creatorsが2名表示される。

  • 1つ目は Candy Machine v2 が verified:1 にしてくれているため無視
  • 2つ目に自分が指定したアドレスが表示され、 verified:0 になっている

上部のサマリーまたは、Metadataタブでverify状況が確認できる。

2. Transactionの確認

SolscanのTransactionsタブから、 NFTの最初のトランザクション を表示する。

3. CreatorsのMetadata Accountの取得

非常にわかりにくいが、「#5 - Instruction 4」セクションの「#5 - Account4」項目がMetadata Accountになる。

(参考)

  • 該当アカウントの詳細を見ると、「Program」と「Owner Program: Metaplex Token Metadata」となっているのが目印
  • Solana Explorerで表示すると「Account」と表示され、Program Accountではなく、URIなどのMetadata関連情報を格納するためのMetadata Accountと思われる
  • おそらくここで定義されている? 複雑すぎて該当項目は発見できず metaplex-program-library / instruction.rs

このMetadata Accountでverifyが可能になる。

4. CLIの実行

Candy Machine v2 CLIのsignを使用するため、該当ディレクトリまで移動してヘルプを表示。

% cd js/packages/cli/src
% ts-node candy-machine-v2-cli.ts sign sign -h

Usage: candy-machine-v2-cli sign [options]

Options:
  -e, --env <string>         Solana cluster env name (default: "devnet")
  -k, --keypair <path>       Solana wallet location
  -l, --log-level <string>   log level
  -c, --cache-name <string>  Cache file name (default: "temp")
  -m, --metadata <string>    base58 metadata account id
  -r, --rpc-url <string>     custom rpc url since this is a heavy command
  -h, --help                 display help for command

キーペアとCreatorsのMetadata Accountを指定して、veriyを実行する。
なお、キーペアはCreatorsのものが必要。

ts-node candy-machine-v2-cli.ts sign -k ~/.config/solana/devnet.json -m 4xHtfjprxBK423wfinNjdxiPJUWmNGnvct7ataYkkRvw

NFTの詳細を再度確認すると、すべてverifyになっている。これでMetaplexのStorefrontでも販売が可能。

(方法2)Metabossを使う場合

Candy Machine v2 CLIのsignだと、Metadata Accountを人力で探さなければならないため、非常に大変。また、Creatorsが複数になった場合は、さらにややこしくなる。
Metaboss というツールを利用すると、一発で対応可能になる。

Metabossをインストールして、 metaboss sign を実行するだけ。

metaboss sign one --keypair <PATH_TO_KEYPAIR> --account <MINT_ACCOUNT>

MINT_ACCOUNTは、 SolScan だと、右上にある「Token address」というものになる。

参考

クリエイターを複数人にしたらUNVERIFIEDのまま販売できない

現象

NFT作成時に、クリエイターを複数人にして使用料も分配して実行。
NFTを販売しようとしても表示されず、NFT詳細画面を見ると、「UNVERIFIED」と表示される。

原因

クリエイター全員がverifyになっていないため。

対応

原因や対応の詳細は、本ページの「Candy Machine v2で作成したNFTがMetaplexで販売できない」を参照。

参考サイト

  • Solana and Metaplex FAQ
    Q&Aがわかりやすく載っている。
  • Metaplex公式 Discord
    ヒントが載っている(解決策がドンピシャで上がっているケースはあまり多くないため、基本的にヒント目的になる)。
  • Metaplex公式 GitHub Issues
    あらきらかに挙動がおかしい場合はIssuesにバグ報告されているケースもある。