light_token_interface/state/token/
top_up.rs1use light_compressible::compression_info::CompressionInfo;
4use light_program_profiler::profile;
5#[cfg(target_os = "solana")]
6use pinocchio::account_info::AccountInfo;
7
8use super::ACCOUNT_TYPE_TOKEN_ACCOUNT;
9use crate::state::ExtensionType;
10
11pub const MIN_SIZE_WITH_COMPRESSIBLE: usize = COMPRESSION_INFO_OFFSET + COMPRESSION_INFO_SIZE;
14
15const COMPRESSION_INFO_OFFSET: usize = 176;
18
19const COMPRESSION_INFO_SIZE: usize = 96;
24
25const ACCOUNT_TYPE_OFFSET: usize = 165;
27
28const OPTION_DISCRIMINATOR_OFFSET: usize = 166;
30
31const FIRST_EXT_DISCRIMINATOR_OFFSET: usize = 171;
33
34const OPTION_SOME: u8 = 1;
36
37#[inline(always)]
40#[profile]
41pub fn top_up_lamports_from_slice(
42 data: &[u8],
43 current_lamports: u64,
44 current_slot: u64,
45) -> Option<u64> {
46 if data.len() < MIN_SIZE_WITH_COMPRESSIBLE
47 || data[ACCOUNT_TYPE_OFFSET] != ACCOUNT_TYPE_TOKEN_ACCOUNT
48 || data[OPTION_DISCRIMINATOR_OFFSET] != OPTION_SOME
49 || data[FIRST_EXT_DISCRIMINATOR_OFFSET] != ExtensionType::Compressible as u8
50 {
51 return None;
52 }
53
54 let info: &CompressionInfo = bytemuck::from_bytes(
55 &data[COMPRESSION_INFO_OFFSET..COMPRESSION_INFO_OFFSET + COMPRESSION_INFO_SIZE],
56 );
57
58 info.calculate_top_up_lamports(data.len() as u64, current_slot, current_lamports)
59 .ok()
60}
61
62#[cfg(target_os = "solana")]
67#[inline(always)]
68#[profile]
69pub fn top_up_lamports_from_account_info_unchecked(
70 account_info: &AccountInfo,
71 current_slot: &mut u64,
72) -> Option<u64> {
73 use pinocchio::sysvars::{clock::Clock, Sysvar};
74 let data = account_info.try_borrow_data().ok()?;
75 let current_lamports = account_info.lamports();
76 if *current_slot == 0 {
77 *current_slot = Clock::get().ok()?.slot;
78 }
79 top_up_lamports_from_slice(&data, current_lamports, *current_slot)
80}