sunset history API (we have the transaction list now)
This commit is contained in:
parent
d88829cfa8
commit
60891b502a
@ -1,512 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2019 GNUnet e.V.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports.
|
|
||||||
*/
|
|
||||||
import { InternalWalletState } from "./state";
|
|
||||||
import { Stores, ProposalStatus, ProposalRecord } from "../types/dbTypes";
|
|
||||||
import { Amounts } from "../util/amounts";
|
|
||||||
import { AmountJson } from "../util/amounts";
|
|
||||||
import {
|
|
||||||
HistoryQuery,
|
|
||||||
HistoryEvent,
|
|
||||||
HistoryEventType,
|
|
||||||
OrderShortInfo,
|
|
||||||
ReserveType,
|
|
||||||
ReserveCreationDetail,
|
|
||||||
VerbosePayCoinDetails,
|
|
||||||
VerboseRefreshDetails,
|
|
||||||
} from "../types/history";
|
|
||||||
import { assertUnreachable } from "../util/assertUnreachable";
|
|
||||||
import { TransactionHandle } from "../util/query";
|
|
||||||
import { timestampCmp } from "../util/time";
|
|
||||||
import { summarizeReserveHistory } from "../util/reserveHistoryUtil";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an event ID from the type and the primary key for the event.
|
|
||||||
*/
|
|
||||||
function makeEventId(type: HistoryEventType, ...args: string[]): string {
|
|
||||||
return type + ";" + args.map((x) => encodeURIComponent(x)).join(";");
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOrderShortInfo(
|
|
||||||
proposal: ProposalRecord,
|
|
||||||
): OrderShortInfo | undefined {
|
|
||||||
const download = proposal.download;
|
|
||||||
if (!download) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
amount: Amounts.stringify(download.contractData.amount),
|
|
||||||
fulfillmentUrl: download.contractData.fulfillmentUrl,
|
|
||||||
orderId: download.contractData.orderId,
|
|
||||||
merchantBaseUrl: download.contractData.merchantBaseUrl,
|
|
||||||
proposalId: proposal.proposalId,
|
|
||||||
summary: download.contractData.summary,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function collectProposalHistory(
|
|
||||||
tx: TransactionHandle,
|
|
||||||
history: HistoryEvent[],
|
|
||||||
historyQuery?: HistoryQuery,
|
|
||||||
): Promise<void> {
|
|
||||||
tx.iter(Stores.proposals).forEachAsync(async (proposal) => {
|
|
||||||
const status = proposal.proposalStatus;
|
|
||||||
switch (status) {
|
|
||||||
case ProposalStatus.ACCEPTED:
|
|
||||||
{
|
|
||||||
const shortInfo = getOrderShortInfo(proposal);
|
|
||||||
if (!shortInfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.OrderAccepted,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.OrderAccepted,
|
|
||||||
proposal.proposalId,
|
|
||||||
),
|
|
||||||
orderShortInfo: shortInfo,
|
|
||||||
timestamp: proposal.timestamp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ProposalStatus.DOWNLOADING:
|
|
||||||
case ProposalStatus.PROPOSED:
|
|
||||||
// no history event needed
|
|
||||||
break;
|
|
||||||
case ProposalStatus.REFUSED:
|
|
||||||
{
|
|
||||||
const shortInfo = getOrderShortInfo(proposal);
|
|
||||||
if (!shortInfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.OrderRefused,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.OrderRefused,
|
|
||||||
proposal.proposalId,
|
|
||||||
),
|
|
||||||
orderShortInfo: shortInfo,
|
|
||||||
timestamp: proposal.timestamp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ProposalStatus.REPURCHASE:
|
|
||||||
{
|
|
||||||
const alreadyPaidProposal = await tx.get(
|
|
||||||
Stores.proposals,
|
|
||||||
proposal.repurchaseProposalId,
|
|
||||||
);
|
|
||||||
if (!alreadyPaidProposal) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const alreadyPaidOrderShortInfo = getOrderShortInfo(
|
|
||||||
alreadyPaidProposal,
|
|
||||||
);
|
|
||||||
if (!alreadyPaidOrderShortInfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const newOrderShortInfo = getOrderShortInfo(proposal);
|
|
||||||
if (!newOrderShortInfo) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.OrderRedirected,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.OrderRedirected,
|
|
||||||
proposal.proposalId,
|
|
||||||
),
|
|
||||||
alreadyPaidOrderShortInfo,
|
|
||||||
newOrderShortInfo,
|
|
||||||
timestamp: proposal.timestamp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assertUnreachable(status);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrive the full event history for this wallet.
|
|
||||||
*/
|
|
||||||
export async function getHistory(
|
|
||||||
ws: InternalWalletState,
|
|
||||||
historyQuery?: HistoryQuery,
|
|
||||||
): Promise<{ history: HistoryEvent[] }> {
|
|
||||||
const history: HistoryEvent[] = [];
|
|
||||||
|
|
||||||
// FIXME: do pagination instead of generating the full history
|
|
||||||
// We uniquely identify history rows via their timestamp.
|
|
||||||
// This works as timestamps are guaranteed to be monotonically
|
|
||||||
// increasing even
|
|
||||||
|
|
||||||
await ws.db.runWithReadTransaction(
|
|
||||||
[
|
|
||||||
Stores.currencies,
|
|
||||||
Stores.coins,
|
|
||||||
Stores.denominations,
|
|
||||||
Stores.exchanges,
|
|
||||||
Stores.exchangeUpdatedEvents,
|
|
||||||
Stores.proposals,
|
|
||||||
Stores.purchases,
|
|
||||||
Stores.refreshGroups,
|
|
||||||
Stores.reserves,
|
|
||||||
Stores.reserveHistory,
|
|
||||||
Stores.tips,
|
|
||||||
Stores.withdrawalGroups,
|
|
||||||
Stores.payEvents,
|
|
||||||
Stores.planchets,
|
|
||||||
Stores.refundEvents,
|
|
||||||
Stores.reserveUpdatedEvents,
|
|
||||||
Stores.recoupGroups,
|
|
||||||
],
|
|
||||||
async (tx) => {
|
|
||||||
tx.iter(Stores.exchanges).forEach((exchange) => {
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.ExchangeAdded,
|
|
||||||
builtIn: false,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.ExchangeAdded,
|
|
||||||
exchange.baseUrl,
|
|
||||||
),
|
|
||||||
exchangeBaseUrl: exchange.baseUrl,
|
|
||||||
timestamp: exchange.timestampAdded,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.iter(Stores.exchangeUpdatedEvents).forEach((eu) => {
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.ExchangeUpdated,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.ExchangeUpdated,
|
|
||||||
eu.exchangeBaseUrl,
|
|
||||||
),
|
|
||||||
exchangeBaseUrl: eu.exchangeBaseUrl,
|
|
||||||
timestamp: eu.timestamp,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.iter(Stores.withdrawalGroups).forEach((wsr) => {
|
|
||||||
if (wsr.timestampFinish) {
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.Withdrawn,
|
|
||||||
withdrawalGroupId: wsr.withdrawalGroupId,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.Withdrawn,
|
|
||||||
wsr.withdrawalGroupId,
|
|
||||||
),
|
|
||||||
amountWithdrawnEffective: Amounts.stringify(
|
|
||||||
wsr.denomsSel.totalCoinValue,
|
|
||||||
),
|
|
||||||
amountWithdrawnRaw: Amounts.stringify(wsr.rawWithdrawalAmount),
|
|
||||||
exchangeBaseUrl: wsr.exchangeBaseUrl,
|
|
||||||
timestamp: wsr.timestampFinish,
|
|
||||||
withdrawalSource: wsr.source,
|
|
||||||
verboseDetails: undefined,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await collectProposalHistory(tx, history, historyQuery);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
let verboseDetails: VerbosePayCoinDetails | undefined = undefined;
|
|
||||||
if (historyQuery?.extraDebug) {
|
|
||||||
const coins: {
|
|
||||||
value: string;
|
|
||||||
contribution: string;
|
|
||||||
denomPub: string;
|
|
||||||
}[] = [];
|
|
||||||
for (const x of purchase.coinDepositPermissions) {
|
|
||||||
const c = await tx.get(Stores.coins, x.coin_pub);
|
|
||||||
if (!c) {
|
|
||||||
// FIXME: what to do here??
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const d = await tx.get(Stores.denominations, [
|
|
||||||
c.exchangeBaseUrl,
|
|
||||||
c.denomPub,
|
|
||||||
]);
|
|
||||||
if (!d) {
|
|
||||||
// FIXME: what to do here??
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
coins.push({
|
|
||||||
contribution: x.contribution,
|
|
||||||
denomPub: c.denomPub,
|
|
||||||
value: Amounts.stringify(d.value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
verboseDetails = { coins };
|
|
||||||
}
|
|
||||||
const amountPaidWithFees = Amounts.sum(
|
|
||||||
purchase.coinDepositPermissions.map((x) =>
|
|
||||||
Amounts.parseOrThrow(x.contribution),
|
|
||||||
),
|
|
||||||
).amount;
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.PaymentSent,
|
|
||||||
eventId: makeEventId(HistoryEventType.PaymentSent, pe.proposalId),
|
|
||||||
orderShortInfo,
|
|
||||||
replay: pe.isReplay,
|
|
||||||
sessionId: pe.sessionId,
|
|
||||||
timestamp: pe.timestamp,
|
|
||||||
numCoins: purchase.coinDepositPermissions.length,
|
|
||||||
amountPaidWithFees: Amounts.stringify(amountPaidWithFees),
|
|
||||||
verboseDetails,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
await tx.iter(Stores.refreshGroups).forEachAsync(async (rg) => {
|
|
||||||
if (!rg.timestampFinished) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let numInputCoins = 0;
|
|
||||||
let numRefreshedInputCoins = 0;
|
|
||||||
let numOutputCoins = 0;
|
|
||||||
const amountsRaw: AmountJson[] = [];
|
|
||||||
const amountsEffective: AmountJson[] = [];
|
|
||||||
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 {
|
|
||||||
amountsRaw.push(c.currentAmount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const amountRefreshedRaw = Amounts.sum(amountsRaw).amount;
|
|
||||||
let amountRefreshedEffective: AmountJson;
|
|
||||||
if (amountsEffective.length == 0) {
|
|
||||||
amountRefreshedEffective = Amounts.getZero(
|
|
||||||
amountRefreshedRaw.currency,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
amountRefreshedEffective = Amounts.sum(amountsEffective).amount;
|
|
||||||
}
|
|
||||||
let verboseDetails: VerboseRefreshDetails | undefined = undefined;
|
|
||||||
if (historyQuery?.extraDebug) {
|
|
||||||
const outputCoins: {
|
|
||||||
value: string;
|
|
||||||
denomPub: string;
|
|
||||||
}[] = [];
|
|
||||||
for (const rs of rg.refreshSessionPerCoin) {
|
|
||||||
if (!rs) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const nd of rs.newDenoms) {
|
|
||||||
if (!nd) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const d = await tx.get(Stores.denominations, [
|
|
||||||
rs.exchangeBaseUrl,
|
|
||||||
nd,
|
|
||||||
]);
|
|
||||||
if (!d) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
outputCoins.push({
|
|
||||||
denomPub: d.denomPub,
|
|
||||||
value: Amounts.stringify(d.value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
verboseDetails = {
|
|
||||||
outputCoins: outputCoins,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.Refreshed,
|
|
||||||
refreshGroupId: rg.refreshGroupId,
|
|
||||||
eventId: makeEventId(HistoryEventType.Refreshed, rg.refreshGroupId),
|
|
||||||
timestamp: rg.timestampFinished,
|
|
||||||
refreshReason: rg.reason,
|
|
||||||
amountRefreshedEffective: Amounts.stringify(amountRefreshedEffective),
|
|
||||||
amountRefreshedRaw: Amounts.stringify(amountRefreshedRaw),
|
|
||||||
numInputCoins,
|
|
||||||
numOutputCoins,
|
|
||||||
numRefreshedInputCoins,
|
|
||||||
verboseDetails,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.iter(Stores.reserveUpdatedEvents).forEachAsync(async (ru) => {
|
|
||||||
const reserve = await tx.get(Stores.reserves, ru.reservePub);
|
|
||||||
if (!reserve) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let reserveCreationDetail: ReserveCreationDetail;
|
|
||||||
if (reserve.bankInfo) {
|
|
||||||
reserveCreationDetail = {
|
|
||||||
type: ReserveType.TalerBankWithdraw,
|
|
||||||
bankUrl: reserve.bankInfo.statusUrl,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
reserveCreationDetail = {
|
|
||||||
type: ReserveType.Manual,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const hist = await tx.get(Stores.reserveHistory, reserve.reservePub);
|
|
||||||
if (!hist) {
|
|
||||||
throw Error("inconsistent database");
|
|
||||||
}
|
|
||||||
const s = summarizeReserveHistory(
|
|
||||||
hist.reserveTransactions,
|
|
||||||
reserve.currency,
|
|
||||||
);
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.ReserveBalanceUpdated,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.ReserveBalanceUpdated,
|
|
||||||
ru.reserveUpdateId,
|
|
||||||
),
|
|
||||||
timestamp: ru.timestamp,
|
|
||||||
reserveShortInfo: {
|
|
||||||
exchangeBaseUrl: reserve.exchangeBaseUrl,
|
|
||||||
reserveCreationDetail,
|
|
||||||
reservePub: reserve.reservePub,
|
|
||||||
},
|
|
||||||
reserveAwaitedAmount: Amounts.stringify(s.awaitedReserveAmount),
|
|
||||||
reserveBalance: Amounts.stringify(s.computedReserveBalance),
|
|
||||||
reserveUnclaimedAmount: Amounts.stringify(s.unclaimedReserveAmount),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
tx.iter(Stores.tips).forEach((tip) => {
|
|
||||||
if (tip.acceptedTimestamp) {
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.TipAccepted,
|
|
||||||
eventId: makeEventId(HistoryEventType.TipAccepted, tip.tipId),
|
|
||||||
timestamp: tip.acceptedTimestamp,
|
|
||||||
tipId: tip.tipId,
|
|
||||||
tipAmountRaw: Amounts.stringify(tip.amount),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// tx.iter(Stores.refundEvents).forEachAsync(async (re) => {
|
|
||||||
// const proposal = await tx.get(Stores.proposals, re.proposalId);
|
|
||||||
// if (!proposal) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// const purchase = await tx.get(Stores.purchases, re.proposalId);
|
|
||||||
// if (!purchase) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// const orderShortInfo = getOrderShortInfo(proposal);
|
|
||||||
// if (!orderShortInfo) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// const purchaseAmount = purchase.contractData.amount;
|
|
||||||
// let amountRefundedRaw = Amounts.getZero(purchaseAmount.currency);
|
|
||||||
// let amountRefundedInvalid = Amounts.getZero(purchaseAmount.currency);
|
|
||||||
// let amountRefundedEffective = Amounts.getZero(purchaseAmount.currency);
|
|
||||||
// Object.keys(purchase.refundsDone).forEach((x, i) => {
|
|
||||||
// const r = purchase.refundsDone[x];
|
|
||||||
// if (r.refundGroupId !== re.refundGroupId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// 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;
|
|
||||||
// });
|
|
||||||
// Object.keys(purchase.refundsFailed).forEach((x, i) => {
|
|
||||||
// const r = purchase.refundsFailed[x];
|
|
||||||
// if (r.refundGroupId !== re.refundGroupId) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// const ra = Amounts.parseOrThrow(r.perm.refund_amount);
|
|
||||||
// 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;
|
|
||||||
// });
|
|
||||||
// history.push({
|
|
||||||
// type: HistoryEventType.Refund,
|
|
||||||
// eventId: makeEventId(HistoryEventType.Refund, re.refundGroupId),
|
|
||||||
// refundGroupId: re.refundGroupId,
|
|
||||||
// orderShortInfo,
|
|
||||||
// timestamp: re.timestamp,
|
|
||||||
// amountRefundedEffective: Amounts.stringify(amountRefundedEffective),
|
|
||||||
// amountRefundedRaw: Amounts.stringify(amountRefundedRaw),
|
|
||||||
// amountRefundedInvalid: Amounts.stringify(amountRefundedInvalid),
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
|
|
||||||
tx.iter(Stores.recoupGroups).forEach((rg) => {
|
|
||||||
if (rg.timestampFinished) {
|
|
||||||
let verboseDetails: any = undefined;
|
|
||||||
if (historyQuery?.extraDebug) {
|
|
||||||
verboseDetails = {
|
|
||||||
oldAmountPerCoin: rg.oldAmountPerCoin.map(Amounts.stringify),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
history.push({
|
|
||||||
type: HistoryEventType.FundsRecouped,
|
|
||||||
timestamp: rg.timestampFinished,
|
|
||||||
eventId: makeEventId(
|
|
||||||
HistoryEventType.FundsRecouped,
|
|
||||||
rg.recoupGroupId,
|
|
||||||
),
|
|
||||||
numCoinsRecouped: rg.coinPubs.length,
|
|
||||||
verboseDetails,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
history.sort((h1, h2) => timestampCmp(h1.timestamp, h2.timestamp));
|
|
||||||
|
|
||||||
return { history };
|
|
||||||
}
|
|
@ -1,698 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of GNU Taler
|
|
||||||
(C) 2019 Taler Systems S.A.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
|
||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type and schema definitions for the wallet's history.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports.
|
|
||||||
*/
|
|
||||||
import { RefreshReason } from "./walletTypes";
|
|
||||||
import { WithdrawalSource } from "./dbTypes";
|
|
||||||
import { Timestamp } from "../util/time";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Type tags for the history event types.
|
|
||||||
*/
|
|
||||||
export const enum HistoryEventType {
|
|
||||||
AuditorComplaintSent = "auditor-complained-sent",
|
|
||||||
AuditorComplaintProcessed = "auditor-complaint-processed",
|
|
||||||
AuditorTrustAdded = "auditor-trust-added",
|
|
||||||
AuditorTrustRemoved = "auditor-trust-removed",
|
|
||||||
ExchangeAdded = "exchange-added",
|
|
||||||
ExchangeTermsAccepted = "exchange-terms-accepted",
|
|
||||||
ExchangePolicyChanged = "exchange-policy-changed",
|
|
||||||
ExchangeTrustAdded = "exchange-trust-added",
|
|
||||||
ExchangeTrustRemoved = "exchange-trust-removed",
|
|
||||||
ExchangeUpdated = "exchange-updated",
|
|
||||||
FundsDepositedToSelf = "funds-deposited-to-self",
|
|
||||||
FundsRecouped = "funds-recouped",
|
|
||||||
OrderAccepted = "order-accepted",
|
|
||||||
OrderRedirected = "order-redirected",
|
|
||||||
OrderRefused = "order-refused",
|
|
||||||
PaymentAborted = "payment-aborted",
|
|
||||||
PaymentSent = "payment-sent",
|
|
||||||
Refreshed = "refreshed",
|
|
||||||
Refund = "refund",
|
|
||||||
ReserveBalanceUpdated = "reserve-balance-updated",
|
|
||||||
ReserveCreated = "reserve-created",
|
|
||||||
TipAccepted = "tip-accepted",
|
|
||||||
TipDeclined = "tip-declined",
|
|
||||||
Withdrawn = "withdrawn",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const enum ReserveType {
|
|
||||||
/**
|
|
||||||
* Manually created.
|
|
||||||
*/
|
|
||||||
Manual = "manual",
|
|
||||||
/**
|
|
||||||
* Withdrawn from a bank that has "tight" Taler integration
|
|
||||||
*/
|
|
||||||
TalerBankWithdraw = "taler-bank-withdraw",
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Short info about a reserve. Enough to display in a list view and
|
|
||||||
* to query more information from the wallet.
|
|
||||||
*/
|
|
||||||
export interface ReserveShortInfo {
|
|
||||||
/**
|
|
||||||
* The exchange that the reserve will be at.
|
|
||||||
*/
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Key to query more details
|
|
||||||
*/
|
|
||||||
reservePub: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detail about how the reserve has been created.
|
|
||||||
*/
|
|
||||||
reserveCreationDetail: ReserveCreationDetail;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ReserveCreationDetail =
|
|
||||||
| { type: ReserveType.Manual }
|
|
||||||
| { type: ReserveType.TalerBankWithdraw; bankUrl: string };
|
|
||||||
|
|
||||||
export interface HistoryReserveCreatedEvent {
|
|
||||||
type: HistoryEventType.ReserveCreated;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that the should appear in the reserve once its status
|
|
||||||
* is requested from the exchange.
|
|
||||||
*/
|
|
||||||
expectedAmount: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed information about the reserve.
|
|
||||||
*/
|
|
||||||
reserveShortInfo: ReserveShortInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This event is emitted every time we ask the exchange for the status
|
|
||||||
* of the reserve, and the status has changed.
|
|
||||||
*/
|
|
||||||
export interface HistoryReserveBalanceUpdatedEvent {
|
|
||||||
type: HistoryEventType.ReserveBalanceUpdated;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Point in time when the reserve was confirmed.
|
|
||||||
*/
|
|
||||||
timestamp: Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed information about the reserve.
|
|
||||||
*/
|
|
||||||
reserveShortInfo: ReserveShortInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount currently left in the reserve.
|
|
||||||
*/
|
|
||||||
reserveBalance: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount we still expect to be added to the reserve.
|
|
||||||
*/
|
|
||||||
reserveAwaitedAmount: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that hasn't been withdrawn yet.
|
|
||||||
*/
|
|
||||||
reserveUnclaimedAmount: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that the user has accepted a tip.
|
|
||||||
*/
|
|
||||||
export interface HistoryTipAcceptedEvent {
|
|
||||||
type: HistoryEventType.TipAccepted;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Point in time when the tip has been accepted.
|
|
||||||
*/
|
|
||||||
timestamp: Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique identifier for the tip to query more information.
|
|
||||||
*/
|
|
||||||
tipId: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Raw amount of the tip, without extra fees that apply.
|
|
||||||
*/
|
|
||||||
tipAmountRaw: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that the user has accepted a tip.
|
|
||||||
*/
|
|
||||||
export interface HistoryTipDeclinedEvent {
|
|
||||||
type: HistoryEventType.TipDeclined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Point in time when the tip has been declined.
|
|
||||||
*/
|
|
||||||
timestamp: Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique identifier for the tip to query more information.
|
|
||||||
*/
|
|
||||||
tipId: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Raw amount of the tip, without extra fees that apply.
|
|
||||||
*/
|
|
||||||
tipAmountRaw: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The wallet has send a complaint (typically with cryptographic evidence of
|
|
||||||
* something having gone wrong) to the auditor.
|
|
||||||
*/
|
|
||||||
export interface HistoryAuditorComplaintSentEvent {
|
|
||||||
type: HistoryEventType.AuditorComplaintSent;
|
|
||||||
|
|
||||||
auditorComplaintId: string;
|
|
||||||
|
|
||||||
/* FIXME: add fields once this feature is implemented */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The wallet has received a response from the auditor to a complaint.
|
|
||||||
*/
|
|
||||||
export interface HistoryAuditorComplaintProcessedEvent {
|
|
||||||
type: HistoryEventType.AuditorComplaintProcessed;
|
|
||||||
|
|
||||||
auditorComplaintId: string;
|
|
||||||
|
|
||||||
/* FIXME: add fields once this feature is implemented */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The wallet has added an auditor as a trusted auditor.
|
|
||||||
*/
|
|
||||||
export interface HistoryAuditorTrustAddedEvent {
|
|
||||||
type: HistoryEventType.AuditorTrustAdded;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base URL of the auditor.
|
|
||||||
*/
|
|
||||||
auditorBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If set to true, this auditor hasn't been added by the user,
|
|
||||||
* but is part of the pre-set trusted auditors in the wallet.
|
|
||||||
*/
|
|
||||||
builtIn: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The wallet has added an auditor as a trusted auditor.
|
|
||||||
*/
|
|
||||||
export interface HistoryAuditorTrustRemovedEvent {
|
|
||||||
type: HistoryEventType.AuditorTrustRemoved;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base URL of the auditor.
|
|
||||||
*/
|
|
||||||
auditorBaseUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An exchange has been added to the wallet. The wallet only
|
|
||||||
* downloads information about the exchange, but does not necessarily
|
|
||||||
* trust it yet.
|
|
||||||
*/
|
|
||||||
export interface HistoryExchangeAddedEvent {
|
|
||||||
type: HistoryEventType.ExchangeAdded;
|
|
||||||
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to true if the exchange was pre-configured
|
|
||||||
* by the wallet.
|
|
||||||
*/
|
|
||||||
builtIn: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that the wallet now trusts
|
|
||||||
* an exchange.
|
|
||||||
*/
|
|
||||||
export interface HistoryExchangeTrustAddedEvent {
|
|
||||||
type: HistoryEventType.ExchangeTrustAdded;
|
|
||||||
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to true if the exchange was pre-configured
|
|
||||||
* by the wallet.
|
|
||||||
*/
|
|
||||||
builtIn: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that the wallet doesn't trust
|
|
||||||
* an exchange anymore.
|
|
||||||
*/
|
|
||||||
export interface HistoryExchangeTrustRemovedEvent {
|
|
||||||
type: HistoryEventType.ExchangeTrustRemoved;
|
|
||||||
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This event indicates that the user accepted the terms of service
|
|
||||||
* of the exchange.
|
|
||||||
*/
|
|
||||||
export interface HistoryExchangeTermsAcceptedEvent {
|
|
||||||
type: HistoryEventType.ExchangeTermsAccepted;
|
|
||||||
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Etag that the exchange sent with the terms of service.
|
|
||||||
* Identifies the version of the terms of service.
|
|
||||||
*/
|
|
||||||
termsEtag: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The exchange has changed the terms of service or privacy
|
|
||||||
* policy.
|
|
||||||
*/
|
|
||||||
export interface HistoryExchangePolicyChangedEvent {
|
|
||||||
type: HistoryEventType.ExchangePolicyChanged;
|
|
||||||
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Etag that the exchange sent with the terms of service.
|
|
||||||
* Identifies the version of the terms of service.
|
|
||||||
*/
|
|
||||||
termsEtag: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Etag that the exchange sent with the privacy policy.
|
|
||||||
* Identifies the version of the privacy policy.
|
|
||||||
*/
|
|
||||||
privacyPolicyEtag: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This history event indicates that the exchange has updated
|
|
||||||
* the /keys or /wire information. The event is only emitted if
|
|
||||||
* this information changed since the last time the wallet checked it.
|
|
||||||
*/
|
|
||||||
export interface HistoryExchangeUpdatedEvent {
|
|
||||||
type: HistoryEventType.ExchangeUpdated;
|
|
||||||
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that the user sent back digital cash from
|
|
||||||
* their wallet back to their own bank account (basically acting as a merchant).
|
|
||||||
*/
|
|
||||||
export interface HistoryFundsDepositedToSelfEvent {
|
|
||||||
type: HistoryEventType.FundsDepositedToSelf;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that got sent back.
|
|
||||||
*/
|
|
||||||
amount: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Account that received the funds.
|
|
||||||
*/
|
|
||||||
receiverPaytoUri: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that the exchange marked
|
|
||||||
* some denominations as "compromised", and the wallet has
|
|
||||||
* converted funds in these denominations to new funds.
|
|
||||||
*/
|
|
||||||
export interface HistoryFundsRecoupedEvent {
|
|
||||||
type: HistoryEventType.FundsRecouped;
|
|
||||||
numCoinsRecouped: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed information about an order, enough to display in a list view
|
|
||||||
* and to query more details from the wallet for a detail view.
|
|
||||||
*/
|
|
||||||
export interface OrderShortInfo {
|
|
||||||
/**
|
|
||||||
* Wallet-internal identifier of the proposal.
|
|
||||||
*/
|
|
||||||
proposalId: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Order ID, uniquely identifies the order within a merchant instance.
|
|
||||||
*/
|
|
||||||
orderId: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base URL of the merchant.
|
|
||||||
*/
|
|
||||||
merchantBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that must be paid for the contract.
|
|
||||||
*/
|
|
||||||
amount: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary of the proposal, given by the merchant.
|
|
||||||
*/
|
|
||||||
summary: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* URL of the fulfillment, given by the merchant.
|
|
||||||
*/
|
|
||||||
fulfillmentUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user has accepted purchasing something.
|
|
||||||
*/
|
|
||||||
export interface HistoryOrderAcceptedEvent {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.OrderAccepted;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed info about the order.
|
|
||||||
*/
|
|
||||||
orderShortInfo: OrderShortInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The customer refused to pay.
|
|
||||||
*/
|
|
||||||
export interface HistoryOrderRefusedEvent {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.OrderRefused;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed info about the order.
|
|
||||||
*/
|
|
||||||
orderShortInfo: OrderShortInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The wallet has claimed an order.
|
|
||||||
*/
|
|
||||||
export interface HistoryOrderRedirectedEvent {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.OrderRedirected;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed info about the new order that contains a
|
|
||||||
* product (identified by the fulfillment URL) that we've already paid for.
|
|
||||||
*/
|
|
||||||
newOrderShortInfo: OrderShortInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed info about the order that we already paid for.
|
|
||||||
*/
|
|
||||||
alreadyPaidOrderShortInfo: OrderShortInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The user aborted a pending, partially submitted payment.
|
|
||||||
*/
|
|
||||||
export interface HistoryPaymentAbortedEvent {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.PaymentAborted;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed info about the order that we already paid for.
|
|
||||||
*/
|
|
||||||
orderShortInfo: OrderShortInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that was lost due to refund and refreshing fees.
|
|
||||||
*/
|
|
||||||
amountLost: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VerbosePayCoinDetails {
|
|
||||||
coins: {
|
|
||||||
value: string;
|
|
||||||
contribution: string;
|
|
||||||
denomPub: string;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* History event to indicate that a payment has been (re-)submitted
|
|
||||||
* to the merchant.
|
|
||||||
*/
|
|
||||||
export interface HistoryPaymentSent {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.PaymentSent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Condensed info about the order that we already paid for.
|
|
||||||
*/
|
|
||||||
orderShortInfo: OrderShortInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to true if the payment has been previously sent
|
|
||||||
* to the merchant successfully, possibly with a different session ID.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
sessionId: string | undefined;
|
|
||||||
|
|
||||||
verboseDetails?: VerbosePayCoinDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A refund has been applied.
|
|
||||||
*/
|
|
||||||
export interface HistoryRefunded {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.Refund;
|
|
||||||
|
|
||||||
timestamp: Timestamp;
|
|
||||||
|
|
||||||
orderShortInfo: OrderShortInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique identifier for this refund.
|
|
||||||
* (Identifies multiple refund permissions that were obtained at once.)
|
|
||||||
*/
|
|
||||||
refundGroupId: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Part of the refund that couldn't be applied because
|
|
||||||
* the refund permissions were expired.
|
|
||||||
*/
|
|
||||||
amountRefundedInvalid: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that has been refunded by the merchant.
|
|
||||||
*/
|
|
||||||
amountRefundedRaw: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount will be added to the wallet's balance after fees and refreshing.
|
|
||||||
*/
|
|
||||||
amountRefundedEffective: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VerboseRefreshDetails {
|
|
||||||
outputCoins: {
|
|
||||||
denomPub: string;
|
|
||||||
value: string;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Event to indicate that a group of refresh sessions has completed.
|
|
||||||
*/
|
|
||||||
export interface HistoryRefreshedEvent {
|
|
||||||
/**
|
|
||||||
* Type tag.
|
|
||||||
*/
|
|
||||||
type: HistoryEventType.Refreshed;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that is now available again because it has
|
|
||||||
* been refreshed.
|
|
||||||
*/
|
|
||||||
amountRefreshedEffective: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that we spent for refreshing.
|
|
||||||
*/
|
|
||||||
amountRefreshedRaw: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Why was the refreshing done?
|
|
||||||
*/
|
|
||||||
refreshReason: RefreshReason;
|
|
||||||
|
|
||||||
numInputCoins: number;
|
|
||||||
numRefreshedInputCoins: number;
|
|
||||||
numOutputCoins: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Identifier for a refresh group, contains one or
|
|
||||||
* more refresh session IDs.
|
|
||||||
*/
|
|
||||||
refreshGroupId: string;
|
|
||||||
|
|
||||||
verboseDetails?: VerboseRefreshDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface VerboseWithdrawDetails {
|
|
||||||
coins: {
|
|
||||||
value: string;
|
|
||||||
denomPub: string;
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A withdrawal has completed.
|
|
||||||
*/
|
|
||||||
export interface HistoryWithdrawnEvent {
|
|
||||||
type: HistoryEventType.Withdrawn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exchange that was withdrawn from.
|
|
||||||
*/
|
|
||||||
exchangeBaseUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique identifier for the withdrawal session, can be used to
|
|
||||||
* query more detailed information from the wallet.
|
|
||||||
*/
|
|
||||||
withdrawalGroupId: string;
|
|
||||||
|
|
||||||
withdrawalSource: WithdrawalSource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that has been subtracted from the reserve's balance
|
|
||||||
* for this withdrawal.
|
|
||||||
*/
|
|
||||||
amountWithdrawnRaw: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Amount that actually was added to the wallet's balance.
|
|
||||||
*/
|
|
||||||
amountWithdrawnEffective: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verbose details of the operations, only generated when requested.
|
|
||||||
*/
|
|
||||||
verboseDetails?: VerboseWithdrawDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common fields that all history events need to have.
|
|
||||||
*/
|
|
||||||
export interface HistoryEventBase {
|
|
||||||
type: HistoryEventType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main timestamp of the history event.
|
|
||||||
*/
|
|
||||||
timestamp: Timestamp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opaque unique ID for the event, used as a starting point
|
|
||||||
* for paginating history queries and for invoking actions
|
|
||||||
* on the event (e.g. hiding it from the history).
|
|
||||||
*/
|
|
||||||
eventId: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extra details for debugging.
|
|
||||||
*/
|
|
||||||
verboseDetails?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Union of all history detail types, discriminated by their type.
|
|
||||||
*/
|
|
||||||
export type HistoryEvent = HistoryEventBase &
|
|
||||||
(
|
|
||||||
| HistoryAuditorComplaintSentEvent
|
|
||||||
| HistoryAuditorComplaintProcessedEvent
|
|
||||||
| HistoryAuditorTrustAddedEvent
|
|
||||||
| HistoryAuditorTrustRemovedEvent
|
|
||||||
| HistoryExchangeAddedEvent
|
|
||||||
| HistoryExchangeTermsAcceptedEvent
|
|
||||||
| HistoryExchangePolicyChangedEvent
|
|
||||||
| HistoryExchangeTrustAddedEvent
|
|
||||||
| HistoryExchangeTrustRemovedEvent
|
|
||||||
| HistoryExchangeUpdatedEvent
|
|
||||||
| HistoryFundsDepositedToSelfEvent
|
|
||||||
| HistoryFundsRecoupedEvent
|
|
||||||
| HistoryOrderAcceptedEvent
|
|
||||||
| HistoryOrderRedirectedEvent
|
|
||||||
| HistoryOrderRefusedEvent
|
|
||||||
| HistoryPaymentAbortedEvent
|
|
||||||
| HistoryPaymentSent
|
|
||||||
| HistoryRefreshedEvent
|
|
||||||
| HistoryRefunded
|
|
||||||
| HistoryReserveBalanceUpdatedEvent
|
|
||||||
| HistoryReserveCreatedEvent
|
|
||||||
| HistoryTipAcceptedEvent
|
|
||||||
| HistoryTipDeclinedEvent
|
|
||||||
| HistoryWithdrawnEvent
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface HistoryQuery {
|
|
||||||
/**
|
|
||||||
* Output extra verbose details, intended for debugging
|
|
||||||
* and not for end users.
|
|
||||||
*/
|
|
||||||
extraDebug?: boolean;
|
|
||||||
}
|
|
@ -93,7 +93,6 @@ import { InternalWalletState } from "./operations/state";
|
|||||||
import { createReserve } from "./operations/reserves";
|
import { createReserve } from "./operations/reserves";
|
||||||
import { processRefreshGroup, createRefreshGroup } from "./operations/refresh";
|
import { processRefreshGroup, createRefreshGroup } from "./operations/refresh";
|
||||||
import { processWithdrawGroup } from "./operations/withdraw";
|
import { processWithdrawGroup } from "./operations/withdraw";
|
||||||
import { getHistory } from "./operations/history";
|
|
||||||
import { getPendingOperations } from "./operations/pending";
|
import { getPendingOperations } from "./operations/pending";
|
||||||
import { getBalances } from "./operations/balance";
|
import { getBalances } from "./operations/balance";
|
||||||
import { acceptTip, getTipStatus, processTip } from "./operations/tip";
|
import { acceptTip, getTipStatus, processTip } from "./operations/tip";
|
||||||
@ -106,7 +105,6 @@ import {
|
|||||||
PendingOperationType,
|
PendingOperationType,
|
||||||
} from "./types/pending";
|
} from "./types/pending";
|
||||||
import { WalletNotification, NotificationType } from "./types/notifications";
|
import { WalletNotification, NotificationType } from "./types/notifications";
|
||||||
import { HistoryQuery, HistoryEvent } from "./types/history";
|
|
||||||
import { processPurchaseQueryRefund, applyRefund } from "./operations/refund";
|
import { processPurchaseQueryRefund, applyRefund } from "./operations/refund";
|
||||||
import { durationMin, Duration } from "./util/time";
|
import { durationMin, Duration } from "./util/time";
|
||||||
import { processRecoupGroup } from "./operations/recoup";
|
import { processRecoupGroup } from "./operations/recoup";
|
||||||
@ -558,9 +556,9 @@ export class Wallet {
|
|||||||
* Retrive the full event history for this wallet.
|
* Retrive the full event history for this wallet.
|
||||||
*/
|
*/
|
||||||
async getHistory(
|
async getHistory(
|
||||||
historyQuery?: HistoryQuery,
|
historyQuery?: any[],
|
||||||
): Promise<{ history: HistoryEvent[] }> {
|
): Promise<{ history: any[] }> {
|
||||||
return getHistory(this.ws, historyQuery);
|
return { history: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPendingOperations({ onlyDue = false } = {}): Promise<
|
async getPendingOperations({ onlyDue = false } = {}): Promise<
|
||||||
|
Loading…
Reference in New Issue
Block a user