@@ -15,6 +15,7 @@ use log::{debug, error};
15
15
use num_bigint:: BigUint ;
16
16
use num_traits:: cast:: ToPrimitive ;
17
17
use ring:: digest:: { digest, SHA256 } ;
18
+ use serde_json:: json;
18
19
use std:: {
19
20
marker:: PhantomData ,
20
21
str:: { self , FromStr } ,
@@ -204,9 +205,8 @@ impl_web! {
204
205
( StatusCode :: from_u16( 500 ) . unwrap( ) , error_msg)
205
206
} )
206
207
. and_then( move |_| {
207
- // TODO: Return a Quantity of safe_amount and account.asset_scale()
208
- let ret = Bytes :: from( "Success" ) ;
209
- Ok ( ( StatusCode :: OK , ret) )
208
+ let ret = json!( Quantity :: new( safe_amount, account. asset_scale( ) ) ) ;
209
+ Ok ( ( StatusCode :: OK , ret. to_string( ) . into( ) ) )
210
210
} )
211
211
} )
212
212
} ) )
@@ -315,31 +315,72 @@ mod tests {
315
315
mod settlement_tests {
316
316
use super :: * ;
317
317
318
+ #[ test]
319
+ fn handle_overflow ( ) {
320
+ // if upscaling would overflow, return u64::MAX
321
+ let id = TEST_ACCOUNT_0 . clone ( ) . id . to_string ( ) ;
322
+ let store = test_store ( false , true ) ;
323
+ let api = test_api ( store. clone ( ) , false ) ;
324
+ let overflow_quantity = Quantity :: new ( "200000000000" , 1 ) ;
325
+ let ret: Response < _ > = api
326
+ . receive_settlement ( id. clone ( ) , overflow_quantity, None )
327
+ . wait ( )
328
+ . unwrap ( ) ;
329
+ let q: Quantity = serde_json:: from_slice ( ret. body ( ) ) . unwrap ( ) ;
330
+ assert_eq ! ( ret. status( ) , 200 ) ;
331
+ assert_eq ! ( q. amount, std:: u64 :: MAX . to_string( ) ) ;
332
+ assert_eq ! ( q. scale, 9 ) ;
333
+ }
334
+
335
+ #[ test]
336
+ fn handle_precision_loss ( ) {
337
+ // 2 least significant digits get lost
338
+ let id = TEST_ACCOUNT_0 . clone ( ) . id . to_string ( ) ;
339
+ let store = test_store ( false , true ) ;
340
+ let api = test_api ( store. clone ( ) , false ) ;
341
+ let precision_loss_quantity = Quantity :: new ( 123 , 11 ) ;
342
+ let ret: Response < _ > = api
343
+ . receive_settlement ( id. clone ( ) , precision_loss_quantity, None )
344
+ . wait ( )
345
+ . unwrap ( ) ;
346
+ let q: Quantity = serde_json:: from_slice ( ret. body ( ) ) . unwrap ( ) ;
347
+ assert_eq ! ( ret. status( ) , 200 ) ;
348
+ assert_eq ! ( q. amount, 1 . to_string( ) ) ;
349
+ let leftovers = 123 - 1 . normalize_scale ( ConvertDetails { from : 9 , to : 11 } ) ;
350
+ assert_eq ! ( leftovers, 23 ) ;
351
+ assert_eq ! ( q. scale, 9 ) ;
352
+ }
353
+
318
354
#[ test]
319
355
fn settlement_ok ( ) {
320
356
let id = TEST_ACCOUNT_0 . clone ( ) . id . to_string ( ) ;
321
357
let store = test_store ( false , true ) ;
322
358
let api = test_api ( store. clone ( ) , false ) ;
323
359
360
+ let quantity1 = Quantity :: new ( "200000000000" , 18 ) ;
361
+
324
362
let ret: Response < _ > = api
325
- . receive_settlement ( id. clone ( ) , Quantity :: new ( 200 , 18 ) , IDEMPOTENCY . clone ( ) )
363
+ . receive_settlement ( id. clone ( ) , quantity1 . clone ( ) , IDEMPOTENCY . clone ( ) )
326
364
. wait ( )
327
365
. unwrap ( ) ;
366
+ let q: Quantity = serde_json:: from_slice ( ret. body ( ) ) . unwrap ( ) ;
328
367
assert_eq ! ( ret. status( ) , 200 ) ;
329
- assert_eq ! ( ret. body( ) , "Success" ) ;
368
+ assert_eq ! ( q. amount, "200" ) ;
369
+ assert_eq ! ( q. scale, 9 ) ;
330
370
331
371
// check that it's idempotent
332
372
let ret: Response < _ > = api
333
- . receive_settlement ( id. clone ( ) , Quantity :: new ( 200 , 18 ) , IDEMPOTENCY . clone ( ) )
373
+ . receive_settlement ( id. clone ( ) , quantity1 . clone ( ) , IDEMPOTENCY . clone ( ) )
334
374
. wait ( )
335
375
. unwrap ( ) ;
336
376
assert_eq ! ( ret. status( ) , 200 ) ;
337
- assert_eq ! ( ret. body( ) , "Success" ) ;
377
+ assert_eq ! ( q. amount, "200" ) ;
378
+ assert_eq ! ( q. scale, 9 ) ;
338
379
339
380
// fails with different account id
340
381
let id2 = "2" . to_string ( ) ;
341
382
let ret: Response < _ > = api
342
- . receive_settlement ( id2. clone ( ) , Quantity :: new ( 200 , 18 ) , IDEMPOTENCY . clone ( ) )
383
+ . receive_settlement ( id2. clone ( ) , quantity1 . clone ( ) , IDEMPOTENCY . clone ( ) )
343
384
. wait ( )
344
385
. unwrap_err ( ) ;
345
386
assert_eq ! ( ret. status( ) , StatusCode :: from_u16( 409 ) . unwrap( ) ) ;
@@ -377,7 +418,10 @@ mod tests {
377
418
let cache_hits = s. cache_hits . read ( ) ;
378
419
assert_eq ! ( * cache_hits, 4 ) ;
379
420
assert_eq ! ( cached_data. 0 , StatusCode :: OK ) ;
380
- assert_eq ! ( cached_data. 1 , & Bytes :: from( "Success" ) ) ;
421
+ assert_eq ! (
422
+ cached_data. 1 ,
423
+ Bytes :: from( json!( Quantity :: new( "200" , 9 ) ) . to_string( ) )
424
+ ) ;
381
425
}
382
426
383
427
#[ test]
0 commit comments