12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 |
- use {
- super::{check_account_owner, MAX_FORMATTED_DIGITS, U64_BYTES},
- core::str::from_utf8_unchecked,
- pinocchio::{
- account_info::AccountInfo, program::set_return_data, program_error::ProgramError,
- ProgramResult,
- },
- pinocchio_log::logger::{Argument, Logger},
- spl_token_interface::{
- error::TokenError,
- state::{load, mint::Mint},
- },
- };
- pub fn process_amount_to_ui_amount(
- accounts: &[AccountInfo],
- instruction_data: &[u8],
- ) -> ProgramResult {
- let amount = if instruction_data.len() >= U64_BYTES {
- // SAFETY: The minimum size of the instruction data is `U64_BYTES` bytes.
- unsafe { u64::from_le_bytes(*(instruction_data.as_ptr() as *const [u8; U64_BYTES])) }
- } else {
- return Err(TokenError::InvalidInstruction.into());
- };
- let mint_info = accounts.first().ok_or(ProgramError::NotEnoughAccountKeys)?;
- check_account_owner(mint_info)?;
- // SAFETY: single immutable borrow to `mint_info` account data and
- // `load` validates that the mint is initialized.
- let mint = unsafe {
- load::<Mint>(mint_info.borrow_data_unchecked()).map_err(|_| TokenError::InvalidMint)?
- };
- let mut logger = Logger::<MAX_FORMATTED_DIGITS>::default();
- logger.append_with_args(amount, &[Argument::Precision(mint.decimals)]);
- // "Extract" the formatted string from the logger.
- //
- // SAFETY: the logger is guaranteed to be a valid UTF-8 string.
- let mut s = unsafe { from_utf8_unchecked(&logger) };
- if mint.decimals > 0 && s.contains('.') {
- let zeros_trimmed = s.trim_end_matches('0');
- s = zeros_trimmed.trim_end_matches('.');
- }
- set_return_data(s.as_bytes());
- Ok(())
- }
|