rialo_spl_token_2022/
lib.rs1#![allow(clippy::arithmetic_side_effects)]
5#![deny(missing_docs)]
6#![cfg_attr(not(test), warn(unsafe_code))]
7
8pub mod error;
11pub mod extension;
12pub mod generic_token_account;
13pub mod instruction;
14pub mod native_mint;
15pub mod offchain;
16pub mod onchain;
17pub mod pod;
18pub mod pod_instruction;
19pub mod processor;
20pub mod state;
21
22#[cfg(not(feature = "no-entrypoint"))]
23mod entrypoint;
24
25use rialo_s_program_error::{ProgramError, ProgramResult};
28use rialo_s_pubkey::Pubkey;
29use rialo_s_sdk_ids::system_program;
30pub use rialo_s_zk_sdk;
31#[cfg(feature = "zk-ops")]
32use rialo_s_zk_sdk::encryption::pod::elgamal::PodElGamalCiphertext;
33#[cfg(feature = "zk-ops")]
34use rialo_spl_token_2022_interface::error::TokenError;
35#[deprecated(
36 since = "9.1.0",
37 note = "Use rialo_spl_token_2022_interface instead and remove spl_token_2022 as a dependency"
38)]
39pub use rialo_spl_token_2022_interface::{check_id, check_program_account, id, ID};
40
41pub fn ui_amount_to_amount(ui_amount: f64, decimals: u8) -> u64 {
44 (ui_amount * 10_usize.pow(decimals as u32) as f64) as u64
45}
46
47pub fn amount_to_ui_amount(amount: u64, decimals: u8) -> f64 {
50 amount as f64 / 10_usize.pow(decimals as u32) as f64
51}
52
53pub fn amount_to_ui_amount_string(amount: u64, decimals: u8) -> String {
56 let decimals = decimals as usize;
57 if decimals > 0 {
58 let mut s = format!("{:01$}", amount, decimals + 1);
60 s.insert(s.len() - decimals, '.');
62 s
63 } else {
64 amount.to_string()
65 }
66}
67
68pub fn amount_to_ui_amount_string_trimmed(amount: u64, decimals: u8) -> String {
71 let s = amount_to_ui_amount_string(amount, decimals);
72 trim_ui_amount_string(s, decimals)
73}
74
75fn trim_ui_amount_string(mut ui_amount: String, decimals: u8) -> String {
77 if decimals > 0 {
78 let zeros_trimmed = ui_amount.trim_end_matches('0');
79 ui_amount = zeros_trimmed.trim_end_matches('.').to_string();
80 }
81 ui_amount
82}
83
84pub fn try_ui_amount_into_amount(ui_amount: String, decimals: u8) -> Result<u64, ProgramError> {
87 let decimals = decimals as usize;
88 let mut parts = ui_amount.split('.');
89 let mut amount_str = parts.next().unwrap().to_string();
92 let after_decimal = parts.next().unwrap_or("");
93 let after_decimal = after_decimal.trim_end_matches('0');
94 if (amount_str.is_empty() && after_decimal.is_empty())
95 || parts.next().is_some()
96 || after_decimal.len() > decimals
97 {
98 return Err(ProgramError::InvalidArgument);
99 }
100
101 amount_str.push_str(after_decimal);
102 for _ in 0..decimals.saturating_sub(after_decimal.len()) {
103 amount_str.push('0');
104 }
105 amount_str
106 .parse::<u64>()
107 .map_err(|_| ProgramError::InvalidArgument)
108}
109
110pub fn check_zk_elgamal_proof_program_account(
113 zk_elgamal_proof_program_id: &Pubkey,
114) -> ProgramResult {
115 if zk_elgamal_proof_program_id != &rialo_s_zk_sdk::zk_elgamal_proof_program::id() {
116 return Err(ProgramError::IncorrectProgramId);
117 }
118 Ok(())
119}
120
121pub fn check_system_program_account(system_program_id: &Pubkey) -> ProgramResult {
123 if system_program_id != &system_program::id() {
124 return Err(ProgramError::IncorrectProgramId);
125 }
126 Ok(())
127}
128
129pub(crate) fn check_elgamal_registry_program_account(
131 elgamal_registry_account_program_id: &Pubkey,
132) -> ProgramResult {
133 if elgamal_registry_account_program_id != &rialo_s_spl_elgamal_registry::id() {
134 return Err(ProgramError::IncorrectProgramId);
135 }
136 Ok(())
137}
138
139#[cfg(feature = "zk-ops")]
141pub(crate) fn check_auditor_ciphertext(
142 instruction_data_auditor_ciphertext_lo: &PodElGamalCiphertext,
143 instruction_data_auditor_ciphertext_hi: &PodElGamalCiphertext,
144 proof_context_auditor_ciphertext_lo: &PodElGamalCiphertext,
145 proof_context_auditor_ciphertext_hi: &PodElGamalCiphertext,
146) -> ProgramResult {
147 if instruction_data_auditor_ciphertext_lo != proof_context_auditor_ciphertext_lo {
148 return Err(TokenError::ConfidentialTransferBalanceMismatch.into());
149 }
150 if instruction_data_auditor_ciphertext_hi != proof_context_auditor_ciphertext_hi {
151 return Err(TokenError::ConfidentialTransferBalanceMismatch.into());
152 }
153 Ok(())
154}