pure TS amount arithmetic
This commit is contained in:
parent
180e122ee6
commit
81428771b8
@ -126,6 +126,91 @@ export interface Reserve {
|
||||
reserve_pub: string;
|
||||
}
|
||||
|
||||
export namespace Amounts {
|
||||
export interface Result {
|
||||
amount: AmountJson;
|
||||
// Was there an over-/underflow?
|
||||
saturated: boolean;
|
||||
}
|
||||
|
||||
function getMaxAmount(currency: string) {
|
||||
return {
|
||||
currency,
|
||||
value: Number.MAX_SAFE_INTEGER,
|
||||
fraction: 2**32,
|
||||
}
|
||||
}
|
||||
|
||||
export function add(first: AmountJson, ...rest: AmountJson[]): Result {
|
||||
let currency = first.currency;
|
||||
let value = first.value + Math.floor(first.fraction / 1e6);
|
||||
if (value > Number.MAX_SAFE_INTEGER) {
|
||||
return {amount: getMaxAmount(currency), saturated: true};
|
||||
}
|
||||
let fraction = first.fraction;
|
||||
for (let x of rest) {
|
||||
if (x.currency !== currency) {
|
||||
throw Error(`Mismatched currency: ${x.currency} and ${currency}`);
|
||||
}
|
||||
|
||||
fraction = (fraction + x.fraction) % 1e6;
|
||||
value = value + x.value + (Math.floor(fraction + x.fraction) / 1e6);
|
||||
if (value > Number.MAX_SAFE_INTEGER) {
|
||||
return {amount: getMaxAmount(currency), saturated: true};
|
||||
}
|
||||
}
|
||||
return {amount: {currency, value, fraction}, saturated: false};
|
||||
}
|
||||
|
||||
|
||||
export function sub(a: AmountJson, b: AmountJson): Result {
|
||||
if (a.currency !== b.currency) {
|
||||
throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`);
|
||||
}
|
||||
let currency = a.currency;
|
||||
let value = a.value;
|
||||
let fraction = a.fraction;
|
||||
if (fraction < b.fraction) {
|
||||
if (value < 1) {
|
||||
return {amount: {currency, value: 0, fraction: 0}, saturated: true};
|
||||
}
|
||||
value--;
|
||||
fraction = +1e6;
|
||||
}
|
||||
console.assert(fraction >= b.fraction);
|
||||
fraction -= b.fraction;
|
||||
if (value < b.value) {
|
||||
return {amount: {currency, value: 0, fraction: 0}, saturated: true};
|
||||
}
|
||||
value -= b.value;
|
||||
return {amount: {currency, value, fraction}, saturated: false};
|
||||
}
|
||||
|
||||
export function cmp(a: AmountJson, b: AmountJson): number {
|
||||
if (a.currency !== b.currency) {
|
||||
throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`);
|
||||
}
|
||||
let av = a.value + Math.floor(a.fraction / 1e6);
|
||||
let af = a.fraction % 1e6;
|
||||
let bv = b.value + Math.floor(b.fraction / 1e6);
|
||||
let bf = b.fraction % 1e6;
|
||||
switch (true) {
|
||||
case av < bv:
|
||||
return -1;
|
||||
case av > bv:
|
||||
return 1;
|
||||
case af < bf:
|
||||
return -1;
|
||||
case af > bf:
|
||||
return 1;
|
||||
case af == bf:
|
||||
return 0;
|
||||
default:
|
||||
throw Error("assertion failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface Notifier {
|
||||
notify();
|
||||
}
|
Loading…
Reference in New Issue
Block a user