anchor testで「connect ECONNREFUSED ::1:8899」エラー

SolanaのAnchorで、結合テスト、システムテストとテストファイルを分けて、個別にテスト実行したときに発生した現象。

前提

個別テストする前に、solana-test-validatorでローカルのバリデーターは起動済みの状態:

% solana-test-validator
--faucet-sol argument ignored, ledger already exists
Ledger location: test-ledger
Log: test-ledger/validator.log
⠈ Initializing...
Identity: CYVZukfTPo9MnTob8zQ5ZraMr9n1rfy65BorMiLLogSY
Genesis Hash: 79Mmdu3eybVNJcQVhSDfNrvdSNAxNQmWLoztcRJ7paSM
Version: 1.14.10
Shred Version: 61746
Gossip Address: 127.0.0.1:1024
TPU Address: 127.0.0.1:1027
JSON RPC URL: http://127.0.0.1:8899
⠒ 00:25:19 | Processed Slot: 11244 | Confirmed Slot: 11244 | Finalized Slot: 11212 | Full Snapshot Slot: 11202 | Incremental Snapshot Slot: - | Transactions: 11893 | ◎499.945462500

Anchor.toml:

[features]
seeds = false
skip-lint = false
[programs.localnet]
hok = "CTgTMTJ2jkCU2TKkWa7FNiLa8aEcsu1knKPahSN9tLD"

[registry]
url = "https://api.apr.dev"

[provider]
cluster = "Localnet"
wallet = "~/.config/solana/id.json"

[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
system-test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/system.ts" 

↑個別実行できるように、最終行に system-test を追記している。

ファイル構成(テストファイルの場所のみ):
 tests/integration.ts
 tests/system.ts ← 「anchor run system-test」でこれを実行するようにしている

現象

個別テストを実行すると以下のエラー。

% anchor run system-test
yarn run v1.22.10
warning package.json: No license field
$ /Users/user/Documents/Programming/exit-cafe/Hibernation-of-KUMA/programs/node_modules/.bin/ts-mocha -p ./tsconfig.json -t 1000000 tests/system.ts


  HoK System Test
    1) Airdrop SOL to Users
Success for new record.
undefined
    ✔ Create event by Provider


  1 passing (124ms)
  1 failing

  1) HoK System Test
       Airdrop SOL to Users:
     Error: failed to get recent blockhash: FetchError: request to http://localhost:8899/ failed, reason: connect ECONNREFUSED ::1:8899
      at Connection.getLatestBlockhash (node_modules/@solana/web3.js/src/connection.ts:4498:13)
      at processTicksAndRejections (node:internal/process/task_queues:95:5)



error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

原因

ローカルのバリデーターとURLが異なるため。

ローカルバリデーター:http://127.0.0.1:8899
Anchorが指定したバリデーター:http://localhost:8899/

対応

Anchor.tomlを以下に修正すると、127.0.0.1を指定するようになる。

[provider]
# cluster = "Localnet" # コメントアウト
cluster = "http://127.0.0.1:8899" # 追記
wallet = "~/.config/solana/id.json"

備考

solana-test-validator側の設定変更でも対応できそうな気がしたが、URL指定がうまくいかず断念した。

【追記】
ターミナル上で、solana-test-validatorコマンドで設定を試行錯誤していたが、anchor testで利用するsolana-test-validatorは、おそらく以下で設定が可能と思われる。
試してないが、以下を設定変更することで解決される可能性あり。

Anchor.toml Reference

[test.validator]
url = "https://api.mainnet-beta.solana.com"     # This is the url of the cluster that accounts are cloned from (See `test.validator.clone`).
warp_slot = 1337                                # Warp the ledger to `warp_slot` after starting the validator. 
slots_per_epoch = 5                             # Override the number of slots in an epoch.
rpc_port = 1337                                 # Set JSON RPC on this port, and the next port for the RPC websocket.
limit_ledger_size = 1337                        # Keep this amount of shreds in root slots.
ledger = "test-ledger"                          # Set ledger location.
gossip_port = 1337                              # Gossip port number for the validator.
gossip_host = "127.0.0.1"                       # Gossip DNS name or IP address for the validator to advertise in gossip.
faucet_sol = 1337                               # Give the faucet address this much SOL in genesis.
faucet_port = 1337                              # Enable the faucet on this port.
dynamic_port_range = "1337 - 13337"             # Range to use for dynamically assigned ports.
bind_address = "0.0.0.0"                        # IP address to bind the validator ports.
test.validator.clone

補足

Solanaのprogram(sendAndConfirmTransactionなど)は、本対応でうまくいったが、Anchorで作ったprogram(AnchorでRust開発)したものだと、うまく動かないケースが発生した。
そのときは、nodeのバージョンをv18からv16にダウングレードすることでうまくいった。
おそらく、これが正規の解決方法っぽい。

AnchorのIssuesを見ると、Solana本体のsolana-test-validatorが原因と書かれている。