use light_compressed_account::Pubkey;
use crate::{
state::{AccountState, ExtensionStruct, Token, ACCOUNT_TYPE_TOKEN_ACCOUNT},
AnchorDeserialize, AnchorSerialize,
};
impl AnchorSerialize for Token {
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_all(&self.mint.to_bytes())?;
writer.write_all(&self.owner.to_bytes())?;
writer.write_all(&self.amount.to_le_bytes())?;
if let Some(delegate) = self.delegate {
writer.write_all(&[1, 0, 0, 0])?; writer.write_all(&delegate.to_bytes())?;
} else {
writer.write_all(&[0; 36])?; }
writer.write_all(&[self.state as u8])?;
if let Some(is_native) = self.is_native {
writer.write_all(&[1, 0, 0, 0])?; writer.write_all(&is_native.to_le_bytes())?;
} else {
writer.write_all(&[0; 12])?; }
writer.write_all(&self.delegated_amount.to_le_bytes())?;
if let Some(close_authority) = self.close_authority {
writer.write_all(&[1, 0, 0, 0])?; writer.write_all(&close_authority.to_bytes())?;
} else {
writer.write_all(&[0; 36])?; }
if self.extensions.is_some() {
writer.write_all(&[self.account_type])?;
self.extensions.serialize(writer)?;
}
Ok(())
}
}
impl AnchorDeserialize for Token {
fn deserialize_reader<R: std::io::Read>(buf: &mut R) -> std::io::Result<Self> {
let mut mint_bytes = [0u8; 32];
buf.read_exact(&mut mint_bytes)?;
let mint = Pubkey::from(mint_bytes);
let mut owner_bytes = [0u8; 32];
buf.read_exact(&mut owner_bytes)?;
let owner = Pubkey::from(owner_bytes);
let mut amount_bytes = [0u8; 8];
buf.read_exact(&mut amount_bytes)?;
let amount = u64::from_le_bytes(amount_bytes);
let mut discriminator = [0u8; 4];
buf.read_exact(&mut discriminator)?;
let mut pubkey_bytes = [0u8; 32];
buf.read_exact(&mut pubkey_bytes)?;
let delegate = if u32::from_le_bytes(discriminator) == 1 {
Some(Pubkey::from(pubkey_bytes))
} else {
None
};
let mut state = [0u8; 1];
buf.read_exact(&mut state)?;
let state = state[0];
let mut discriminator = [0u8; 4];
buf.read_exact(&mut discriminator)?;
let mut value_bytes = [0u8; 8];
buf.read_exact(&mut value_bytes)?;
let is_native = if u32::from_le_bytes(discriminator) == 1 {
Some(u64::from_le_bytes(value_bytes))
} else {
None
};
let mut delegated_amount_bytes = [0u8; 8];
buf.read_exact(&mut delegated_amount_bytes)?;
let delegated_amount = u64::from_le_bytes(delegated_amount_bytes);
let mut discriminator = [0u8; 4];
buf.read_exact(&mut discriminator)?;
let mut pubkey_bytes = [0u8; 32];
buf.read_exact(&mut pubkey_bytes)?;
let close_authority = if u32::from_le_bytes(discriminator) == 1 {
Some(Pubkey::from(pubkey_bytes))
} else {
None
};
let mut account_type_byte = [0u8; 1];
let (account_type, extensions) = if buf.read_exact(&mut account_type_byte).is_ok() {
let account_type = account_type_byte[0];
if account_type == ACCOUNT_TYPE_TOKEN_ACCOUNT {
let extensions =
Option::<Vec<ExtensionStruct>>::deserialize_reader(buf).unwrap_or_default();
(account_type, extensions)
} else {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Account type does not match Token account",
));
}
} else {
(ACCOUNT_TYPE_TOKEN_ACCOUNT, None)
};
Ok(Self {
mint,
owner,
amount,
delegate,
state: AccountState::try_from(state)
.map_err(|e| std::io::Error::from_raw_os_error(u32::from(e) as i32))?,
is_native,
delegated_amount,
close_authority,
account_type,
extensions,
})
}
}