Skip to content

Commit 2cf72b4

Browse files
committed
feat(settlement): Connector returns the amount & account scale for incoming settlements
1 parent 1c3a182 commit 2cf72b4

File tree

1 file changed

+53
-9
lines changed
  • crates/interledger-settlement/src

1 file changed

+53
-9
lines changed

crates/interledger-settlement/src/api.rs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use log::{debug, error};
1515
use num_bigint::BigUint;
1616
use num_traits::cast::ToPrimitive;
1717
use ring::digest::{digest, SHA256};
18+
use serde_json::json;
1819
use std::{
1920
marker::PhantomData,
2021
str::{self, FromStr},
@@ -204,9 +205,8 @@ impl_web! {
204205
(StatusCode::from_u16(500).unwrap(), error_msg)
205206
})
206207
.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()))
210210
})
211211
})
212212
}))
@@ -315,31 +315,72 @@ mod tests {
315315
mod settlement_tests {
316316
use super::*;
317317

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+
318354
#[test]
319355
fn settlement_ok() {
320356
let id = TEST_ACCOUNT_0.clone().id.to_string();
321357
let store = test_store(false, true);
322358
let api = test_api(store.clone(), false);
323359

360+
let quantity1 = Quantity::new("200000000000", 18);
361+
324362
let ret: Response<_> = api
325-
.receive_settlement(id.clone(), Quantity::new(200, 18), IDEMPOTENCY.clone())
363+
.receive_settlement(id.clone(), quantity1.clone(), IDEMPOTENCY.clone())
326364
.wait()
327365
.unwrap();
366+
let q: Quantity = serde_json::from_slice(ret.body()).unwrap();
328367
assert_eq!(ret.status(), 200);
329-
assert_eq!(ret.body(), "Success");
368+
assert_eq!(q.amount, "200");
369+
assert_eq!(q.scale, 9);
330370

331371
// check that it's idempotent
332372
let ret: Response<_> = api
333-
.receive_settlement(id.clone(), Quantity::new(200, 18), IDEMPOTENCY.clone())
373+
.receive_settlement(id.clone(), quantity1.clone(), IDEMPOTENCY.clone())
334374
.wait()
335375
.unwrap();
336376
assert_eq!(ret.status(), 200);
337-
assert_eq!(ret.body(), "Success");
377+
assert_eq!(q.amount, "200");
378+
assert_eq!(q.scale, 9);
338379

339380
// fails with different account id
340381
let id2 = "2".to_string();
341382
let ret: Response<_> = api
342-
.receive_settlement(id2.clone(), Quantity::new(200, 18), IDEMPOTENCY.clone())
383+
.receive_settlement(id2.clone(), quantity1.clone(), IDEMPOTENCY.clone())
343384
.wait()
344385
.unwrap_err();
345386
assert_eq!(ret.status(), StatusCode::from_u16(409).unwrap());
@@ -377,7 +418,10 @@ mod tests {
377418
let cache_hits = s.cache_hits.read();
378419
assert_eq!(*cache_hits, 4);
379420
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+
);
381425
}
382426

383427
#[test]

0 commit comments

Comments
 (0)