We have a struct like:
#[account(zero_copy)]
#[repr(C)]
pub struct SomeStruct {
pub authority: Pubkey,
pub some_value: u128,
pub another_value: u64,
// etc...
}
This struct has alignment 16 because of the use of u128, which causes issues with some platforms, such as the Rust-based anchor client. We have lots of problems with alignment 16 generally, while 8 is universal. We can fix this by using:
#[account(zero_copy)]
#[repr(C)]
pub struct SomeStruct {
pub authority: Pubkey,
pub some_value: [u8; 16],
pub another_value: u64,
// etc...
}
impl SomeStruct {
pub fn some_value_u128(&self) -> u128 {
bytemuck::cast_slice(&self.some_value)[0]
}
}
Now it aligns 8, which is compatible with everything, and we can still update the value with some_struct.some_value = new_value.to_ne_bytes();
Great. The only problem is that the idl now generates an array like:
"type": {
"array": {
"len": 16,
"type": "u8"
}
}
i.e. a number[], instead of a BN. We can easily make it back into a BN with: new anchor.BN(someStruct.someValue, undefined, "le"),
, so it is easily convertible, but this is annoying for anyone integrating on top of our idl.
How can we force the IDL to treat the [u8; 16]
slice as a BN for deserialization purposes, so it can accessed as a BN like let a: BN = someStruct.someValue
on the TS side without the additional conversion? Ultimately it is a BN, so this should be possible.
Manually editing the IDL to make the type a BN just returns the raw bytes.