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
}
}
}
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.