aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-10-19 22:49:03 +0200
committerFlorian Dold <florian.dold@gmail.com>2016-10-19 22:49:03 +0200
commite6763f3fac0d2c9e6f7459499b960b4d5c54fc66 (patch)
tree6275af237861430a33ecb3aadc395ec26d7d52dc
parent4fd1e07449c97619dbf1e0e17baa47168644dba9 (diff)
downloadwallet-core-e6763f3fac0d2c9e6f7459499b960b4d5c54fc66.tar.xz
show pending outgoing balance in overview
-rw-r--r--lib/wallet/types.ts33
-rw-r--r--lib/wallet/wallet.ts46
-rw-r--r--pages/tree.tsx3
-rw-r--r--popup/popup.tsx54
4 files changed, 101 insertions, 35 deletions
diff --git a/lib/wallet/types.ts b/lib/wallet/types.ts
index 1edfa3601..2df8094a7 100644
--- a/lib/wallet/types.ts
+++ b/lib/wallet/types.ts
@@ -327,6 +327,7 @@ export interface WalletBalance {
export interface WalletBalanceEntry {
available: AmountJson;
pendingIncoming: AmountJson;
+ pendingPayment: AmountJson;
}
@@ -432,26 +433,30 @@ export namespace Amounts {
}
- export function sub(a: AmountJson, b: AmountJson): Result {
- if (a.currency !== b.currency) {
- throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`);
- }
+ export function sub(a: AmountJson, ...rest: AmountJson[]): Result {
let currency = a.currency;
let value = a.value;
let fraction = a.fraction;
- if (fraction < b.fraction) {
- if (value < 1) {
+
+ for (let b of rest) {
+ if (b.currency !== currency) {
+ throw Error(`Mismatched currency: ${b.currency} and ${currency}`);
+ }
+ 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--;
- fraction += 1e6;
+ value -= b.value;
}
- 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 };
}
diff --git a/lib/wallet/wallet.ts b/lib/wallet/wallet.ts
index 851b7b048..f66e42e29 100644
--- a/lib/wallet/wallet.ts
+++ b/lib/wallet/wallet.ts
@@ -153,6 +153,12 @@ interface Transaction {
contract: Contract;
payReq: PayReq;
merchantSig: string;
+
+ /**
+ * The transaction isn't active anymore, it's either successfully paid
+ * or refunded/aborted.
+ */
+ finished: boolean;
}
export enum HistoryLevel {
@@ -461,7 +467,8 @@ export class Wallet {
let x: number;
- function storeExchangeCoin(mc: JoinResult<IExchangeInfo, Coin>, url: string) {
+ function storeExchangeCoin(mc: JoinResult<IExchangeInfo, Coin>,
+ url: string) {
let exchange: IExchangeInfo = mc.left;
console.log("got coin for exchange", url);
let coin: Coin = mc.right;
@@ -584,6 +591,7 @@ export class Wallet {
contract: offer.contract,
payReq: payReq,
merchantSig: offer.merchant_sig,
+ finished: false,
};
let historyEntry: HistoryRecord = {
@@ -835,6 +843,7 @@ export class Wallet {
.put(Stores.reserves, reserve)
.put(Stores.history, historyEntry)
.finish();
+ this.notifier.notify();
this.processReserve(reserve);
}
@@ -915,7 +924,7 @@ export class Wallet {
throw Error("can't withdraw from reserve when current amount is" +
" unknown");
}
- let x = Amounts.sub(currentAmount, preCoin.coinValue);
+ let x = Amounts.sub(currentAmount, preCoin.coinValue, denom.fee_withdraw);
if (x.saturated) {
aborted = true;
throw AbortTransaction;
@@ -928,6 +937,7 @@ export class Wallet {
.put(Stores.precoins, preCoin)
.mutate(Stores.reserves, reserve.reserve_pub, mutateReserve)
.finish();
+ this.notifier.notify();
if (!aborted) {
await this.processPreCoin(preCoin);
}
@@ -987,6 +997,7 @@ export class Wallet {
await this.q()
.put(Stores.reserves, reserve)
.finish();
+ this.notifier.notify();
return reserve;
}
@@ -1186,6 +1197,7 @@ export class Wallet {
balance[currency] = entry = {
available: z,
pendingIncoming: z,
+ pendingPayment: z,
};
}
return entry;
@@ -1228,6 +1240,17 @@ export class Wallet {
return balance;
}
+ function collectPayments(t: Transaction, balance: WalletBalance) {
+ if (t.finished) {
+ return balance;
+ }
+ let entry = ensureEntry(balance, t.contract.amount.currency);
+ entry.pendingPayment = Amounts.add(entry.pendingPayment,
+ t.contract.amount).amount;
+
+ return balance;
+ }
+
function collectSmallestWithdraw(e: IExchangeInfo, sw: any) {
let min: AmountJson|undefined;
for (let d of e.active_denoms) {
@@ -1253,8 +1276,7 @@ export class Wallet {
.iter(Stores.exchanges)
.reduce(collectSmallestWithdraw, {}));
- console.log("smallest withdraw", smallestWithdraw);
-
+ console.log("smallest withdraws", smallestWithdraw)
await (this.q()
.iter(Stores.coins)
.reduce(collectBalances, balance));
@@ -1262,13 +1284,12 @@ export class Wallet {
await (this.q()
.iter(Stores.refresh)
.reduce(collectPendingRefresh, balance));
-
- console.log("balances collected");
-
await (this.q()
.iter(Stores.reserves)
.reduce(collectPendingWithdraw, balance));
- console.log("balance", balance);
+ await (this.q()
+ .iter(Stores.transactions)
+ .reduce(collectPayments, balance));
return balance;
}
@@ -1583,6 +1604,8 @@ export class Wallet {
console.error("contract not found");
return;
}
+ t.finished = true;
+ let modifiedCoins: Coin[] = [];
for (let pc of t.payReq.coins) {
let c = await this.q().get<Coin>(Stores.coins, pc.coin_pub);
if (!c) {
@@ -1590,8 +1613,13 @@ export class Wallet {
return;
}
c.transactionPending = false;
- await this.q().put(Stores.coins, c).finish();
+ modifiedCoins.push(c);
}
+
+ await this.q()
+ .putAll(Stores.coins, modifiedCoins)
+ .put(Stores.transactions, t)
+ .finish();
for (let c of t.payReq.coins) {
this.refresh(c.coin_pub);
}
diff --git a/pages/tree.tsx b/pages/tree.tsx
index 0d1046b34..e782877a5 100644
--- a/pages/tree.tsx
+++ b/pages/tree.tsx
@@ -43,6 +43,9 @@ class ReserveView extends preact.Component<ReserveViewProps, void> {
<ul>
<li>Key: {r.reserve_pub}</li>
<li>Created: {(new Date(r.created * 1000).toString())}</li>
+ <li>Current: {r.current_amount ? prettyAmount(r.current_amount!) : "null"}</li>
+ <li>Requested: {prettyAmount(r.requested_amount)}</li>
+ <li>Confirmed: {r.confirmed}</li>
</ul>
</div>
);
diff --git a/popup/popup.tsx b/popup/popup.tsx
index 31f950c21..121562e31 100644
--- a/popup/popup.tsx
+++ b/popup/popup.tsx
@@ -221,12 +221,46 @@ class WalletBalanceView extends preact.Component<any, any> {
getting started?</div>;
}
- formatPending(amount: AmountJson) {
- return (
- <span>
- (<span style="color: darkgreen">{prettyAmount(amount)}</span> pending)
- </span>
- );
+ formatPending(entry: WalletBalanceEntry): JSX.Element {
+ let incoming: JSX.Element | undefined;
+ let payment: JSX.Element | undefined;
+
+ console.log("available: ", entry.pendingIncoming ? prettyAmount(entry.available) : null);
+ console.log("incoming: ", entry.pendingIncoming ? prettyAmount(entry.pendingIncoming) : null);
+
+ if (Amounts.isNonZero(entry.pendingIncoming)) {
+ incoming = (
+ <span>
+ <span style="color: darkgreen">
+ {"+"}
+ {prettyAmount(entry.pendingIncoming)}
+ </span>
+ {" "}
+ incoming
+ </span>);
+ }
+
+ if (Amounts.isNonZero(entry.pendingPayment)) {
+ payment = (
+ <span>
+ <span style="color: darkblue">
+ {prettyAmount(entry.pendingPayment)}
+ </span>
+ {" "}
+ being spent
+ </span>);
+ }
+
+ let l = [incoming, payment].filter((x) => x !== undefined);
+ if (l.length == 0) {
+ return <span />;
+ }
+
+ if (l.length == 1) {
+ return <span>({l})</span>
+ }
+ return <span>({l[0]}, {l[1]})</span>;
+
}
render(): JSX.Element {
@@ -243,12 +277,8 @@ class WalletBalanceView extends preact.Component<any, any> {
return (
<p>
{prettyAmount(entry.available)}
- { " "}
- {Amounts.isNonZero(entry.pendingIncoming)
- ? this.formatPending(entry.pendingIncoming)
- : []
- }
-
+ {" "}
+ {this.formatPending(entry)}
</p>
);
});