diff --git a/src/android/index.ts b/src/android/index.ts
index dcdb9d756..300cffd12 100644
--- a/src/android/index.ts
+++ b/src/android/index.ts
@@ -31,6 +31,8 @@ import { HttpRequestLibrary, HttpResponse } from "../util/http";
// @ts-ignore: special built-in module
//import akono = require("akono");
+export { handleWorkerError, handleWorkerMessage } from "../crypto/workers/nodeThreadWorker";
+
export class AndroidHttpLib implements HttpRequestLibrary {
useNfcTunnel: boolean = false;
diff --git a/src/dbTypes.ts b/src/dbTypes.ts
index e39d73672..3625740e2 100644
--- a/src/dbTypes.ts
+++ b/src/dbTypes.ts
@@ -1003,10 +1003,7 @@ export interface PurchaseRecord {
*/
merchantSig: string;
- /**
- * A successful payment has been made.
- */
- payFinished: boolean;
+ firstSuccessfulPayTimestamp: Timestamp | undefined;
/**
* Pending refunds for the purchase.
diff --git a/src/headless/helpers.ts b/src/headless/helpers.ts
index cfc7e3695..c4c84d44b 100644
--- a/src/headless/helpers.ts
+++ b/src/headless/helpers.ts
@@ -32,7 +32,8 @@ import { Bank } from "./bank";
import fs = require("fs");
import { Logger } from "../util/logging";
import { NodeThreadCryptoWorkerFactory } from "../crypto/workers/nodeThreadWorker";
-import { NotificationType } from "../walletTypes";
+import { NotificationType, WalletNotification } from "../walletTypes";
+import { SynchronousCryptoWorkerFactory } from "../crypto/workers/synchronousWorker";
const logger = new Logger("helpers.ts");
@@ -87,7 +88,7 @@ export interface DefaultNodeWalletArgs {
/**
* Handler for asynchronous notifications from the wallet.
*/
- notifyHandler?: (reason: string) => void;
+ notifyHandler?: (n: WalletNotification) => void;
/**
* If specified, use this as HTTP request library instead
@@ -163,11 +164,15 @@ export async function getDefaultNodeWallet(
const worker = new NodeThreadCryptoWorkerFactory();
- return new Wallet(
+ const w = new Wallet(
myDb,
myHttpLib,
worker,
);
+ if (args.notifyHandler) {
+ w.addNotificationListener(args.notifyHandler);
+ }
+ return w;
}
export async function withdrawTestBalance(
diff --git a/src/wallet-impl/balance.ts b/src/wallet-impl/balance.ts
index 082e62563..8ce91a173 100644
--- a/src/wallet-impl/balance.ts
+++ b/src/wallet-impl/balance.ts
@@ -138,7 +138,7 @@ export async function getBalances(
});
await tx.iter(Stores.purchases).forEach(t => {
- if (t.payFinished) {
+ if (t.firstSuccessfulPayTimestamp) {
return;
}
for (const c of t.payReq.coins) {
diff --git a/src/wallet-impl/history.ts b/src/wallet-impl/history.ts
index 23887e895..99e51c8de 100644
--- a/src/wallet-impl/history.ts
+++ b/src/wallet-impl/history.ts
@@ -14,11 +14,11 @@
GNU Taler; see the file COPYING. If not, see
*/
- /**
- * Imports.
- */
+/**
+ * Imports.
+ */
import { HistoryQuery, HistoryEvent } from "../walletTypes";
-import { oneShotIter } from "../util/query";
+import { oneShotIter, runWithReadTransaction } from "../util/query";
import { InternalWalletState } from "./state";
import { Stores, TipRecord } from "../dbTypes";
import * as Amounts from "../util/amounts";
@@ -34,139 +34,186 @@ export async function getHistory(
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
- /*
- const proposals = await oneShotIter(ws.db, Stores.proposals).toArray();
- for (const p of proposals) {
- history.push({
- detail: {
- contractTermsHash: p.contractTermsHash,
- merchantName: p.contractTerms.merchant.name,
- },
- timestamp: p.timestamp,
- type: "claim-order",
- explicit: false,
- });
- }
- */
-
- const withdrawals = await oneShotIter(
+ await runWithReadTransaction(
ws.db,
- Stores.withdrawalSession,
- ).toArray();
- for (const w of withdrawals) {
- history.push({
- detail: {
- withdrawalAmount: w.rawWithdrawalAmount,
- },
- timestamp: w.startTimestamp,
- type: "withdraw",
- explicit: false,
- });
- }
-
- const purchases = await oneShotIter(ws.db, Stores.purchases).toArray();
- for (const p of purchases) {
- history.push({
- detail: {
- amount: p.contractTerms.amount,
- contractTermsHash: p.contractTermsHash,
- fulfillmentUrl: p.contractTerms.fulfillment_url,
- merchantName: p.contractTerms.merchant.name,
- },
- timestamp: p.acceptTimestamp,
- type: "pay",
- explicit: false,
- });
- if (p.lastRefundStatusTimestamp) {
- const contractAmount = Amounts.parseOrThrow(p.contractTerms.amount);
- const amountsPending = Object.keys(p.refundsPending).map(x =>
- Amounts.parseOrThrow(p.refundsPending[x].refund_amount),
- );
- const amountsDone = Object.keys(p.refundsDone).map(x =>
- Amounts.parseOrThrow(p.refundsDone[x].refund_amount),
- );
- const amounts: AmountJson[] = amountsPending.concat(amountsDone);
- const amount = Amounts.add(
- Amounts.getZero(contractAmount.currency),
- ...amounts,
- ).amount;
-
- history.push({
- detail: {
- contractTermsHash: p.contractTermsHash,
- fulfillmentUrl: p.contractTerms.fulfillment_url,
- merchantName: p.contractTerms.merchant.name,
- refundAmount: amount,
- },
- timestamp: p.lastRefundStatusTimestamp,
- type: "refund",
- explicit: false,
+ [
+ Stores.currencies,
+ Stores.coins,
+ Stores.denominations,
+ Stores.exchanges,
+ Stores.proposals,
+ Stores.purchases,
+ Stores.refresh,
+ Stores.reserves,
+ Stores.tips,
+ Stores.withdrawalSession,
+ ],
+ async tx => {
+ await tx.iter(Stores.proposals).forEach(p => {
+ history.push({
+ detail: {},
+ timestamp: p.timestamp,
+ type: "claim-order",
+ explicit: false,
+ });
});
- }
- }
- const reserves = await oneShotIter(ws.db, Stores.reserves).toArray();
-
- for (const r of reserves) {
- const reserveType = r.bankWithdrawStatusUrl ? "taler-bank" : "manual";
- history.push({
- detail: {
- exchangeBaseUrl: r.exchangeBaseUrl,
- requestedAmount: Amounts.toString(r.initiallyRequestedAmount),
- reservePub: r.reservePub,
- reserveType,
- bankWithdrawStatusUrl: r.bankWithdrawStatusUrl,
- },
- timestamp: r.created,
- type: "reserve-created",
- explicit: false,
- });
- if (r.timestampConfirmed) {
- history.push({
- detail: {
- exchangeBaseUrl: r.exchangeBaseUrl,
- requestedAmount: Amounts.toString(r.initiallyRequestedAmount),
- reservePub: r.reservePub,
- reserveType,
- bankWithdrawStatusUrl: r.bankWithdrawStatusUrl,
- },
- timestamp: r.created,
- type: "reserve-confirmed",
- explicit: false,
+ await tx.iter(Stores.withdrawalSession).forEach(w => {
+ history.push({
+ detail: {
+ withdrawalAmount: w.rawWithdrawalAmount,
+ },
+ timestamp: w.startTimestamp,
+ type: "withdraw-started",
+ explicit: false,
+ });
+ if (w.finishTimestamp) {
+ history.push({
+ detail: {
+ withdrawalAmount: w.rawWithdrawalAmount,
+ },
+ timestamp: w.finishTimestamp,
+ type: "withdraw-finished",
+ explicit: false,
+ });
+ }
});
- }
- }
- const tips: TipRecord[] = await oneShotIter(ws.db, Stores.tips).toArray();
- for (const tip of tips) {
- history.push({
- detail: {
- accepted: tip.accepted,
- amount: tip.amount,
- merchantBaseUrl: tip.merchantBaseUrl,
- tipId: tip.merchantTipId,
- },
- timestamp: tip.createdTimestamp,
- explicit: false,
- type: "tip",
- });
- }
+ await tx.iter(Stores.purchases).forEach(p => {
+ history.push({
+ detail: {
+ amount: p.contractTerms.amount,
+ contractTermsHash: p.contractTermsHash,
+ fulfillmentUrl: p.contractTerms.fulfillment_url,
+ merchantName: p.contractTerms.merchant.name,
+ },
+ timestamp: p.acceptTimestamp,
+ type: "pay-started",
+ explicit: false,
+ });
+ if (p.firstSuccessfulPayTimestamp) {
+ history.push({
+ detail: {
+ amount: p.contractTerms.amount,
+ contractTermsHash: p.contractTermsHash,
+ fulfillmentUrl: p.contractTerms.fulfillment_url,
+ merchantName: p.contractTerms.merchant.name,
+ },
+ timestamp: p.firstSuccessfulPayTimestamp,
+ type: "pay-finished",
+ explicit: false,
+ });
+ }
+ if (p.lastRefundStatusTimestamp) {
+ const contractAmount = Amounts.parseOrThrow(p.contractTerms.amount);
+ const amountsPending = Object.keys(p.refundsPending).map(x =>
+ Amounts.parseOrThrow(p.refundsPending[x].refund_amount),
+ );
+ const amountsDone = Object.keys(p.refundsDone).map(x =>
+ Amounts.parseOrThrow(p.refundsDone[x].refund_amount),
+ );
+ const amounts: AmountJson[] = amountsPending.concat(amountsDone);
+ const amount = Amounts.add(
+ Amounts.getZero(contractAmount.currency),
+ ...amounts,
+ ).amount;
- await oneShotIter(ws.db, Stores.exchanges).forEach(exchange => {
- history.push({
- type: "exchange-added",
- explicit: false,
- timestamp: exchange.timestampAdded,
- detail: {
- exchangeBaseUrl: exchange.baseUrl,
- },
- });
- });
+ history.push({
+ detail: {
+ contractTermsHash: p.contractTermsHash,
+ fulfillmentUrl: p.contractTerms.fulfillment_url,
+ merchantName: p.contractTerms.merchant.name,
+ refundAmount: amount,
+ },
+ timestamp: p.lastRefundStatusTimestamp,
+ type: "refund",
+ explicit: false,
+ });
+ }
+ });
+
+ await tx.iter(Stores.reserves).forEach(r => {
+ const reserveType = r.bankWithdrawStatusUrl ? "taler-bank" : "manual";
+ history.push({
+ detail: {
+ exchangeBaseUrl: r.exchangeBaseUrl,
+ requestedAmount: Amounts.toString(r.initiallyRequestedAmount),
+ reservePub: r.reservePub,
+ reserveType,
+ bankWithdrawStatusUrl: r.bankWithdrawStatusUrl,
+ },
+ timestamp: r.created,
+ type: "reserve-created",
+ explicit: false,
+ });
+ if (r.timestampConfirmed) {
+ history.push({
+ detail: {
+ exchangeBaseUrl: r.exchangeBaseUrl,
+ requestedAmount: Amounts.toString(r.initiallyRequestedAmount),
+ reservePub: r.reservePub,
+ reserveType,
+ bankWithdrawStatusUrl: r.bankWithdrawStatusUrl,
+ },
+ timestamp: r.created,
+ type: "reserve-confirmed",
+ explicit: false,
+ });
+ }
+ });
+
+ await tx.iter(Stores.tips).forEach(tip => {
+ history.push({
+ detail: {
+ accepted: tip.accepted,
+ amount: tip.amount,
+ merchantBaseUrl: tip.merchantBaseUrl,
+ tipId: tip.merchantTipId,
+ },
+ timestamp: tip.createdTimestamp,
+ explicit: false,
+ type: "tip",
+ });
+ });
+
+ await tx.iter(Stores.exchanges).forEach(exchange => {
+ history.push({
+ type: "exchange-added",
+ explicit: false,
+ timestamp: exchange.timestampAdded,
+ detail: {
+ exchangeBaseUrl: exchange.baseUrl,
+ },
+ });
+ });
+
+ await tx.iter(Stores.refresh).forEach((r) => {
+ history.push({
+ type: "refresh-started",
+ explicit: false,
+ timestamp: r.created,
+ detail: {
+ refreshSessionId: r.refreshSessionId,
+ },
+ });
+ if (r.finishedTimestamp) {
+ history.push({
+ type: "refresh-finished",
+ explicit: false,
+ timestamp: r.finishedTimestamp,
+ detail: {
+ refreshSessionId: r.refreshSessionId,
+ },
+ });
+ }
+
+ });
+ },
+ );
history.sort((h1, h2) => Math.sign(h1.timestamp.t_ms - h2.timestamp.t_ms));
diff --git a/src/wallet-impl/pay.ts b/src/wallet-impl/pay.ts
index 1375a22ca..4933098cd 100644
--- a/src/wallet-impl/pay.ts
+++ b/src/wallet-impl/pay.ts
@@ -343,7 +343,6 @@ async function recordConfirmPay(
abortRequested: false,
contractTerms: d.contractTerms,
contractTermsHash: d.contractTermsHash,
- payFinished: false,
lastSessionId: undefined,
merchantSig: d.merchantSig,
payReq,
@@ -359,6 +358,7 @@ async function recordConfirmPay(
refundStatusRequested: false,
lastRefundApplyError: undefined,
refundApplyRetryInfo: initRetryInfo(),
+ firstSuccessfulPayTimestamp: undefined,
};
await runWithWriteTransaction(
@@ -405,7 +405,7 @@ export async function abortFailedPayment(
if (!purchase) {
throw Error("Purchase not found, unable to abort with refund");
}
- if (purchase.payFinished) {
+ if (purchase.firstSuccessfulPayTimestamp) {
throw Error("Purchase already finished, not aborting");
}
if (purchase.abortDone) {
@@ -465,6 +465,7 @@ async function incrementProposalRetry(
pr.lastError = err;
await tx.put(Stores.proposals, pr);
});
+ ws.notify({ type: NotificationType.ProposalOperationError });
}
async function incrementPurchasePayRetry(
@@ -486,6 +487,7 @@ async function incrementPurchasePayRetry(
pr.lastPayError = err;
await tx.put(Stores.purchases, pr);
});
+ ws.notify({ type: NotificationType.PayOperationError });
}
async function incrementPurchaseQueryRefundRetry(
@@ -507,6 +509,7 @@ async function incrementPurchaseQueryRefundRetry(
pr.lastRefundStatusError = err;
await tx.put(Stores.purchases, pr);
});
+ ws.notify({ type: NotificationType.RefundStatusOperationError });
}
async function incrementPurchaseApplyRefundRetry(
@@ -528,6 +531,7 @@ async function incrementPurchaseApplyRefundRetry(
pr.lastRefundApplyError = err;
await tx.put(Stores.purchases, pr);
});
+ ws.notify({ type: NotificationType.RefundApplyOperationError });
}
export async function processDownloadProposal(
@@ -698,7 +702,7 @@ export async function submitPay(
// FIXME: properly display error
throw Error("merchant payment signature invalid");
}
- purchase.payFinished = true;
+ purchase.firstSuccessfulPayTimestamp = getTimestampNow();
purchase.lastPayError = undefined;
purchase.payRetryInfo = initRetryInfo(false);
const modifiedCoins: CoinRecord[] = [];
@@ -1044,10 +1048,9 @@ async function acceptRefundResponse(
throw Error("empty refund");
}
-
let numNewRefunds = 0;
- await runWithWriteTransaction(ws.db, [Stores.purchases], async (tx) => {
+ await runWithWriteTransaction(ws.db, [Stores.purchases], async tx => {
const p = await tx.get(Stores.purchases, proposalId);
if (!p) {
console.error("purchase not found, not adding refunds");
@@ -1080,6 +1083,9 @@ async function acceptRefundResponse(
await tx.put(Stores.purchases, p);
});
+ ws.notify({
+ type: NotificationType.RefundQueried,
+ });
if (numNewRefunds > 0) {
await processPurchaseApplyRefund(ws, proposalId);
}
@@ -1099,7 +1105,6 @@ async function startRefundQuery(
return false;
}
if (p.refundStatusRequested) {
-
}
p.refundStatusRequested = true;
p.lastRefundStatusError = undefined;
@@ -1113,6 +1118,10 @@ async function startRefundQuery(
return;
}
+ ws.notify({
+ type: NotificationType.RefundStarted,
+ });
+
await processPurchaseQueryRefund(ws, proposalId);
}
@@ -1169,7 +1178,7 @@ async function processPurchasePayImpl(
return;
}
logger.trace(`processing purchase pay ${proposalId}`);
- if (purchase.payFinished) {
+ if (purchase.firstSuccessfulPayTimestamp) {
return;
}
await submitPay(ws, proposalId, purchase.lastSessionId);
diff --git a/src/wallet-impl/pending.ts b/src/wallet-impl/pending.ts
index 169c7e291..b0ae71f6b 100644
--- a/src/wallet-impl/pending.ts
+++ b/src/wallet-impl/pending.ts
@@ -353,7 +353,7 @@ async function gatherPurchasePending(
onlyDue: boolean = false,
): Promise {
await tx.iter(Stores.purchases).forEach((pr) => {
- if (!pr.payFinished) {
+ if (!pr.firstSuccessfulPayTimestamp) {
resp.nextRetryDelay = updateRetryDelay(
resp.nextRetryDelay,
now,
diff --git a/src/wallet-impl/refresh.ts b/src/wallet-impl/refresh.ts
index a3b48919d..93be1435d 100644
--- a/src/wallet-impl/refresh.ts
+++ b/src/wallet-impl/refresh.ts
@@ -312,6 +312,7 @@ async function incrementRefreshRetry(
r.lastError = err;
await tx.put(Stores.refresh, r);
});
+ ws.notify({ type: NotificationType.RefreshOperationError });
}
diff --git a/src/wallet-impl/reserves.ts b/src/wallet-impl/reserves.ts
index f00956b46..8a700bebc 100644
--- a/src/wallet-impl/reserves.ts
+++ b/src/wallet-impl/reserves.ts
@@ -342,6 +342,7 @@ async function incrementReserveRetry(
r.lastError = err;
await tx.put(Stores.reserves, r);
});
+ ws.notify({ type: NotificationType.ReserveOperationError });
}
/**
@@ -606,6 +607,10 @@ async function depleteReserve(
if (success) {
console.log("processing new withdraw session");
+ ws.notify({
+ type: NotificationType.WithdrawSessionCreated,
+ withdrawSessionId: withdrawalSessionId,
+ });
await processWithdrawSession(ws, withdrawalSessionId);
} else {
console.trace("withdraw session already existed");
diff --git a/src/wallet-impl/tip.ts b/src/wallet-impl/tip.ts
index 3ae931d45..9cfaed930 100644
--- a/src/wallet-impl/tip.ts
+++ b/src/wallet-impl/tip.ts
@@ -18,7 +18,7 @@
import { oneShotGet, oneShotPut, oneShotMutate, runWithWriteTransaction } from "../util/query";
import { InternalWalletState } from "./state";
import { parseTipUri } from "../util/taleruri";
-import { TipStatus, getTimestampNow, OperationError } from "../walletTypes";
+import { TipStatus, getTimestampNow, OperationError, NotificationType } from "../walletTypes";
import { TipPickupGetResponse, TipPlanchetDetail, TipResponse } from "../talerTypes";
import * as Amounts from "../util/amounts";
import { Stores, PlanchetRecord, WithdrawalSessionRecord, initRetryInfo, updateRetryInfoTimeout } from "../dbTypes";
@@ -122,6 +122,7 @@ async function incrementTipRetry(
t.lastError = err;
await tx.put(Stores.tips, t);
});
+ ws.notify({ type: NotificationType.TipOperationError });
}
export async function processTip(
diff --git a/src/wallet-impl/withdraw.ts b/src/wallet-impl/withdraw.ts
index 3122a463c..5d89f64a9 100644
--- a/src/wallet-impl/withdraw.ts
+++ b/src/wallet-impl/withdraw.ts
@@ -260,17 +260,17 @@ async function processPlanchet(
let withdrawSessionFinished = false;
let reserveDepleted = false;
- await runWithWriteTransaction(
+ const success = await runWithWriteTransaction(
ws.db,
[Stores.coins, Stores.withdrawalSession, Stores.reserves],
async tx => {
const ws = await tx.get(Stores.withdrawalSession, withdrawalSessionId);
if (!ws) {
- return;
+ return false;
}
if (ws.withdrawn[coinIdx]) {
// Already withdrawn
- return;
+ return false;
}
ws.withdrawn[coinIdx] = true;
ws.lastCoinErrors[coinIdx] = undefined;
@@ -301,9 +301,16 @@ async function processPlanchet(
}
}
await tx.add(Stores.coins, coin);
+ return true;
},
);
+ if (success) {
+ ws.notify( {
+ type: NotificationType.CoinWithdrawn,
+ } );
+ }
+
if (withdrawSessionFinished) {
ws.notify({
type: NotificationType.WithdrawSessionFinished,
@@ -503,6 +510,7 @@ async function incrementWithdrawalRetry(
wsr.lastError = err;
await tx.put(Stores.withdrawalSession, wsr);
});
+ ws.notify({ type: NotificationType.WithdrawOperationError });
}
export async function processWithdrawSession(
diff --git a/src/walletTypes.ts b/src/walletTypes.ts
index f27970330..6e246c682 100644
--- a/src/walletTypes.ts
+++ b/src/walletTypes.ts
@@ -506,6 +506,7 @@ export interface PendingPayOperation {
}
export const enum NotificationType {
+ CoinWithdrawn = "coin-withdrawn",
ProposalAccepted = "proposal-accepted",
ProposalDownloaded = "proposal-downloaded",
RefundsSubmitted = "refunds-submitted",
@@ -518,9 +519,21 @@ export const enum NotificationType {
ReserveUpdated = "reserve-updated",
ReserveConfirmed = "reserve-confirmed",
ReserveDepleted = "reserve-depleted",
+ WithdrawSessionCreated = "withdraw-session-created",
WithdrawSessionFinished = "withdraw-session-finished",
WaitingForRetry = "waiting-for-retry",
+ RefundStarted = "refund-started",
+ RefundQueried = "refund-queried",
RefundFinished = "refund-finished",
+ ExchangeOperationError = "exchange-operation-error",
+ RefreshOperationError = "refresh-operation-error",
+ RefundApplyOperationError = "refund-apply-error",
+ RefundStatusOperationError = "refund-status-error",
+ ProposalOperationError = "proposal-error",
+ TipOperationError = "tip-error",
+ PayOperationError = "pay-error",
+ WithdrawOperationError = "withdraw-error",
+ ReserveOperationError = "reserve-error",
}
export interface ProposalAcceptedNotification {
@@ -528,6 +541,18 @@ export interface ProposalAcceptedNotification {
proposalId: string;
}
+export interface CoinWithdrawnNotification {
+ type: NotificationType.CoinWithdrawn;
+}
+
+export interface RefundStartedNotification {
+ type: NotificationType.RefundStarted;
+}
+
+export interface RefundQueriedNotification {
+ type: NotificationType.RefundQueried;
+}
+
export interface ProposalDownloadedNotification {
type: NotificationType.ProposalDownloaded;
proposalId: string;
@@ -570,6 +595,11 @@ export interface ReserveConfirmedNotification {
type: NotificationType.ReserveConfirmed;
}
+export interface WithdrawSessionCreatedNotification {
+ type: NotificationType.WithdrawSessionCreated;
+ withdrawSessionId: string;
+}
+
export interface WithdrawSessionFinishedNotification {
type: NotificationType.WithdrawSessionFinished;
withdrawSessionId: string;
@@ -590,7 +620,52 @@ export interface RefundFinishedNotification {
type: NotificationType.RefundFinished;
}
+export interface ExchangeOperationErrorNotification {
+ type: NotificationType.ExchangeOperationError;
+}
+
+export interface RefreshOperationErrorNotification {
+ type: NotificationType.RefreshOperationError;
+}
+
+export interface RefundStatusOperationErrorNotification {
+ type: NotificationType.RefundStatusOperationError;
+}
+
+export interface RefundApplyOperationErrorNotification {
+ type: NotificationType.RefundApplyOperationError;
+}
+
+export interface PayOperationErrorNotification {
+ type: NotificationType.PayOperationError;
+}
+
+export interface ProposalOperationErrorNotification {
+ type: NotificationType.ProposalOperationError;
+}
+
+export interface TipOperationErrorNotification {
+ type: NotificationType.TipOperationError;
+}
+
+export interface WithdrawOperationErrorNotification {
+ type: NotificationType.WithdrawOperationError;
+}
+
+export interface ReserveOperationErrorNotification {
+ type: NotificationType.ReserveOperationError;
+}
+
export type WalletNotification =
+ | WithdrawOperationErrorNotification
+ | ReserveOperationErrorNotification
+ | ExchangeOperationErrorNotification
+ | RefreshOperationErrorNotification
+ | RefundStatusOperationErrorNotification
+ | RefundApplyOperationErrorNotification
+ | ProposalOperationErrorNotification
+ | PayOperationErrorNotification
+ | TipOperationErrorNotification
| ProposalAcceptedNotification
| ProposalDownloadedNotification
| RefundsSubmittedNotification
@@ -605,7 +680,11 @@ export type WalletNotification =
| WithdrawSessionFinishedNotification
| ReserveDepletedNotification
| WaitingForRetryNotification
- | RefundFinishedNotification;
+ | RefundStartedNotification
+ | RefundFinishedNotification
+ | RefundQueriedNotification
+ | WithdrawSessionCreatedNotification
+ | CoinWithdrawnNotification;
export interface OperationError {
type: string;