If [u8; 16]
works for you, then you can trick Anchor into treating it as a u128
by creating a custom type with the same name, "u128"
. To not pollute the outer scope, you declare it in a module. Like so:
mod custom_scope {
use anchor_lang::prelude::*;
#[derive(Copy, Clone, bytemuck::Zeroable, bytemuck::Pod, Debug)]
#[repr(C)]
pub struct u128(pub [u8; 16]);
impl u128 {
pub fn as_u128(&self) -> core::primitive::u128 {
core::primitive::u128::from_le_bytes(self.0)
}
}
#[account(zero_copy)]
#[repr(C)]
pub struct SomeStruct {
pub authority: Pubkey,
pub some_value: u128, // anchor will think this `u128` is a primitive and not a custom type
pub data: u64,
}
}
It is key to also declare SomeStruct
in the same scope so that we can do pub some_value: u128
because this is what tricks Anchor into treating it as a regular u128
and not a custom type.
And now, when your client sends data as u128
you can simply casttransform it into the type the account expects, with custom_scope::u128(some_value.to_le_bytes())
.
Or if you want your my_account.some_value
to act as a u128
, you can simply do my_account.some_value.as_u128()
.
Here's the demo: https://beta.solpg.io/65184223fb53fa325bfd0bc9
Check the test file and notice it treats the someValue
field in the account as BN
without additional conversion. This works because in the account, the byte layout of custom_scope::u128
and u128
is the same so the client can treat it as a simple u128
.
And in the IDL that the above link generates during build, it will show
{
"name": "someValue",
"type": "u128"
}