Skip to main content

apl_token/
lib.rs

1#![allow(clippy::arithmetic_side_effects)]
2#![deny(missing_docs)]
3#![cfg_attr(not(test), forbid(unsafe_code))]
4#![allow(unexpected_cfgs)]
5
6//! An ERC20-like Token program for the Arch blockchain
7
8pub mod error;
9pub mod instruction;
10pub mod native_mint;
11pub mod processor;
12pub mod state;
13
14#[cfg(not(feature = "no-entrypoint"))]
15mod entrypoint;
16
17// Export current sdk types for downstream users building with a different sdk
18// version
19pub use arch_program;
20use arch_program::{entrypoint::ProgramResult, program_error::ProgramError, pubkey::Pubkey};
21
22arch_program::declare_id!("TokenT4em53UrV4gSvZ3nCS2mZeHaqTLapwt6iZt6Mk");
23
24/// Convert the UI representation of a token amount (using the decimals field
25/// defined in its mint) to the raw amount
26pub fn ui_amount_to_amount(ui_amount: f64, decimals: u8) -> u64 {
27    (ui_amount * 10_usize.pow(decimals as u32) as f64) as u64
28}
29
30/// Convert a raw amount to its UI representation (using the decimals field
31/// defined in its mint)
32pub fn amount_to_ui_amount(amount: u64, decimals: u8) -> f64 {
33    amount as f64 / 10_usize.pow(decimals as u32) as f64
34}
35
36/// Convert a raw amount to its UI representation (using the decimals field
37/// defined in its mint)
38pub fn amount_to_ui_amount_string(amount: u64, decimals: u8) -> String {
39    let decimals = decimals as usize;
40    if decimals > 0 {
41        // Left-pad zeros to decimals + 1, so we at least have an integer zero
42        let mut s = format!("{:01$}", amount, decimals + 1);
43        // Add the decimal point (Sorry, "," locales!)
44        s.insert(s.len() - decimals, '.');
45        s
46    } else {
47        amount.to_string()
48    }
49}
50
51/// Convert a raw amount to its UI representation using the given decimals field
52/// Excess zeroes or unneeded decimal point are trimmed.
53pub fn amount_to_ui_amount_string_trimmed(amount: u64, decimals: u8) -> String {
54    let mut s = amount_to_ui_amount_string(amount, decimals);
55    if decimals > 0 {
56        let zeros_trimmed = s.trim_end_matches('0');
57        s = zeros_trimmed.trim_end_matches('.').to_string();
58    }
59    s
60}
61
62/// Try to convert a UI representation of a token amount to its raw amount using
63/// the given decimals field
64pub fn try_ui_amount_into_amount(ui_amount: String, decimals: u8) -> Result<u64, ProgramError> {
65    let decimals = decimals as usize;
66    let mut parts = ui_amount.split('.');
67    // splitting a string, even an empty one, will always yield an iterator of
68    // at least length == 1
69    let mut amount_str = parts.next().unwrap().to_string();
70    let after_decimal = parts.next().unwrap_or("");
71    let after_decimal = after_decimal.trim_end_matches('0');
72    if (amount_str.is_empty() && after_decimal.is_empty())
73        || parts.next().is_some()
74        || after_decimal.len() > decimals
75    {
76        return Err(ProgramError::InvalidArgument);
77    }
78
79    amount_str.push_str(after_decimal);
80    for _ in 0..decimals.saturating_sub(after_decimal.len()) {
81        amount_str.push('0');
82    }
83    amount_str
84        .parse::<u64>()
85        .map_err(|_| ProgramError::InvalidArgument)
86}
87
88/// The program ID for the APL-token program
89pub fn check_program_account(apl_token_program_id: &Pubkey) -> ProgramResult {
90    if !check_id(apl_token_program_id) {
91        return Err(ProgramError::IncorrectProgramId);
92    }
93    Ok(())
94}