pending ops / history / notification tweaks
This commit is contained in:
parent
d8170c8159
commit
4159367d8c
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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) {
|
||||
|
@ -14,11 +14,11 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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));
|
||||
|
||||
|
@ -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);
|
||||
|
@ -353,7 +353,7 @@ async function gatherPurchasePending(
|
||||
onlyDue: boolean = false,
|
||||
): Promise<void> {
|
||||
await tx.iter(Stores.purchases).forEach((pr) => {
|
||||
if (!pr.payFinished) {
|
||||
if (!pr.firstSuccessfulPayTimestamp) {
|
||||
resp.nextRetryDelay = updateRetryDelay(
|
||||
resp.nextRetryDelay,
|
||||
now,
|
||||
|
@ -312,6 +312,7 @@ async function incrementRefreshRetry(
|
||||
r.lastError = err;
|
||||
await tx.put(Stores.refresh, r);
|
||||
});
|
||||
ws.notify({ type: NotificationType.RefreshOperationError });
|
||||
}
|
||||
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user