Solana Anchorで「Fallback functions are not supported」エラー

現象

anchor testを実行すると以下のエラーが表示される。

1) post_to_earn
    Creates a payment account.:
    Error: 101: Fallback functions are not supported
    at Function.parse (node_modules/@project-serum/anchor/src/error.ts:53:14)
    at Object.rpc [as createPayment] (node_modules/@project-serum/anchor/src/program/namespace/rpc.ts:32:42)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

問題が発生している箇所:

    pub fn createPayment(ctx: Context<CreatePayment>) -> Result<()> {
        let payment = &mut ctx.accounts.payment;
        payment.bump = *ctx.bumps.get("payment").unwrap();
        payment.count = 0;
        Ok(())
    }

原因

Rustの関数につける命名ルールに違反しているため。以下のように lowerCamelCase でつけてしまっていた。

pub fn createPayment

対応

正しくは snake_case になる。

Rust命名ルール

以下のように修正して完了。

    pub fn create_payment(ctx: Context<CreatePayment>) -> Result<()> {
        let payment = &mut ctx.accounts.payment;
        payment.bump = *ctx.bumps.get("payment").unwrap();
        payment.count = 0;
        Ok(())
    }

補足

以下のように「TypeError: program.rpc.create_payment is not a function」エラーが出力された場合も、命名規則がおかしい。

1) post_to_earn
Creates a payment account.:
TypeError: program.rpc.create_payment is not a function
at /Users/user/Documents/Programming/Blockchain/solana-anchor-react-minimal-example/anchor/post_to_earn/tests/post_to_earn.ts:92:48
at Generator.next (<anonymous>)
at /Users/user/Documents/Programming/Blockchain/solana-anchor-react-minimal-example/anchor/post_to_earn/tests/post_to_earn.ts:31:71
at new Promise (<anonymous>)
at __awaiter (tests/post_to_earn.ts:27:12)
at Context.<anonymous> (tests/post_to_earn.ts:91:47)
at processImmediate (node:internal/timers:464:21)

ソースは以下のようになっている。

lib.rs

    pub fn create_payment(ctx: Context<CreatePayment>) -> Result<()> {
        let payment = &mut ctx.accounts.payment;
        payment.bump = *ctx.bumps.get("payment").unwrap();
        payment.count = 0;
        Ok(())
    }

post_to_earn.ts

    const createPayment_tx = await program.rpc.create_payment(
      {
        accounts: {
          user: provider.wallet.publicKey,
          payment: pdaPayment,
          systemProgram: SystemProgram.programId
        }
      }
    );

今回の場合は、Rust側ではなくTypeScript側の関数の呼び出し方が違反していた。

正しくは以下になる。

post_to_earn.ts

    const createPayment_tx = await program.rpc.createPayment(

命名ルールの整理

整理すると以下の命名ルールで関数の定義/呼び出しになる。

 Rust側(関数の定義):snake_case (例)pub fn create_payment()
 TypeScript側(関数の呼び出し):lowerCamelCase (例)program.rpc.createPayment()