show pending outgoing balance in overview
This commit is contained in:
parent
4fd1e07449
commit
e6763f3fac
@ -327,6 +327,7 @@ export interface WalletBalance {
|
|||||||
export interface WalletBalanceEntry {
|
export interface WalletBalanceEntry {
|
||||||
available: AmountJson;
|
available: AmountJson;
|
||||||
pendingIncoming: AmountJson;
|
pendingIncoming: AmountJson;
|
||||||
|
pendingPayment: AmountJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -432,26 +433,30 @@ export namespace Amounts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function sub(a: AmountJson, b: AmountJson): Result {
|
export function sub(a: AmountJson, ...rest: AmountJson[]): Result {
|
||||||
if (a.currency !== b.currency) {
|
|
||||||
throw Error(`Mismatched currency: ${a.currency} and ${b.currency}`);
|
|
||||||
}
|
|
||||||
let currency = a.currency;
|
let currency = a.currency;
|
||||||
let value = a.value;
|
let value = a.value;
|
||||||
let fraction = a.fraction;
|
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 };
|
return { amount: { currency, value: 0, fraction: 0 }, saturated: true };
|
||||||
}
|
}
|
||||||
value--;
|
value -= b.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 };
|
return { amount: { currency, value, fraction }, saturated: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,6 +153,12 @@ interface Transaction {
|
|||||||
contract: Contract;
|
contract: Contract;
|
||||||
payReq: PayReq;
|
payReq: PayReq;
|
||||||
merchantSig: string;
|
merchantSig: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transaction isn't active anymore, it's either successfully paid
|
||||||
|
* or refunded/aborted.
|
||||||
|
*/
|
||||||
|
finished: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum HistoryLevel {
|
export enum HistoryLevel {
|
||||||
@ -461,7 +467,8 @@ export class Wallet {
|
|||||||
|
|
||||||
let x: number;
|
let x: number;
|
||||||
|
|
||||||
function storeExchangeCoin(mc: JoinResult<IExchangeInfo, Coin>, url: string) {
|
function storeExchangeCoin(mc: JoinResult<IExchangeInfo, Coin>,
|
||||||
|
url: string) {
|
||||||
let exchange: IExchangeInfo = mc.left;
|
let exchange: IExchangeInfo = mc.left;
|
||||||
console.log("got coin for exchange", url);
|
console.log("got coin for exchange", url);
|
||||||
let coin: Coin = mc.right;
|
let coin: Coin = mc.right;
|
||||||
@ -584,6 +591,7 @@ export class Wallet {
|
|||||||
contract: offer.contract,
|
contract: offer.contract,
|
||||||
payReq: payReq,
|
payReq: payReq,
|
||||||
merchantSig: offer.merchant_sig,
|
merchantSig: offer.merchant_sig,
|
||||||
|
finished: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let historyEntry: HistoryRecord = {
|
let historyEntry: HistoryRecord = {
|
||||||
@ -835,6 +843,7 @@ export class Wallet {
|
|||||||
.put(Stores.reserves, reserve)
|
.put(Stores.reserves, reserve)
|
||||||
.put(Stores.history, historyEntry)
|
.put(Stores.history, historyEntry)
|
||||||
.finish();
|
.finish();
|
||||||
|
this.notifier.notify();
|
||||||
|
|
||||||
this.processReserve(reserve);
|
this.processReserve(reserve);
|
||||||
}
|
}
|
||||||
@ -915,7 +924,7 @@ export class Wallet {
|
|||||||
throw Error("can't withdraw from reserve when current amount is" +
|
throw Error("can't withdraw from reserve when current amount is" +
|
||||||
" unknown");
|
" unknown");
|
||||||
}
|
}
|
||||||
let x = Amounts.sub(currentAmount, preCoin.coinValue);
|
let x = Amounts.sub(currentAmount, preCoin.coinValue, denom.fee_withdraw);
|
||||||
if (x.saturated) {
|
if (x.saturated) {
|
||||||
aborted = true;
|
aborted = true;
|
||||||
throw AbortTransaction;
|
throw AbortTransaction;
|
||||||
@ -928,6 +937,7 @@ export class Wallet {
|
|||||||
.put(Stores.precoins, preCoin)
|
.put(Stores.precoins, preCoin)
|
||||||
.mutate(Stores.reserves, reserve.reserve_pub, mutateReserve)
|
.mutate(Stores.reserves, reserve.reserve_pub, mutateReserve)
|
||||||
.finish();
|
.finish();
|
||||||
|
this.notifier.notify();
|
||||||
if (!aborted) {
|
if (!aborted) {
|
||||||
await this.processPreCoin(preCoin);
|
await this.processPreCoin(preCoin);
|
||||||
}
|
}
|
||||||
@ -987,6 +997,7 @@ export class Wallet {
|
|||||||
await this.q()
|
await this.q()
|
||||||
.put(Stores.reserves, reserve)
|
.put(Stores.reserves, reserve)
|
||||||
.finish();
|
.finish();
|
||||||
|
this.notifier.notify();
|
||||||
return reserve;
|
return reserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,6 +1197,7 @@ export class Wallet {
|
|||||||
balance[currency] = entry = {
|
balance[currency] = entry = {
|
||||||
available: z,
|
available: z,
|
||||||
pendingIncoming: z,
|
pendingIncoming: z,
|
||||||
|
pendingPayment: z,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
@ -1228,6 +1240,17 @@ export class Wallet {
|
|||||||
return balance;
|
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) {
|
function collectSmallestWithdraw(e: IExchangeInfo, sw: any) {
|
||||||
let min: AmountJson|undefined;
|
let min: AmountJson|undefined;
|
||||||
for (let d of e.active_denoms) {
|
for (let d of e.active_denoms) {
|
||||||
@ -1253,8 +1276,7 @@ export class Wallet {
|
|||||||
.iter(Stores.exchanges)
|
.iter(Stores.exchanges)
|
||||||
.reduce(collectSmallestWithdraw, {}));
|
.reduce(collectSmallestWithdraw, {}));
|
||||||
|
|
||||||
console.log("smallest withdraw", smallestWithdraw);
|
console.log("smallest withdraws", smallestWithdraw)
|
||||||
|
|
||||||
await (this.q()
|
await (this.q()
|
||||||
.iter(Stores.coins)
|
.iter(Stores.coins)
|
||||||
.reduce(collectBalances, balance));
|
.reduce(collectBalances, balance));
|
||||||
@ -1262,13 +1284,12 @@ export class Wallet {
|
|||||||
await (this.q()
|
await (this.q()
|
||||||
.iter(Stores.refresh)
|
.iter(Stores.refresh)
|
||||||
.reduce(collectPendingRefresh, balance));
|
.reduce(collectPendingRefresh, balance));
|
||||||
|
|
||||||
console.log("balances collected");
|
|
||||||
|
|
||||||
await (this.q()
|
await (this.q()
|
||||||
.iter(Stores.reserves)
|
.iter(Stores.reserves)
|
||||||
.reduce(collectPendingWithdraw, balance));
|
.reduce(collectPendingWithdraw, balance));
|
||||||
console.log("balance", balance);
|
await (this.q()
|
||||||
|
.iter(Stores.transactions)
|
||||||
|
.reduce(collectPayments, balance));
|
||||||
return balance;
|
return balance;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1583,6 +1604,8 @@ export class Wallet {
|
|||||||
console.error("contract not found");
|
console.error("contract not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
t.finished = true;
|
||||||
|
let modifiedCoins: Coin[] = [];
|
||||||
for (let pc of t.payReq.coins) {
|
for (let pc of t.payReq.coins) {
|
||||||
let c = await this.q().get<Coin>(Stores.coins, pc.coin_pub);
|
let c = await this.q().get<Coin>(Stores.coins, pc.coin_pub);
|
||||||
if (!c) {
|
if (!c) {
|
||||||
@ -1590,8 +1613,13 @@ export class Wallet {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c.transactionPending = false;
|
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) {
|
for (let c of t.payReq.coins) {
|
||||||
this.refresh(c.coin_pub);
|
this.refresh(c.coin_pub);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,9 @@ class ReserveView extends preact.Component<ReserveViewProps, void> {
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Key: {r.reserve_pub}</li>
|
<li>Key: {r.reserve_pub}</li>
|
||||||
<li>Created: {(new Date(r.created * 1000).toString())}</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -221,12 +221,46 @@ class WalletBalanceView extends preact.Component<any, any> {
|
|||||||
getting started?</div>;
|
getting started?</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
formatPending(amount: AmountJson) {
|
formatPending(entry: WalletBalanceEntry): JSX.Element {
|
||||||
return (
|
let incoming: JSX.Element | undefined;
|
||||||
<span>
|
let payment: JSX.Element | undefined;
|
||||||
(<span style="color: darkgreen">{prettyAmount(amount)}</span> pending)
|
|
||||||
</span>
|
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 {
|
render(): JSX.Element {
|
||||||
@ -243,12 +277,8 @@ class WalletBalanceView extends preact.Component<any, any> {
|
|||||||
return (
|
return (
|
||||||
<p>
|
<p>
|
||||||
{prettyAmount(entry.available)}
|
{prettyAmount(entry.available)}
|
||||||
{ " "}
|
{" "}
|
||||||
{Amounts.isNonZero(entry.pendingIncoming)
|
{this.formatPending(entry)}
|
||||||
? this.formatPending(entry.pendingIncoming)
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user