aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-02-22 20:55:01 +0100
committerFlorian Dold <florian.dold@gmail.com>2016-02-22 21:53:05 +0100
commit81428771b8fc526a692dd26cf3f1421b65e32d6d (patch)
tree5af00513215837a538ddebda6a001bc026e95b5a
parent180e122ee639fa41d4cfbca0f57117f5a12fa33a (diff)
pure TS amount arithmetic
-rw-r--r--extension/lib/wallet/types.ts85
1 files changed, 85 insertions, 0 deletions
diff --git a/extension/lib/wallet/types.ts b/extension/lib/wallet/types.ts
index d18bd95f4..cfd30bbc3 100644
--- a/extension/lib/wallet/types.ts
+++ b/extension/lib/wallet/types.ts
@@ -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();
} \ No newline at end of file