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:


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());

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,


  • can you take the map_err() off of BorshDeserialize::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
    – trent.sol
    Jul 28, 2022 at 6:48
  • Hey! @CTKI how did you manage to parse Raydium LP? May you share more details? On JS is pretty straight forward but I'm having issues parsing it on rust... Mar 20 at 5:46

1 Answer 1


I think you are getting confused as to what Serum pools are. The code in your link is some sort of agnostic pool which doesn't define a swap capability.

If you read the spl-token-swap documentation "The Token Swap Program was deployed to all networks by the Serum team at SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8". It can be found in the explorer with the Swap program label.


So Serum swap pools are in fact also using spl-token-swap

8Gmi2HhZmwQPVdCwzS7CM66MGstMXPcTVHA7jF19cLZz is a serum-dex market, unrelated to Serum swap pools.

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.