Transaction failing while calling a Solana program with PDA

174 views Asked by At

I'm calling a function of anchor_movie_review_program program on devnet CLA5Pk8tpcsA3RPmCYPaRNBdU6xBknRnqshsT1bKT7if.

I cloned the following GitHub https://github.com/Unboxed-Software/anchor-movie-review-program project. The test is running well but when I call it from my vue app it fails. The function name is add_movie_review.

If anyone has any idea about what am I doing wrong and how can I fix it please let me know. Thank you in advance.

I'm forming the Tx in 2 ways but I am failing to add a movie.

# First way :

        const wallet = useWallet();
        const programId = new PublicKey("CLA5Pk8tpcsA3RPmCYPaRNBdU6xBknRnqshsT1bKT7if");
        const provider = new anchor.AnchorProvider(
                            connection,
                            wallet,
                            anchor.AnchorProvider.defaultOptions()
                         );                
        // Generate the program client from IDL. Where MyRaffle is the idl generated by program
        const program = new anchor.Program(MyRaffle, programId, provider);
        const movie = {
                title: "Just a test movie",
                description: "Wow what a good movie it was real great",
                rating: 5,
            };
        const [moviePda] = anchor.web3.PublicKey.findProgramAddressSync(
                [Buffer.from(movie.title), wallet.publicKey.value.toBuffer()],
                program.programId
            );
    
        const tx = await program.methods.addMovieReview(movie.title,  
                            movie.description, movie.rating ).accounts({
                            movieReview: moviePda,
                            initializer: wallet.publicKey.value,
                            systemProgram: anchor.web3.SystemProgram.programId,
                        }).rpc();

# Here is the IDL:

{
    "version": "0.1.0",
    "name": "anchor_movie_review_program",
    "instructions": [
      {
        "name": "addMovieReview",
        "accounts": [
          {
            "name": "movieReview",
            "isMut": true,
            "isSigner": false,
            "pda": {
              "seeds": [
                {
                  "kind": "arg",
                  "type": "string",
                  "path": "title"
                },
                {
                  "kind": "account",
                  "type": "publicKey",
                  "path": "initializer"
                }
              ]
            }
          },
          {
            "name": "initializer",
            "isMut": true,
            "isSigner": true
          },
          {
            "name": "systemProgram",
            "isMut": false,
            "isSigner": false
          }
        ],
        "args": [
          {
            "name": "title",
            "type": "string"
          },
          {
            "name": "description",
            "type": "string"
          },
          {
            "name": "rating",
            "type": "u8"
          }
        ]
      },
      {
        "name": "updateMovieReview",
        "accounts": [
          {
            "name": "movieReview",
            "isMut": true,
            "isSigner": false,
            "pda": {
              "seeds": [
                {
                  "kind": "arg",
                  "type": "string",
                  "path": "title"
                },
                {
                  "kind": "account",
                  "type": "publicKey",
                  "path": "initializer"
                }
              ]
            }
          },
          {
            "name": "initializer",
            "isMut": true,
            "isSigner": true
          },
          {
            "name": "systemProgram",
            "isMut": false,
            "isSigner": false
          }
        ],
        "args": [
          {
            "name": "title",
            "type": "string"
          },
          {
            "name": "description",
            "type": "string"
          },
          {
            "name": "rating",
            "type": "u8"
          }
        ]
      },
      {
        "name": "deleteMovieReview",
        "accounts": [
          {
            "name": "movieReview",
            "isMut": true,
            "isSigner": false,
            "pda": {
              "seeds": [
                {
                  "kind": "arg",
                  "type": "string",
                  "path": "title"
                },
                {
                  "kind": "account",
                  "type": "publicKey",
                  "path": "initializer"
                }
              ]
            }
          },
          {
            "name": "initializer",
            "isMut": true,
            "isSigner": true
          }
        ],
        "args": [
          {
            "name": "title",
            "type": "string"
          }
        ]
      }
    ],
    "accounts": [
      {
        "name": "MovieAccountState",
        "type": {
          "kind": "struct",
          "fields": [
            {
              "name": "reviewer",
              "type": "publicKey"
            },
            {
              "name": "rating",
              "type": "u8"
            },
            {
              "name": "title",
              "type": "string"
            },
            {
              "name": "description",
              "type": "string"
            }
          ]
        }
      }
    ],
    "metadata": {
      "address": "CLA5Pk8tpcsA3RPmCYPaRNBdU6xBknRnqshsT1bKT7if"
    }
  }

With the above code I get the following error

Second Way I try to call it:

  const MOVIE_REVIEW_PROGRAM_ID = 'CLA5Pk8tpcsA3RPmCYPaRNBdU6xBknRnqshsT1bKT7if';` 
  const movie = new Movie(
                "Just a test movie",
                 "Wow what a good movie it was real great",
                 5,
               );
  const wallet = useWallet();
  const connection = new Connection(clusterApiUrl('devnet'));
  const buffer = movie.serialize();
  const transaction = new Transaction();

  const [pda] = await PublicKey.findProgramAddressSync(
        [Buffer.from(movie.title), wallet.publicKey.value.toBuffer()],
        new PublicKey(MOVIE_REVIEW_PROGRAM_ID)
       );
  
  const instruction = new TransactionInstruction({
                keys: [
                    {
                        pubkey: pda,
                        isSigner: false,
                        isWritable: true,
                    },     
                    {
                        pubkey: publicKey.value,
                        isSigner: true,
                        isWritable: true
                    },   
                    {
                        pubkey: SystemProgram.programId,
                        isSigner: false,
                        isWritable: false
                    }
                ],
                data: buffer,
                programId: new PublicKey(MOVIE_REVIEW_PROGRAM_ID)
        });

        transaction.add(instruction);
 
        try {
            let txid = await sendTransaction(transaction, connection)
        } catch (e) {
            alert(JSON.stringify(e))
        }

Here is the movie class:

import * as borsh from "@project-serum/borsh"

export class Movie {
  constructor(title, description, rating) {
    this.title = title
    this.description = description
    this.rating = rating
  }

  borshInstructionSchema = borsh.struct([
    borsh.u8("variant"),
    borsh.str("title"),
    borsh.str("description"),
    borsh.u8("rating")
  ])

  static borshAccountSchema = borsh.struct([
    borsh.bool("initialized"),
    borsh.str("title"),
    borsh.str("description"),
    borsh.u8("rating")
  ])

  serialize() {
    const buffer = Buffer.alloc(1000)
    this.borshInstructionSchema.encode({ ...this, variant: 0 }, buffer)
    return buffer.slice(0, this.borshInstructionSchema.getSpan(buffer))
  }

  static deserialize(buffer) {
    if (!buffer) {
      return null
    }

    try {
      const { title, description , rating} = this.borshAccountSchema.decode(
        buffer
      )
      return new Movie(title, description, rating)
    } catch (e) {
      console.log("Deserialization error:", e)
      console.log(buffer)
      return null
    }
  }
}

With the second approach, I get the following

1

There are 1 answers

1
Yadav Akash On

I think the invalid character error comes from this line of code initializer: wallet.publicKey.value because when you use it in your IDL file the initializer is a signer, and when you pass the account address while calling the addMovieReview method you have to pass wallet.publicKey not wallet.publicKey.value.