Soldev

Anchor serialization

Last updated:

Clients will send transactions which include instruction data. When these transactions are sent over the wire, their instructions are first compressed into bytes which is then compressed into a compact Base58 representation.

Base58 is a type of binary to text encoding.

While everything on Solana is stored in bytes, transforming them into Base58 for data transfer over-the-wire is done as an optimization.

On the other side, as a receiver, you also must be able to translate that Base58 code into something meaningful, like a Struct, when receiving transactions. Once it has been deserialized, validated, and executed it will again be serialized into byte code to be written to the account's buffer.

Serialization

The client and the program must serialize in an identical way. In order to facilitate this, Anchor uses Borsh serialization as a standard, and is our default serializer when we're using Anchor with Rust.

What the program actually receives is the individually parsed instructions, in this format:

fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult

The transaction structure (signatures, blockhash, full message, etc.) is never exposed to your on-chain logic, instead it receives the final parsed instructions.

Given that the Pubkey and AccountInfo have already been parsed into formats that the Rust program can understand, the only thing to parse is the u8 instruction data.

This is where the program would use Borsh serialization to transform that transaction data into the specific structs it would need to handle.

Deserializing with javascript

On the client side, we generate a client that will convert the native Rust types into their corresponding Typescript types.

RustTypescriptExample
boolbooleantrue
u8/u16/u32/i8/i16/i32number99
u64/u128/i64/i128anchor.BNnew anchor.BN(99)
f32/f64number1.0
Stringstring"hello"
[T; N]Array<T>[1, 2, 3]
Vec<T>Array<T>[1, 2, 3]
Option<T>T | null | undefinednull or 42 (some)

More complicated objects like structs become types themselves:

// Rust
struct MyStruct {
  val: u16
}
// Typescript
type MyStruct = {
  val: number;
}