finish refresh correctly, display fees correctly
This commit is contained in:
parent
c2ee8fd9ab
commit
fb6508de9d
@ -1,17 +1,17 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
(C) 2019 GNUnet e.V.
|
||||
This file is part of GNU Taler
|
||||
(C) 2019 Taler Systems S.A.
|
||||
|
||||
TALER is free software; you can redistribute it and/or modify it under the
|
||||
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 3, or (at your option) any later version.
|
||||
|
||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import os = require("os");
|
||||
@ -167,7 +167,10 @@ walletCli
|
||||
});
|
||||
|
||||
walletCli
|
||||
.subcommand("", "history", { help: "Show wallet event history." })
|
||||
.subcommand("history", "history", { help: "Show wallet event history." })
|
||||
.flag("json", ["--json"], {
|
||||
default: false,
|
||||
})
|
||||
.maybeOption("from", ["--from"], clk.STRING)
|
||||
.maybeOption("to", ["--to"], clk.STRING)
|
||||
.maybeOption("limit", ["--limit"], clk.STRING)
|
||||
@ -175,7 +178,17 @@ walletCli
|
||||
.action(async args => {
|
||||
await withWallet(args, async wallet => {
|
||||
const history = await wallet.getHistory();
|
||||
console.log(JSON.stringify(history, undefined, 2));
|
||||
if (args.history.json) {
|
||||
console.log(JSON.stringify(history, undefined, 2));
|
||||
} else {
|
||||
for (const h of history.history) {
|
||||
console.log(
|
||||
`event at ${new Date(h.timestamp.t_ms).toISOString()} with type ${h.type}:`,
|
||||
);
|
||||
console.log(JSON.stringify(h, undefined, 2));
|
||||
console.log();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -231,7 +244,8 @@ walletCli
|
||||
case TalerUriType.TalerWithdraw:
|
||||
{
|
||||
const withdrawInfo = await wallet.getWithdrawDetailsForUri(uri);
|
||||
const selectedExchange = withdrawInfo.bankWithdrawDetails.suggestedExchange;
|
||||
const selectedExchange =
|
||||
withdrawInfo.bankWithdrawDetails.suggestedExchange;
|
||||
if (!selectedExchange) {
|
||||
console.error("no suggested exchange!");
|
||||
process.exit(1);
|
||||
|
@ -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,
|
||||
|
@ -224,6 +224,8 @@ async function gatherRefreshPending(
|
||||
type: PendingOperationType.Refresh,
|
||||
givesLifeness: true,
|
||||
refreshGroupId: r.refreshGroupId,
|
||||
finishedPerCoin: r.finishedPerCoin,
|
||||
retryInfo: r.retryInfo,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 (cmp > 0) {
|
||||
const extra = Amounts.sub(balance, expectedBalance.amount).amount;
|
||||
r.amountWithdrawRemaining = Amounts.add(
|
||||
r.amountWithdrawRemaining,
|
||||
extra,
|
||||
).amount;
|
||||
} else {
|
||||
// We're missing some money.
|
||||
if (r.reserveStatus !== ReserveRecordStatus.QUERYING_STATUS) {
|
||||
return;
|
||||
}
|
||||
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 });
|
||||
|
||||
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.
|
||||
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);
|
||||
}
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -485,6 +485,16 @@ export interface HistoryPaymentSent {
|
||||
*/
|
||||
replay: boolean;
|
||||
|
||||
/**
|
||||
* Number of coins that were involved in the payment.
|
||||
*/
|
||||
numCoins: number;
|
||||
|
||||
/**
|
||||
* Amount that was paid, including deposit and wire fees.
|
||||
*/
|
||||
amountPaidWithFees: string;
|
||||
|
||||
/**
|
||||
* Session ID that the payment was (re-)submitted under.
|
||||
*/
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { OperationError } from "./walletTypes";
|
||||
|
||||
/*
|
||||
This file is part of GNU Taler
|
||||
(C) 2019 GNUnet e.V.
|
||||
@ -29,7 +31,7 @@ export const enum NotificationType {
|
||||
RefreshRevealed = "refresh-revealed",
|
||||
RefreshMelted = "refresh-melted",
|
||||
RefreshStarted = "refresh-started",
|
||||
RefreshRefused = "refresh-refused",
|
||||
RefreshUnwarranted = "refresh-unwarranted",
|
||||
ReserveUpdated = "reserve-updated",
|
||||
ReserveConfirmed = "reserve-confirmed",
|
||||
ReserveDepleted = "reserve-depleted",
|
||||
@ -100,7 +102,7 @@ export interface RefreshStartedNotification {
|
||||
}
|
||||
|
||||
export interface RefreshRefusedNotification {
|
||||
type: NotificationType.RefreshRefused;
|
||||
type: NotificationType.RefreshUnwarranted;
|
||||
}
|
||||
|
||||
export interface ReserveUpdatedNotification {
|
||||
@ -170,6 +172,7 @@ export interface WithdrawOperationErrorNotification {
|
||||
|
||||
export interface ReserveOperationErrorNotification {
|
||||
type: NotificationType.ReserveOperationError;
|
||||
operationError: OperationError;
|
||||
}
|
||||
|
||||
export interface ReserveCreatedNotification {
|
||||
|
@ -87,6 +87,8 @@ export interface PendingRefreshOperation {
|
||||
type: PendingOperationType.Refresh;
|
||||
lastError?: OperationError;
|
||||
refreshGroupId: string;
|
||||
finishedPerCoin: boolean[];
|
||||
retryInfo: RetryInfo;
|
||||
}
|
||||
|
||||
export interface PendingProposalDownloadOperation {
|
||||
|
Loading…
Reference in New Issue
Block a user