Agenda
現象
「% anchor init myAnchor」でanchorを作成後に、かんたんなcounterプログラムを実装して「% anchor test」を実行すると以下のエラーが発生。
実装内容は anchor tutorial basic-2 とほぼ同じ。
(上記だと記述内容が古いため、methodsを使用した書き換えで実装)
% anchor test
myAnchor
1) Creates a counter
0 passing (8ms)
1 failing
1) myAnchor
Creates a counter:
TypeError: Cannot read properties of undefined (reading 'methods')
at /Users/user/Desktop/temp/myAnchor/tests/myAnchor.ts:19:19
at Generator.next (<anonymous>)
at /Users/user/Desktop/temp/myAnchor/tests/myAnchor.ts:31:71
at new Promise (<anonymous>)
at __awaiter (tests/myAnchor.ts:27:12)
at Context.<anonymous> (tests/myAnchor.ts:18:38)
at processImmediate (node:internal/timers:464:21)
use anchor_lang::prelude::*;
declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");
#[program]
pub mod my_anchor {
use super::*;
pub fn create(ctx: Context<Create>, authority: Pubkey) -> Result<()> {
let counter = &mut ctx.accounts.counter;
counter.authority = authority;
counter.count = 0;
Ok(())
}
pub fn increment(ctx: Context<Increment>) -> Result<()> {
let counter = &mut ctx.accounts.counter;
counter.count += 1;
Ok(())
}
}
#[derive(Accounts)]
pub struct Create<'info> {
#[account(init, payer = user, space = 8 + 40)]
pub counter: Account<'info, Counter>,
#[account(mut)]
pub user: Signer<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct Increment<'info> {
#[account(mut, has_one = authority)]
pub counter: Account<'info, Counter>,
pub authority: Signer<'info>,
}
#[account]
pub struct Counter {
pub authority: Pubkey,
pub count: u64,
}
import * as anchor from "@project-serum/anchor";
import { Program } from "@project-serum/anchor";
import { MyAnchor } from "../target/types/my_anchor";
import { assert } from 'chai';
describe("MyAnchor", () => {
// anchor.setProvider(anchor.AnchorProvider.env());
// Configure the client to use the local cluster.
const provider = anchor.AnchorProvider.local();
// Configure the client to use the local cluster.
anchor.setProvider(provider);
// Counter for the tests.
const counter = anchor.web3.Keypair.generate();
const program = anchor.workspace.Counter as Program<MyAnchor>;
it("Creates a counter", async () => {
await program.methods.create(
provider.wallet.publicKey
)
.accounts({
counter: counter.publicKey,
user: provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.signers([counter])
.rpc()
let counterAccount = await program.account.counter.fetch(counter.publicKey);
assert.ok(counterAccount.authority.equals(provider.wallet.publicKey));
assert.ok(counterAccount.count.toNumber() === 0);
});
it("Updates a counter", async () => {
await program.methods.increment()
.accounts({
counter: counter.publicKey,
authority: provider.wallet.publicKey,
})
.rpc()
const counterAccount = await program.account.counter.fetch(
counter.publicKey
);
assert.ok(counterAccount.authority.equals(provider.wallet.publicKey));
assert.ok(counterAccount.count.toNumber() == 1);
});
});
原因
はっきりした原因はわからなかったが、おそらくPJ名(initで指定する名前)が悪さをしていると思われる。
「% anchor init myAnchor」
この、upperLowerCaseがダメっぽい(後述するが、小文字以外すべてダメだった)。
このPJ名は、Cargo.toml、lib.rs、idl(型定義ファイル)に記述されるのだが、program.methodsが、upperLowerCaseやアンダーバーを判別して読み込めていないのでは、という推測。
対応
全部小文字にして暫定的に解決。
「% anchor init myanchor」
大文字小文字、アンダーバー、ハイフンを試したがダメで、すべて小文字の場合しか解決されなかった。
備考
Anchorやnpm関連のファイル削除や1からの再作成など、試行錯誤したが解決できず、名前を変える以外に対応方法がなかった。
2022/7/19時点のバグ(?)と思われるため、そのうち直る可能性あり。
一応、GitHubのIssuesにも本現象 Error testing anchor project #1822 が起案されていた。
なお、「myanchor」を作成したあとに、「myAnchor」「my_anchor」「my-anchor」が作成できるか(大文字小文字、アンダーバー、ハイフンを区別しているのか)を試したところ、結果は区別していなかった。
% anchor init myanchor
〜〜〜作成される〜〜〜
% anchor init myAnchor
Error: File exists (os error 17)
% anchor init my_anchor
Error: Workspace already initialized
% anchor init my-anchor
Error: Workspace already initialized