Solana AnchorでProvider local is not available on browser

現象

Solana Anchorで作ったProgramをReactから呼び出そうとすると、以下のエラー。

@coral-xyz_anchor.js?v=4eaec7da:6889 Uncaught Error: Provider local is not available on browser.
    at AnchorProvider.local (@coral-xyz_anchor.js?v=4eaec7da:6889:13)
    at getProvider (@coral-xyz_anchor.js?v=4eaec7da:7068:27)
    at new _Program (@coral-xyz_anchor.js?v=4eaec7da:11179:18)
    at getAnchorProgram (anchor.ts:8:19)
    at pages.tsx:12:17

ソース

import * as anchor from ‘@coral-xyz/anchor’;
import idl from “./kumo_no_ito.json”;

export const getAnchorProgram = (): any => {
  if (!import.meta.env.VITE_PROGRAM_ID) throw new Error(‘Undefined PROGRAM_ID’);

  const programId = new anchor.web3.PublicKey(import.meta.env.VITE_PROGRAM_ID);
  const program = new anchor.Program(idl as anchor.Idl, programId);
  return program;
}

原因

Anchorがデフォルトだと環境がlocalhostを参照していて、localhost参照だとReactみたいなフロントエンドは動かせない(バックエンドのNodeだったら動く)。

以下で環境設定を取得でき、裏では ANCHOR_PROVIDER_URL の値を取得している。

anchor.AnchorProvider.env()

対応

Anchor側だったらAnchor.tomlで対応できるが、Reactだとそれがないため、anchor.Programにconnectionをセットし、そこでdevnetを指定する。

ソース

// Solana
import { Connection, clusterApiUrl } from '@solana/web3.js';

// Anchor
import * as anchor from '@coral-xyz/anchor';
import idl from "./kumo_no_ito.json";

export const getAnchorProgram = (): any => {
  if (!import.meta.env.VITE_PROGRAM_ID) throw new Error('Undefined PROGRAM_ID');

  const programId = new anchor.web3.PublicKey(import.meta.env.VITE_PROGRAM_ID);
  const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');
  const program = new anchor.Program(idl as anchor.Idl, programId, { connection });

  return program;
}

参照

もしかしたら、@solana/wallet-adapter-react の useConnection(), useAnchorWallet() でも、対応できるかもしれない(確認できていないため、間違っている可能性あり)。