1
1
#[ cfg( feature = "serde-traits" ) ]
2
2
use serde:: { Deserialize , Serialize } ;
3
3
use {
4
- crate :: extension:: { Extension , ExtensionType } ,
4
+ crate :: {
5
+ extension:: { Extension , ExtensionType } ,
6
+ trim_ui_amount_string,
7
+ } ,
5
8
bytemuck:: { Pod , Zeroable } ,
6
9
solana_program:: program_error:: ProgramError ,
7
10
spl_pod:: {
@@ -81,7 +84,7 @@ impl InterestBearingConfig {
81
84
}
82
85
83
86
/// 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.
85
88
pub fn amount_to_ui_amount (
86
89
& self ,
87
90
amount : u64 ,
@@ -90,7 +93,8 @@ impl InterestBearingConfig {
90
93
) -> Option < String > {
91
94
let scaled_amount_with_interest =
92
95
( 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) )
94
98
}
95
99
96
100
/// Try to convert a UI representation of a token amount to its raw amount
@@ -167,6 +171,7 @@ mod tests {
167
171
168
172
#[ test]
169
173
fn specific_amount_to_ui_amount ( ) {
174
+ const ONE : u64 = 1_000_000_000_000_000_000 ;
170
175
// constant 5%
171
176
let config = InterestBearingConfig {
172
177
rate_authority : OptionalNonZeroPubkey :: default ( ) ,
@@ -177,25 +182,25 @@ mod tests {
177
182
} ;
178
183
// 1 year at 5% gives a total of exp(0.05) = 1.0512710963760241
179
184
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 )
181
186
. unwrap ( ) ;
182
- assert_eq ! ( ui_amount, "1.0512710963760241 " ) ;
187
+ assert_eq ! ( ui_amount, "1.051271096376024117 " ) ;
183
188
// with 1 decimal place
184
189
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 )
186
191
. unwrap ( ) ;
187
- assert_eq ! ( ui_amount, "0.10512710963760241 " ) ;
192
+ assert_eq ! ( ui_amount, "0.1051271096376024117 " ) ;
188
193
// with 10 decimal places
189
194
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 )
191
196
. 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!
193
198
194
199
// huge amount with 10 decimal places
195
200
let ui_amount = config
196
201
. amount_to_ui_amount ( 10_000_000_000 , 10 , INT_SECONDS_PER_YEAR )
197
202
. unwrap ( ) ;
198
- assert_eq ! ( ui_amount, "1.0512710963760241 " ) ;
203
+ assert_eq ! ( ui_amount, "1.0512710964 " ) ;
199
204
200
205
// negative
201
206
let config = InterestBearingConfig {
@@ -207,9 +212,9 @@ mod tests {
207
212
} ;
208
213
// 1 year at -5% gives a total of exp(-0.05) = 0.951229424500714
209
214
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 )
211
216
. unwrap ( ) ;
212
- assert_eq ! ( ui_amount, "0.951229424500714 " ) ;
217
+ assert_eq ! ( ui_amount, "0.951229424500713905 " ) ;
213
218
214
219
// net out
215
220
let config = InterestBearingConfig {
@@ -236,12 +241,12 @@ mod tests {
236
241
let ui_amount = config
237
242
. amount_to_ui_amount ( u64:: MAX , 0 , INT_SECONDS_PER_YEAR * 2 )
238
243
. unwrap ( ) ;
239
- assert_eq ! ( ui_amount, "20386805083448100000 " ) ;
244
+ assert_eq ! ( ui_amount, "20386805083448098816 " ) ;
240
245
let ui_amount = config
241
246
. amount_to_ui_amount ( u64:: MAX , 0 , INT_SECONDS_PER_YEAR * 10_000 )
242
247
. unwrap ( ) ;
243
248
// there's an underflow risk, but it works!
244
- assert_eq ! ( ui_amount, "258917064265813830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 " ) ;
249
+ assert_eq ! ( ui_amount, "258917064265813826192025834755112557504850551118283225815045099303279643822914042296793377611277551888244755303462190670431480816358154467489350925148558569427069926786360814068189956495940285398273555561779717914539956777398245259214848 " ) ;
245
250
}
246
251
247
252
#[ test]
0 commit comments