I'd like to get account data from a Serum Liquidity Pool in my Solana Rust Client.
I have chosen the path to do this in Rust, so please avoid asking why I don't do this in TypeScript.
I have successfully parsed LP data from Raydium, Orca and Saros. Orca and Saros are using the Token Swap Program, so that was fairly easy.
I have used the following Rust Repo from Project Serum, to investigate how the account data (Schema) is laid out:
https://github.com/project-serum/serum-dex/blob/master/pool/schema/src/schema.rs
As you can see, there is a "PoolState" struct, including the "ParamDesc" and "AssetInfo" structs.
My assumption is that this would be the Account data for a liquidity pool which I aim to deserialize in my Rust client.
Example address of a Serum LP: 8Gmi2HhZmwQPVdCwzS7CM66MGstMXPcTVHA7jF19cLZz
When I read the account data from this account, it says that the length is 388 Bytes. Which can also be seen here (Online Borsh Deserializer): https://borsh.m2.xyz/address/8Gmi2HhZmwQPVdCwzS7CM66MGstMXPcTVHA7jF19cLZz
I have used std::mem::size_of:: in Rust, to get the size of the "PoolState" struct in the Rust Repo, which gave me a result of 272 bytes.
println!("Size of PoolState Struct: {}", std::mem::size_of::<PoolState>()
Gives the output:
Size of PoolState Struct: 272
This is a mismatch of 116 Bytes between the PoolState struct and the actual Account Data in the LP account.
I have successfully compared and deserialized other LP account data from other protocols (Raydium for example), so I know that my deserialization and size comparsion functions works. Here is the deserialization function if you want to have a look at it: (However, it doesn't work in this case obviously, since the Stuct and Account data sizes don't match)
pub fn decode_pool_state(accounts: &[Account], program_id: Pubkey) -> PoolResult<Option<PoolState>> {
if accounts.len() < 1 {
return Err(ProgramError::NotEnoughAccountKeys);
}
let account = &accounts[0];
if account.owner != program_id {
msg!("Account not owned by pool program");
return Err(ProgramError::IncorrectProgramId);
};
let data = &account.data.clone();
if data.iter().all(|b| *b == 0) {
println!("{}", "Found 0");
return Ok(None);
}
let mut data: &[u8] = data;
println!("{}","Trying deserialization");
Ok(Some(BorshDeserialize::deserialize(&mut data).map_err(
|e| {
msg!("Borsh Deserialize Message: {}", &e.to_string());
ProgramError::InvalidAccountData
},
)?))
}
I would greatly appreciate any advice here, as to what I might do wrong.
It could simply be that the Rust struct in the Serum Repo is in fact not the correct data structure for de-serialization.
However, the same struct can be found in the TypeScript Repo. https://github.com/project-serum/serum-ts/blob/master/packages/pool/src/schema.ts
Best Regards,
CTKI
map_err()
off ofBorshDeserialize::derserialize()
and post the actual Borsh error?PoolState
has a couple variable length fields, so the account data being over sized isn't necessarily a concern