0

I am trying to write data to an account that is the account of the created bet. My smart contract should send reports from the user's account to the bet account. then write down some data (the amount in lamports, the selected party, the public key of the user who made the bet).

I created accounts solana-keygen new -o bet.json - bet account, solana-keygen new -o user1.json - user account.

client and smart contract code

the error indicates that it is not possible to deserialize bet.data. After I checked the betting account in curl, I did not find the data section. How to initialize it?

the structure that I want to write to the account and complete it, like an array

#[derive(BorshSerialize, BorshDeserialize, Debug)]
pub struct Bid {
    /// XJUST lamports
    pub xjust: u64,
    /// selected side
    pub side: u8,
    /// user key
    pub pubkey: String,
}

#[derive(BorshDeserialize, BorshSerialize, Debug)]
pub struct BidData {
    // list bids
    pub bids: Vec<Bid>
}

I am sending the following instructions from the client

//reading accounts
const BET_KEY = readKeypairFromPath(__dirname + '/../localnet/bet.json')
const USER1_KEY = readKeypairFromPath(__dirname + '/../localnet/user1.json')
//...
//createBid(u64, u8) in rust
let createSetValInstruction = (): Buffer => {
  const layout = BufferLayout.struct([
    BufferLayout.u8('instruction'),
    BufferLayout.ns64('xjust'),
    BufferLayout.u8('side')
  ])
  console.log(layout.span);
  const data = Buffer.alloc(layout.span)
  layout.encode({
    xjust: new BN("100000000"),
    side: "1",
    instruction: 2,
  }, data)
  return data
}
//...
const ti = new TransactionInstruction({
    keys: [
      { pubkey: USER1_KEY.publicKey, isSigner: true, isWritable: true },
      { pubkey: BET_KEY.publicKey, isSigner: false, isWritable: true },
      { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
    ],
    programId: PROGRAM_ID.publicKey,
    data: createSetValInstruction(),
  })
  const res = await sendAndConfirmTransaction(connection, new Transaction().add(ti), [USER1_KEY])

instruction processing. There's an error going on here

HelloInstruction::CreateBid(xjust, side) => {
            msg!("value: {:?}", xjust);
            msg!("side: {:?}", side);
            
            let mut bet_account = BidData::try_from_slice(&bet.data.borrow())?;
            let bid = Bid {
                side: side,
                xjust: xjust,
                pubkey: user.key.to_string()
            };
            msg!("bid: {:?}", bid);
            bet_account.bids.push(bid);
         
            bet_account.serialize(&mut &mut bet.data.borrow_mut()[..])?;
            invoke(
                &system_instruction::transfer(user.key, bet.key, xjust),
                &[user.clone(), bet.clone()],
            )?;
        }

I guess that I created the account incorrectly or did not complete some transaction in order to be able to store data in the account. if so, please tell me.

I get an error failed: Failed to serialize or deserialize account data: Unknown', when executing this code:

let mut bet_account = BidData::try_from_slice(&bet.data.borrow())?;
3
  • please add minimal code to reproduce the issue directly in the question as code blocks
    – trent.sol
    Commented Jul 21, 2022 at 17:37
  • @trent.sol added description and code Commented Jul 21, 2022 at 18:05
  • It would be pretty useful if you could post the actual error as well
    – Henry E
    Commented Jul 21, 2022 at 22:02

1 Answer 1

2

In anchor, failure to deserialize an account happens sometimes when a program tries to write more data to an account than the account has space.

It looks like your code example you don't actually create the accounts with any space at all, you just get a keypair solana-keygen new -o bet.json. This is not sufficient to create an account.

Here's an example from the solana cookbook on how to create a system program account using the web3 library. You would need to update the programId with the public key of your program that you intend to edit the data on the account, additionally you would have to change space to match the amount of bytes you want on the accocunt. This leads to recalculating the rentExemptionAmount which is the amount of Sol required to store that amount data in the account.

// amount of space to reserve for the account
const space = 0;

// Seed the created account with lamports for rent exemption
const rentExemptionAmount =
  await connection.getMinimumBalanceForRentExemption(space);

const newAccountPubkey = Keypair.generate();

const createAccountParams = {
  fromPubkey: fromPubkey.publicKey,
  newAccountPubkey: newAccountPubkey.publicKey,
  lamports: rentExemptionAmount,
  space,
  programId: SystemProgram.programId,
};

const createAccountTransaction = new Transaction().add(
  SystemProgram.createAccount(createAccountParams)
);

await sendAndConfirmTransaction(connection, createAccountTransaction, [
  fromPubkey,
  newAccountPubkey,
]);
5
  • I created an account. But the error is the same at the moment try_from_slice() Commented Jul 22, 2022 at 6:26
  • It's still pretty hard to know what error you have if you don't post it. Also, have you considered using anchor instead
    – Henry E
    Commented Jul 22, 2022 at 8:36
  • I get an error "failed: Failed to serialize or deserialize account data: Unknown', when executing this code: let mut bet_account = BidData::try_from_slice(&bet.data.borrow())?; Commented Jul 22, 2022 at 10:13
  • Cool, add that to your main question and hopefully someone else may be familiar with the error and give a good solution. It's possible you want to do borrow_mut
    – Henry E
    Commented Jul 22, 2022 at 10:20
  • I need to get the BidData.bids array from the account and add a new Bid<u64, u8, String> element to it Commented Jul 22, 2022 at 10:25

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.