diff options
author | Florian Dold <florian.dold@gmail.com> | 2016-02-22 20:55:01 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2016-02-22 21:53:05 +0100 |
commit | 81428771b8fc526a692dd26cf3f1421b65e32d6d (patch) | |
tree | 5af00513215837a538ddebda6a001bc026e95b5a /extension/lib/wallet/types.ts | |
parent | 180e122ee639fa41d4cfbca0f57117f5a12fa33a (diff) | |
download | wallet-core-81428771b8fc526a692dd26cf3f1421b65e32d6d.tar.xz |
pure TS amount arithmetic
Diffstat (limited to 'extension/lib/wallet/types.ts')
-rw-r--r-- | extension/lib/wallet/types.ts | 85 |
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 |