7

Rust program:

use {
    anchor_lang::prelude::*,
    clockwork_sdk::{
        queue_program::accounts::{Queue, QueueAccount},
        CrankResponse,
    },
};
#[derive(Accounts)]
#[instruction(name: String)]
pub struct HelloWorld<'info> {
    #[account(address = hello_queue.pubkey(), signer)]
    pub hello_queue: Account<'info, Queue>,
}

pub fn handler(_ctx: Context<HelloWorld>, name: String) -> Result<CrankResponse> {
    msg!(
        "Hello {}! The current time is: {}",
        name,
        Clock::get().unwrap().unix_timestamp
    );

    Ok(CrankResponse {
        next_instruction: None,
        kickoff_instruction: None,
    })
}

Client side example to run above program:

fn main() -> ClientResult<()> {
    // Create Client
    let payer = Keypair::new();
    #[cfg(feature = "devnet")]
    let client = Client::new(payer, "https://api.devnet.solana.com".into());
    #[cfg(not(feature = "devnet"))]
    let client = Client::new(payer, "http://localhost:8899".into());

    client.airdrop(&client.payer_pubkey(), 2 * LAMPORTS_PER_SOL)?;

    // Derive PDAs
    let hello_queue = Queue::pubkey(client.payer_pubkey(), "hello".into());

    // airdrop to hello queue
    client.airdrop(&hello_queue, LAMPORTS_PER_SOL)?;

    // Create ix
    let hello_world_ix = Instruction {
        program_id: hello_clockwork::ID,
        accounts: vec![AccountMeta::new(hello_queue, true)],
        data: hello_clockwork::instruction::HelloWorld { name: "Bob".into() }.data(),
    };

    let queue_create = queue_create(
        client.payer_pubkey(),
        "hello".into(),
        hello_world_ix.into(),
        client.payer_pubkey(),
        hello_queue,
        Trigger::Cron {
            schedule: "*/10 * * * * * *".into(),
            skippable: true,
        },
    );

    send_and_confirm_tx(&client, queue_create, "queue_create".into())?;

    println!(
        "queue: https://explorer.solana.com/address/{}?cluster=custom",
        hello_queue
    );

    Ok(())
}

On the ui side, gonna submit a transaction using JavaScript, but need your suggestion because the transaction fails.

...
import * as anchor from "@project-serum/anchor";
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { Transaction } from "@solana/web3.js";
import { HelloClockwork, IDL } from "anchor/types/hello_clockwork";
import HELLO_CLOCKWORK_PROGRAM_ID from "anchor/addresses/hello_clockwork";
import { useAnchorProvider } from "contexts/AnchorProvider";

export const CreateQueue = () => {
  const anchorProvider = useAnchorProvider();
  const { publicKey, sendTransaction } = useWallet();
  const { connection } = useConnection();

  const [queueMsg, setQueueMsg] = useState("Hello World!");
  const handleCreateQueue = async () => {
    if (!anchorProvider) return;

    const helloworldProgram: anchor.Program<HelloClockwork> =
      new anchor.Program(IDL, HELLO_CLOCKWORK_PROGRAM_ID, anchorProvider);

    const queuePublicKey = new anchor.web3.PublicKey(
      "3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv"
    );

    const queueProgram: anchor.Program<QueueProgram> = new anchor.Program(
      QueueIDL,
      queuePublicKey,
      anchorProvider
    );

    const [pda] = await anchor.web3.PublicKey.findProgramAddress(
      [publicKey.toBuffer(), Buffer.from("hello", "utf-8")],
      queuePublicKey
    );

    try {
      ////////// Send Queue Transaction
      const queue_transaction = await queueProgram.methods
        .queueCreate(
          "hello",
          {
            programId: helloworldProgram.programId,
            accounts: [{ pubKey: pda, isSigner: true, isWritable: false }],
            data: Buffer.from(queueMsg, "utf-8"),
          },
          {
            cron: {
              schedule: "*/10 * * * * * *",
              skippable: true,
            },
          }
        )
        .accounts({
          authority: publicKey,
          payer: publicKey,
          queue: pda,
          systemProgram: anchor.web3.SystemProgram.programId,
        })
        .rpc();

      console.log("success!");
    } catch (e) {
      console.log(e);
    }
  };
...

I think I will need to implement this section in javascript. enter image description here

After the transaction submit, I got this error: enter image description here

Also, if I don't approve the transaction immediately, I got this error: enter image description here

3
  • Please share some more info on what you mean when it fails (at least an error message or a clearer description of the failing behaviour)
    – McBain
    Commented Oct 17, 2022 at 14:53
  • Have you had a look at solana.stackexchange.com/questions/295/… yet?
    – McBain
    Commented Oct 17, 2022 at 15:06
  • 1
    Sorry, I got another error
    – Taylor Lee
    Commented Oct 17, 2022 at 15:37

3 Answers 3

3

You can see you got the custom error 0xbbf, or in decimal, 3007. Since this was not defined by you, it must have come from Anchor itself. You can find a reference of the meaning behind all Anchor error codes here.

In your case, the description states

AccountOwnedByWrongProgram

3007 - The given account is owned by a different program than expected

which basically indicates you have some error going on with what program you're deployed to or how you're deriving PDAs.

2
  • This is the third or fourth time you've edited your question significantly. Please open a different question. I'm not trying to be rude to you specifically, but at the end of the day the point of these forums is not to help just you, but also others who might encounter your issue later. This makes frequent & significant editing of questions bad since it means prior answers get lost. (Consider I help you fix your new error and someone is looking for the answer I've previously typed, they would reopen the same initial question even though I had already invested the work to answer it previously)
    – McBain
    Commented Oct 23, 2022 at 19:54
  • Long story short, please edit your question back to what I and @Hi_ImJohn initially wrote our answers for and then open a new question linking what you had done so far in this one, it doesn't cost you anything and makes everyone happier ;)
    – McBain
    Commented Oct 23, 2022 at 19:55
2

In your transaction, you're using the publickey of the connected wallet as the helloQueue account.

  const { publicKey, sendTransaction } = useWallet(); <--- using the publicKey of the connected wallet
 
  ...

  const handleCreateQueue = async () => {
    ...

    try {
      const transaction = await helloworldProgram.methods
        .helloWorld("hello world!!")
        .accounts({
          helloQueue: publicKey <--- using the publicKey of the connected wallet
        })
        .transaction();

      const signature = await sendTransaction(
        new Transaction().add(transaction),
        connection
      );

In your program the hello_queue account is of type Queue. The error possibly because your program is expecting the hello_queue account to be Queue account owned by the queue_program. Not sure how the queue_program you're using works, but maybe you need to initialize a Queue account first?

#[derive(Accounts)]
#[instruction(name: String)]
pub struct HelloWorld<'info> {
    #[account(address = hello_queue.pubkey(), signer)] <--- unsure about these constraints
    pub hello_queue: Account<'info, Queue>, <---- is this supposed to be a Queue Account?
}

If you need to include the connected wallet as a signer, maybe try something like the following:

#[derive(Accounts)]
#[instruction(name: String)]
pub struct HelloWorld<'info> {
    pub hello_queue: Account<'info, Queue>,
    pub user: Signer<'info>,
}
1
  • thanks Hi_I'mJohn but as you can see in the client program, it used PDA. how can we reflect that PDA on the ui side in js?
    – Taylor Lee
    Commented Oct 18, 2022 at 2:55
2

I found the answer: CPI with unauth’d signer error typically happens because of three reasons:

  • One of the accounts you’re mutating does not have the mut attribute
  • you’re passing in an address derived with the wrong seeds
  • you’re passing in different accounts from what the program expects.

So I was using wrong seeds to generate PDA.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.