1

I'm using the Solana Playground where I deployed an anchor program that stores a counter and increments the number:

use anchor_lang::prelude::*;

declare_id!("XXXXX....");

#[program]
mod hello_anchor {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        let my_account = &mut ctx.accounts.my_account;
        my_account.data = 42;
        Ok(())
    }

    pub fn update(ctx: Context<Update>, data: u64) -> Result<()> {
        let my_account = &mut ctx.accounts.my_account;
        my_account.data = data;
        Ok(())
    }

    pub fn increment(ctx: Context<Increment>) -> Result<()> {
        let my_account = &mut ctx.accounts.my_account;
        my_account.data += 1;
        Ok(())
    }

    pub fn decrement(ctx: Context<Decrement>) -> Result<()> {
        let my_account = &mut ctx.accounts.my_account;
        my_account.data -= 1;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    // We must specify the space in order to initialize an account.
    // First 8 bytes are default account discriminator,
    // next 8 bytes come from NewAccount.data being type u64.
    // (u64 = 64 bits unsigned integer = 8 bytes)
    #[account(init, payer = signer, space = 8 + 8)]
    pub my_account: Account<'info, NewAccount>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct Update<'info> {
    #[account(mut)]
    pub my_account: Account<'info, NewAccount>,
}

#[derive(Accounts)]
pub struct Increment<'info> {
    #[account(mut)]
    pub my_account: Account<'info, NewAccount>,
    #[account(mut)]
    pub signer: Signer<'info>,
}

#[derive(Accounts)]
pub struct Decrement<'info> {
    #[account(mut)]
    pub my_account: Account<'info, NewAccount>,
}

#[account]
pub struct NewAccount {
    data: u64,
}

I'm then trying to call to it with this code that:

  • calls initialize
  • calls increment
  • reads the user's current value
const myAccount = web3.Keypair.generate(); // Keypair for the account you're creating

try {
  // First call: Initialize the account
  const tx = await pg.program.methods
    .initialize()
    .accounts({
      myAccount: myAccount.publicKey, // Public key of the account to initialize
      signer: pg.wallet.publicKey, // Use the connected wallet's public key for payer
      systemProgram: web3.SystemProgram.programId, // System program ID for creating the account
    })
    .signers([myAccount]) // Include both pg.wallet.payer and myAccount keypairs
    .rpc(); // Send the transaction to the network

  console.log("Transaction Signature for initialize:", tx);

  // Second call: Increment the account data
  const tx2 = await pg.program.methods
    .increment() // Call the increment function
    .accounts({
      myAccount: myAccount.publicKey, // Public key of the account to increment
      // signer: pg.wallet.publicKey,
    })
    // .signers([myAccount]) // Sign with the myAccount keypair for the update
    .rpc(); // Send the transaction to the network

  console.log("Transaction Signature for increment:", tx2);

  // Fetch the account data to check if it has been incremented
  const account = await pg.program.account.newAccount.fetch(
    myAccount.publicKey
  );

  console.log("Account data after increment:", account.data.toString());
} catch (error) {
  console.error("Error:", error);
}

My problem is that most of the time when I run this code it says everything finished successfully, but it incorrectly prints Account data after increment: 42 when it should be 43...

The weird thing is that if I mash the client play button then sometimes I can get it to print 43, but most of the time it prints 42...

Usually I would try to use a timeout somewhere to try to fix this data race kind of thing, but it seems like I can't use setTimeout in the solana playground...

Can anyone explain why this is happening and how I can get the correct thing to print out consistently?

Thanks!

1 Answer 1

1

This is most likely happening because sometimes the transaction is already confirmed when you request the new account data and sometimes it is not.

You can await the confirmation of a transaction like this in playground:

    await pg.connection.confirmTransaction(txHash, "confirmed");

There is multiple confirmation stati on solana processed means that the leader has processed your transaction. Confirmed means that 66% of stake voted for your transaction and finalized means that there are 31 blocks build on top of your transaction.

Confirmed it the best middle way and there as never been a confirmed transaction that did not finalize. Its should take around 400ms - 2s.

https://docs.solanalabs.com/de/consensus/commitments

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.