11#[ cfg( feature = "serde-traits" ) ]
22use serde:: { Deserialize , Serialize } ;
33use {
4- crate :: extension:: { Extension , ExtensionType } ,
4+ crate :: {
5+ extension:: { Extension , ExtensionType } ,
6+ trim_ui_amount_string,
7+ } ,
58 bytemuck:: { Pod , Zeroable } ,
69 solana_program:: program_error:: ProgramError ,
710 spl_pod:: {
@@ -81,7 +84,7 @@ impl InterestBearingConfig {
8184 }
8285
8386 /// Convert a raw amount to its UI representation using the given decimals
84- /// field Excess zeroes or unneeded decimal point are trimmed.
87+ /// field. Excess zeroes or unneeded decimal point are trimmed.
8588 pub fn amount_to_ui_amount (
8689 & self ,
8790 amount : u64 ,
@@ -90,7 +93,8 @@ impl InterestBearingConfig {
9093 ) -> Option < String > {
9194 let scaled_amount_with_interest =
9295 ( amount as f64 ) * self . total_scale ( decimals, unix_timestamp) ?;
93- Some ( scaled_amount_with_interest. to_string ( ) )
96+ let ui_amount = format ! ( "{scaled_amount_with_interest:.*}" , decimals as usize ) ;
97+ Some ( trim_ui_amount_string ( ui_amount, decimals) )
9498 }
9599
96100 /// Try to convert a UI representation of a token amount to its raw amount
@@ -167,6 +171,7 @@ mod tests {
167171
168172 #[ test]
169173 fn specific_amount_to_ui_amount ( ) {
174+ const ONE : u64 = 1_000_000_000_000_000_000 ;
170175 // constant 5%
171176 let config = InterestBearingConfig {
172177 rate_authority : OptionalNonZeroPubkey :: default ( ) ,
@@ -177,25 +182,25 @@ mod tests {
177182 } ;
178183 // 1 year at 5% gives a total of exp(0.05) = 1.0512710963760241
179184 let ui_amount = config
180- . amount_to_ui_amount ( 1 , 0 , INT_SECONDS_PER_YEAR )
185+ . amount_to_ui_amount ( ONE , 18 , INT_SECONDS_PER_YEAR )
181186 . unwrap ( ) ;
182- assert_eq ! ( ui_amount, "1.0512710963760241 " ) ;
187+ assert_eq ! ( ui_amount, "1.051271096376024117 " ) ;
183188 // with 1 decimal place
184189 let ui_amount = config
185- . amount_to_ui_amount ( 1 , 1 , INT_SECONDS_PER_YEAR )
190+ . amount_to_ui_amount ( ONE , 19 , INT_SECONDS_PER_YEAR )
186191 . unwrap ( ) ;
187- assert_eq ! ( ui_amount, "0.10512710963760241 " ) ;
192+ assert_eq ! ( ui_amount, "0.1051271096376024117 " ) ;
188193 // with 10 decimal places
189194 let ui_amount = config
190- . amount_to_ui_amount ( 1 , 10 , INT_SECONDS_PER_YEAR )
195+ . amount_to_ui_amount ( ONE , 28 , INT_SECONDS_PER_YEAR )
191196 . unwrap ( ) ;
192- assert_eq ! ( ui_amount, "0.00000000010512710963760242 " ) ; // different digit at the end!
197+ assert_eq ! ( ui_amount, "0.0000000001051271096376024175 " ) ; // different digits at the end!
193198
194199 // huge amount with 10 decimal places
195200 let ui_amount = config
196201 . amount_to_ui_amount ( 10_000_000_000 , 10 , INT_SECONDS_PER_YEAR )
197202 . unwrap ( ) ;
198- assert_eq ! ( ui_amount, "1.0512710963760241 " ) ;
203+ assert_eq ! ( ui_amount, "1.0512710964 " ) ;
199204
200205 // negative
201206 let config = InterestBearingConfig {
@@ -207,9 +212,9 @@ mod tests {
207212 } ;
208213 // 1 year at -5% gives a total of exp(-0.05) = 0.951229424500714
209214 let ui_amount = config
210- . amount_to_ui_amount ( 1 , 0 , INT_SECONDS_PER_YEAR )
215+ . amount_to_ui_amount ( ONE , 18 , INT_SECONDS_PER_YEAR )
211216 . unwrap ( ) ;
212- assert_eq ! ( ui_amount, "0.951229424500714 " ) ;
217+ assert_eq ! ( ui_amount, "0.951229424500713905 " ) ;
213218
214219 // net out
215220 let config = InterestBearingConfig {
@@ -236,12 +241,12 @@ mod tests {
236241 let ui_amount = config
237242 . amount_to_ui_amount ( u64:: MAX , 0 , INT_SECONDS_PER_YEAR * 2 )
238243 . unwrap ( ) ;
239- assert_eq ! ( ui_amount, "20386805083448100000 " ) ;
244+ assert_eq ! ( ui_amount, "20386805083448098816 " ) ;
240245 let ui_amount = config
241246 . amount_to_ui_amount ( u64:: MAX , 0 , INT_SECONDS_PER_YEAR * 10_000 )
242247 . unwrap ( ) ;
243248 // there's an underflow risk, but it works!
244- assert_eq ! ( ui_amount, "258917064265813830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 " ) ;
249+ assert_eq ! ( ui_amount, "258917064265813826192025834755112557504850551118283225815045099303279643822914042296793377611277551888244755303462190670431480816358154467489350925148558569427069926786360814068189956495940285398273555561779717914539956777398245259214848 " ) ;
245250 }
246251
247252 #[ test]
0 commit comments