diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-12-16 21:10:57 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-12-16 21:10:57 +0100 |
commit | fb6508de9d71600dbca59cb0e6a4c77e4f3f3ee5 (patch) | |
tree | 8f1e9e50574ee6d9f561cb93d2ea29663943672d /src/operations | |
parent | c2ee8fd9ab6754275d7423152681236a46cf36a9 (diff) | |
download | wallet-core-fb6508de9d71600dbca59cb0e6a4c77e4f3f3ee5.tar.xz |
finish refresh correctly, display fees correctly
Diffstat (limited to 'src/operations')
-rw-r--r-- | src/operations/history.ts | 69 | ||||
-rw-r--r-- | src/operations/pending.ts | 2 | ||||
-rw-r--r-- | src/operations/refresh.ts | 14 | ||||
-rw-r--r-- | src/operations/reserves.ts | 161 |
4 files changed, 150 insertions, 96 deletions
diff --git a/src/operations/history.ts b/src/operations/history.ts index eec398f37..bb57a9c60 100644 --- a/src/operations/history.ts +++ b/src/operations/history.ts @@ -61,7 +61,6 @@ function getOrderShortInfo( }; } - async function collectProposalHistory( tx: TransactionHandle, history: HistoryEvent[], @@ -162,6 +161,7 @@ export async function getHistory( await ws.db.runWithReadTransaction( [ Stores.currencies, + Stores.coins, Stores.exchanges, Stores.exchangeUpdatedEvents, Stores.proposals, @@ -220,15 +220,22 @@ export async function getHistory( await collectProposalHistory(tx, history, historyQuery); - await tx.iter(Stores.payEvents).forEachAsync(async (pe) => { + await tx.iter(Stores.payEvents).forEachAsync(async pe => { const proposal = await tx.get(Stores.proposals, pe.proposalId); if (!proposal) { return; } + const purchase = await tx.get(Stores.purchases, pe.proposalId); + if (!purchase) { + return; + } const orderShortInfo = getOrderShortInfo(proposal); if (!orderShortInfo) { return; } + const amountPaidWithFees = Amounts.sum( + purchase.payReq.coins.map(x => Amounts.parseOrThrow(x.contribution)), + ).amount; history.push({ type: HistoryEventType.PaymentSent, eventId: makeEventId(HistoryEventType.PaymentSent, pe.proposalId), @@ -236,10 +243,12 @@ export async function getHistory( replay: pe.isReplay, sessionId: pe.sessionId, timestamp: pe.timestamp, + numCoins: purchase.payReq.coins.length, + amountPaidWithFees: Amounts.toString(amountPaidWithFees), }); }); - await tx.iter(Stores.refreshGroups).forEachAsync(async (rg) => { + await tx.iter(Stores.refreshGroups).forEachAsync(async rg => { if (!rg.timestampFinished) { return; } @@ -251,23 +260,26 @@ export async function getHistory( for (let i = 0; i < rg.refreshSessionPerCoin.length; i++) { const session = rg.refreshSessionPerCoin[i]; numInputCoins++; + const c = await tx.get(Stores.coins, rg.oldCoinPubs[i]); + if (!c) { + continue; + } if (session) { numRefreshedInputCoins++; amountsRaw.push(session.amountRefreshInput); + amountsRaw.push(c.currentAmount); amountsEffective.push(session.amountRefreshOutput); numOutputCoins += session.newDenoms.length; } else { - const c = await tx.get(Stores.coins, rg.oldCoinPubs[i]); - if (!c) { - continue; - } amountsRaw.push(c.currentAmount); } } let amountRefreshedRaw = Amounts.sum(amountsRaw).amount; let amountRefreshedEffective: AmountJson; if (amountsEffective.length == 0) { - amountRefreshedEffective = Amounts.getZero(amountRefreshedRaw.currency); + amountRefreshedEffective = Amounts.getZero( + amountRefreshedRaw.currency, + ); } else { amountRefreshedEffective = Amounts.sum(amountsEffective).amount; } @@ -285,7 +297,7 @@ export async function getHistory( }); }); - tx.iter(Stores.reserveUpdatedEvents).forEachAsync(async (ru) => { + tx.iter(Stores.reserveUpdatedEvents).forEachAsync(async ru => { const reserve = await tx.get(Stores.reserves, ru.reservePub); if (!reserve) { return; @@ -295,28 +307,31 @@ export async function getHistory( reserveCreationDetail = { type: ReserveType.TalerBankWithdraw, bankUrl: reserve.bankWithdrawStatusUrl, - } + }; } else { reserveCreationDetail = { type: ReserveType.Manual, - } + }; } history.push({ type: HistoryEventType.ReserveBalanceUpdated, - eventId: makeEventId(HistoryEventType.ReserveBalanceUpdated, ru.reserveUpdateId), + eventId: makeEventId( + HistoryEventType.ReserveBalanceUpdated, + ru.reserveUpdateId, + ), amountExpected: ru.amountExpected, amountReserveBalance: ru.amountReserveBalance, - timestamp: reserve.timestampCreated, + timestamp: ru.timestamp, newHistoryTransactions: ru.newHistoryTransactions, reserveShortInfo: { exchangeBaseUrl: reserve.exchangeBaseUrl, reserveCreationDetail, reservePub: reserve.reservePub, - } + }, }); }); - tx.iter(Stores.tips).forEach((tip) => { + tx.iter(Stores.tips).forEach(tip => { if (tip.acceptedTimestamp) { history.push({ type: HistoryEventType.TipAccepted, @@ -328,7 +343,7 @@ export async function getHistory( } }); - tx.iter(Stores.refundEvents).forEachAsync(async (re) => { + tx.iter(Stores.refundEvents).forEachAsync(async re => { const proposal = await tx.get(Stores.proposals, re.proposalId); if (!proposal) { return; @@ -341,7 +356,9 @@ export async function getHistory( if (!orderShortInfo) { return; } - const purchaseAmount = Amounts.parseOrThrow(purchase.contractTerms.amount); + const purchaseAmount = Amounts.parseOrThrow( + purchase.contractTerms.amount, + ); let amountRefundedRaw = Amounts.getZero(purchaseAmount.currency); let amountRefundedInvalid = Amounts.getZero(purchaseAmount.currency); let amountRefundedEffective = Amounts.getZero(purchaseAmount.currency); @@ -352,9 +369,16 @@ export async function getHistory( } const refundAmount = Amounts.parseOrThrow(r.perm.refund_amount); const refundFee = Amounts.parseOrThrow(r.perm.refund_fee); - amountRefundedRaw = Amounts.add(amountRefundedRaw, refundAmount).amount; - amountRefundedEffective = Amounts.add(amountRefundedEffective, refundAmount).amount; - amountRefundedEffective = Amounts.sub(amountRefundedEffective, refundFee).amount; + amountRefundedRaw = Amounts.add(amountRefundedRaw, refundAmount) + .amount; + amountRefundedEffective = Amounts.add( + amountRefundedEffective, + refundAmount, + ).amount; + amountRefundedEffective = Amounts.sub( + amountRefundedEffective, + refundFee, + ).amount; }); Object.keys(purchase.refundState.refundsFailed).forEach((x, i) => { const r = purchase.refundState.refundsFailed[x]; @@ -365,7 +389,10 @@ export async function getHistory( const refundFee = Amounts.parseOrThrow(r.perm.refund_fee); amountRefundedRaw = Amounts.add(amountRefundedRaw, ra).amount; amountRefundedInvalid = Amounts.add(amountRefundedInvalid, ra).amount; - amountRefundedEffective = Amounts.sub(amountRefundedEffective, refundFee).amount; + amountRefundedEffective = Amounts.sub( + amountRefundedEffective, + refundFee, + ).amount; }); history.push({ type: HistoryEventType.Refund, diff --git a/src/operations/pending.ts b/src/operations/pending.ts index ffa23f101..360180854 100644 --- a/src/operations/pending.ts +++ b/src/operations/pending.ts @@ -224,6 +224,8 @@ async function gatherRefreshPending( type: PendingOperationType.Refresh, givesLifeness: true, refreshGroupId: r.refreshGroupId, + finishedPerCoin: r.finishedPerCoin, + retryInfo: r.retryInfo, }); }); } diff --git a/src/operations/refresh.ts b/src/operations/refresh.ts index f602221af..8390cac54 100644 --- a/src/operations/refresh.ts +++ b/src/operations/refresh.ts @@ -144,10 +144,22 @@ async function refreshCreateSession( return; } rg.finishedPerCoin[coinIndex] = true; + rg.finishedPerCoin[coinIndex] = true; + let allDone = true; + for (const f of rg.finishedPerCoin) { + if (!f) { + allDone = false; + break; + } + } + if (allDone) { + rg.timestampFinished = getTimestampNow(); + rg.retryInfo = initRetryInfo(false); + } await tx.put(Stores.refreshGroups, rg); }, ); - ws.notify({ type: NotificationType.RefreshRefused }); + ws.notify({ type: NotificationType.RefreshUnwarranted }); return; } diff --git a/src/operations/reserves.ts b/src/operations/reserves.ts index 649bf75f2..7be927824 100644 --- a/src/operations/reserves.ts +++ b/src/operations/reserves.ts @@ -34,12 +34,14 @@ import { updateRetryInfoTimeout, ReserveUpdatedEventRecord, } from "../types/dbTypes"; -import { - TransactionAbort, -} from "../util/query"; +import { TransactionAbort } from "../util/query"; import { Logger } from "../util/logging"; import * as Amounts from "../util/amounts"; -import { updateExchangeFromUrl, getExchangeTrust, getExchangePaytoUri } from "./exchanges"; +import { + updateExchangeFromUrl, + getExchangeTrust, + getExchangePaytoUri, +} from "./exchanges"; import { WithdrawOperationStatusResponse } from "../types/talerTypes"; import { assertUnreachable } from "../util/assertUnreachable"; import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto"; @@ -49,7 +51,10 @@ import { processWithdrawSession, getBankWithdrawalInfo, } from "./withdraw"; -import { guardOperationException, OperationFailedAndReportedError } from "./errors"; +import { + guardOperationException, + OperationFailedAndReportedError, +} from "./errors"; import { NotificationType } from "../types/notifications"; import { codecForReserveStatus } from "../types/ReserveStatus"; @@ -206,7 +211,6 @@ export async function processReserve( }); } - async function registerReserveWithBank( ws: InternalWalletState, reservePub: string, @@ -231,7 +235,6 @@ async function registerReserveWithBank( reserve_pub: reservePub, selected_exchange: reserve.exchangeWire, }); - console.log("got response", bankResp); await ws.db.mutate(Stores.reserves, reservePub, r => { switch (r.reserveStatus) { case ReserveRecordStatus.REGISTERING_BANK: @@ -245,7 +248,7 @@ async function registerReserveWithBank( r.retryInfo = initRetryInfo(); return r; }); - ws.notify( { type: NotificationType.Wildcard }); + ws.notify({ type: NotificationType.Wildcard }); return processReserveBankStatus(ws, reservePub); } @@ -282,14 +285,16 @@ async function processReserveBankStatusImpl( try { const statusResp = await ws.http.get(bankStatusUrl); if (statusResp.status !== 200) { - throw Error(`unexpected status ${statusResp.status} for bank status query`); + throw Error( + `unexpected status ${statusResp.status} for bank status query`, + ); } status = WithdrawOperationStatusResponse.checked(await statusResp.json()); } catch (e) { throw e; } - ws.notify( { type: NotificationType.Wildcard }); + ws.notify({ type: NotificationType.Wildcard }); if (status.selection_done) { if (reserve.reserveStatus === ReserveRecordStatus.REGISTERING_BANK) { @@ -330,7 +335,7 @@ async function processReserveBankStatusImpl( }); await incrementReserveRetry(ws, reservePub, undefined); } - ws.notify( { type: NotificationType.Wildcard }); + ws.notify({ type: NotificationType.Wildcard }); } async function incrementReserveRetry( @@ -351,7 +356,12 @@ async function incrementReserveRetry( r.lastError = err; await tx.put(Stores.reserves, r); }); - ws.notify({ type: NotificationType.ReserveOperationError }); + if (err) { + ws.notify({ + type: NotificationType.ReserveOperationError, + operationError: err, + }); + } } /** @@ -386,7 +396,7 @@ async function updateReserve( return; } if (resp.status !== 200) { - throw Error(`unexpected status code ${resp.status} for reserve/status`) + throw Error(`unexpected status code ${resp.status} for reserve/status`); } } catch (e) { const m = e.message; @@ -400,68 +410,73 @@ async function updateReserve( const respJson = await resp.json(); const reserveInfo = codecForReserveStatus.decode(respJson); const balance = Amounts.parseOrThrow(reserveInfo.balance); - await ws.db.runWithWriteTransaction([Stores.reserves, Stores.reserveUpdatedEvents], async (tx) => { - const r = await tx.get(Stores.reserves, reservePub); - if (!r) { - return; - } - if (r.reserveStatus !== ReserveRecordStatus.QUERYING_STATUS) { - return; - } - - const newHistoryTransactions = reserveInfo.history.slice(r.reserveTransactions.length); - - const reserveUpdateId = encodeCrock(getRandomBytes(32)); - - // FIXME: check / compare history! - if (!r.lastSuccessfulStatusQuery) { - // FIXME: check if this matches initial expectations - r.amountWithdrawRemaining = balance; - const reserveUpdate: ReserveUpdatedEventRecord = { - reservePub: r.reservePub, - timestamp: getTimestampNow(), - amountReserveBalance: Amounts.toString(balance), - amountExpected: Amounts.toString(reserve.amountInitiallyRequested), - newHistoryTransactions, - reserveUpdateId, - }; - await tx.put(Stores.reserveUpdatedEvents, reserveUpdate); - } else { - const expectedBalance = Amounts.sub( - r.amountWithdrawAllocated, - r.amountWithdrawCompleted, - ); - const cmp = Amounts.cmp(balance, expectedBalance.amount); - if (cmp == 0) { - // Nothing changed. + await ws.db.runWithWriteTransaction( + [Stores.reserves, Stores.reserveUpdatedEvents], + async tx => { + const r = await tx.get(Stores.reserves, reservePub); + if (!r) { + return; + } + if (r.reserveStatus !== ReserveRecordStatus.QUERYING_STATUS) { return; } - if (cmp > 0) { - const extra = Amounts.sub(balance, expectedBalance.amount).amount; - r.amountWithdrawRemaining = Amounts.add( - r.amountWithdrawRemaining, - extra, - ).amount; + + const newHistoryTransactions = reserveInfo.history.slice( + r.reserveTransactions.length, + ); + + const reserveUpdateId = encodeCrock(getRandomBytes(32)); + + // FIXME: check / compare history! + if (!r.lastSuccessfulStatusQuery) { + // FIXME: check if this matches initial expectations + r.amountWithdrawRemaining = balance; + const reserveUpdate: ReserveUpdatedEventRecord = { + reservePub: r.reservePub, + timestamp: getTimestampNow(), + amountReserveBalance: Amounts.toString(balance), + amountExpected: Amounts.toString(reserve.amountInitiallyRequested), + newHistoryTransactions, + reserveUpdateId, + }; + await tx.put(Stores.reserveUpdatedEvents, reserveUpdate); } else { - // We're missing some money. + const expectedBalance = Amounts.sub( + r.amountWithdrawAllocated, + r.amountWithdrawCompleted, + ); + const cmp = Amounts.cmp(balance, expectedBalance.amount); + if (cmp == 0) { + // Nothing changed. + return; + } + if (cmp > 0) { + const extra = Amounts.sub(balance, expectedBalance.amount).amount; + r.amountWithdrawRemaining = Amounts.add( + r.amountWithdrawRemaining, + extra, + ).amount; + } else { + // We're missing some money. + } + const reserveUpdate: ReserveUpdatedEventRecord = { + reservePub: r.reservePub, + timestamp: getTimestampNow(), + amountReserveBalance: Amounts.toString(balance), + amountExpected: Amounts.toString(expectedBalance.amount), + newHistoryTransactions, + reserveUpdateId, + }; + await tx.put(Stores.reserveUpdatedEvents, reserveUpdate); } - const reserveUpdate: ReserveUpdatedEventRecord = { - reservePub: r.reservePub, - timestamp: getTimestampNow(), - amountReserveBalance: Amounts.toString(balance), - amountExpected: Amounts.toString(expectedBalance.amount), - newHistoryTransactions, - reserveUpdateId, - }; - await tx.put(Stores.reserveUpdatedEvents, reserveUpdate); - } - r.lastSuccessfulStatusQuery = getTimestampNow(); - r.reserveStatus = ReserveRecordStatus.WITHDRAWING; - r.retryInfo = initRetryInfo(); - r.reserveTransactions = reserveInfo.history; - await tx.put(Stores.reserves, r); - }); - ws.notify( { type: NotificationType.ReserveUpdated }); + r.lastSuccessfulStatusQuery = getTimestampNow(); + r.reserveStatus = ReserveRecordStatus.WITHDRAWING; + r.retryInfo = initRetryInfo(); + r.reserveTransactions = reserveInfo.history; + await tx.put(Stores.reserves, r); + }, + ); + ws.notify({ type: NotificationType.ReserveUpdated }); } async function processReserveImpl( @@ -655,8 +670,6 @@ async function depleteReserve( } } - - export async function createTalerWithdrawReserve( ws: InternalWalletState, talerWithdrawUri: string, @@ -683,4 +696,4 @@ export async function createTalerWithdrawReserve( reservePub: reserve.reservePub, confirmTransferUrl: withdrawInfo.confirmTransferUrl, }; -}
\ No newline at end of file +} |