wallet-core: reset reserve retry when resetting withdrawal retry
This commit is contained in:
parent
38d8239f93
commit
c493a3069e
@ -65,6 +65,14 @@ export interface MerchantOperations {
|
|||||||
): Promise<MerchantInfo>;
|
): Promise<MerchantInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ReserveOperations {
|
||||||
|
processReserve(
|
||||||
|
ws: InternalWalletState,
|
||||||
|
reservePub: string,
|
||||||
|
forceNow?: boolean,
|
||||||
|
): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for exchange-related operations.
|
* Interface for exchange-related operations.
|
||||||
*/
|
*/
|
||||||
@ -152,6 +160,7 @@ export interface InternalWalletState {
|
|||||||
exchangeOps: ExchangeOperations;
|
exchangeOps: ExchangeOperations;
|
||||||
recoupOps: RecoupOperations;
|
recoupOps: RecoupOperations;
|
||||||
merchantOps: MerchantOperations;
|
merchantOps: MerchantOperations;
|
||||||
|
reserveOps: ReserveOperations;
|
||||||
|
|
||||||
db: DbAccess<typeof WalletStoresV1>;
|
db: DbAccess<typeof WalletStoresV1>;
|
||||||
http: HttpRequestLibrary;
|
http: HttpRequestLibrary;
|
||||||
|
@ -15,35 +15,63 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AcceptWithdrawalResponse, addPaytoQueryParams, Amounts, canonicalizeBaseUrl, codecForBankWithdrawalOperationPostResponse,
|
AcceptWithdrawalResponse,
|
||||||
|
addPaytoQueryParams,
|
||||||
|
Amounts,
|
||||||
|
canonicalizeBaseUrl,
|
||||||
|
codecForBankWithdrawalOperationPostResponse,
|
||||||
codecForReserveStatus,
|
codecForReserveStatus,
|
||||||
codecForWithdrawOperationStatusResponse, CreateReserveRequest,
|
codecForWithdrawOperationStatusResponse,
|
||||||
CreateReserveResponse, Duration,
|
CreateReserveRequest,
|
||||||
|
CreateReserveResponse,
|
||||||
|
Duration,
|
||||||
durationMax,
|
durationMax,
|
||||||
durationMin, encodeCrock, getRandomBytes, getTimestampNow, Logger, NotificationType, randomBytes, ReserveTransactionType,
|
durationMin,
|
||||||
TalerErrorCode, TalerErrorDetails, URL
|
encodeCrock,
|
||||||
|
getRandomBytes,
|
||||||
|
getTimestampNow,
|
||||||
|
Logger,
|
||||||
|
NotificationType,
|
||||||
|
randomBytes,
|
||||||
|
ReserveTransactionType,
|
||||||
|
TalerErrorCode,
|
||||||
|
TalerErrorDetails,
|
||||||
|
URL,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { InternalWalletState } from "../common.js";
|
import { InternalWalletState } from "../common.js";
|
||||||
import {
|
import {
|
||||||
ReserveBankInfo,
|
ReserveBankInfo,
|
||||||
ReserveRecord, ReserveRecordStatus, WalletStoresV1, WithdrawalGroupRecord
|
ReserveRecord,
|
||||||
|
ReserveRecordStatus,
|
||||||
|
WalletStoresV1,
|
||||||
|
WithdrawalGroupRecord,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { guardOperationException, OperationFailedError } from "../errors.js";
|
import { guardOperationException, OperationFailedError } from "../errors.js";
|
||||||
import { assertUnreachable } from "../util/assertUnreachable.js";
|
import { assertUnreachable } from "../util/assertUnreachable.js";
|
||||||
import {
|
import {
|
||||||
readSuccessResponseJsonOrErrorCode,
|
readSuccessResponseJsonOrErrorCode,
|
||||||
readSuccessResponseJsonOrThrow,
|
readSuccessResponseJsonOrThrow,
|
||||||
throwUnexpectedRequestError
|
throwUnexpectedRequestError,
|
||||||
} from "../util/http.js";
|
} from "../util/http.js";
|
||||||
import { GetReadOnlyAccess } from "../util/query.js";
|
import { GetReadOnlyAccess } from "../util/query.js";
|
||||||
import {
|
import {
|
||||||
getRetryDuration, initRetryInfo, updateRetryInfoTimeout
|
getRetryDuration,
|
||||||
|
initRetryInfo,
|
||||||
|
updateRetryInfoTimeout,
|
||||||
} from "../util/retries.js";
|
} from "../util/retries.js";
|
||||||
import {
|
import {
|
||||||
getExchangeDetails, getExchangePaytoUri, getExchangeTrust, updateExchangeFromUrl
|
getExchangeDetails,
|
||||||
|
getExchangePaytoUri,
|
||||||
|
getExchangeTrust,
|
||||||
|
updateExchangeFromUrl,
|
||||||
} from "./exchanges.js";
|
} from "./exchanges.js";
|
||||||
import {
|
import {
|
||||||
denomSelectionInfoToState, getBankWithdrawalInfo, getCandidateWithdrawalDenoms, processWithdrawGroup, selectWithdrawalDenominations, updateWithdrawalDenoms
|
denomSelectionInfoToState,
|
||||||
|
getBankWithdrawalInfo,
|
||||||
|
getCandidateWithdrawalDenoms,
|
||||||
|
processWithdrawGroup,
|
||||||
|
selectWithdrawalDenominations,
|
||||||
|
updateWithdrawalDenoms,
|
||||||
} from "./withdraw.js";
|
} from "./withdraw.js";
|
||||||
|
|
||||||
const logger = new Logger("reserves.ts");
|
const logger = new Logger("reserves.ts");
|
||||||
@ -617,7 +645,8 @@ async function updateReserve(
|
|||||||
logger.trace(
|
logger.trace(
|
||||||
`Remaining unclaimed amount in reseve is ${Amounts.stringify(
|
`Remaining unclaimed amount in reseve is ${Amounts.stringify(
|
||||||
remainingAmount,
|
remainingAmount,
|
||||||
)} and can be withdrawn with ${denomSelInfo.selectedDenoms.length
|
)} and can be withdrawn with ${
|
||||||
|
denomSelInfo.selectedDenoms.length
|
||||||
} coins`,
|
} coins`,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -19,12 +19,25 @@
|
|||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts, OrderShortInfo, PaymentStatus, timestampCmp, Transaction, TransactionsRequest,
|
Amounts,
|
||||||
TransactionsResponse, TransactionType, WithdrawalDetails, WithdrawalType
|
Logger,
|
||||||
|
OrderShortInfo,
|
||||||
|
PaymentStatus,
|
||||||
|
timestampCmp,
|
||||||
|
Transaction,
|
||||||
|
TransactionsRequest,
|
||||||
|
TransactionsResponse,
|
||||||
|
TransactionType,
|
||||||
|
WithdrawalDetails,
|
||||||
|
WithdrawalType,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { InternalWalletState } from "../common.js";
|
import { InternalWalletState } from "../common.js";
|
||||||
import {
|
import {
|
||||||
AbortStatus, RefundState, ReserveRecord, ReserveRecordStatus, WalletRefundItem
|
AbortStatus,
|
||||||
|
RefundState,
|
||||||
|
ReserveRecord,
|
||||||
|
ReserveRecordStatus,
|
||||||
|
WalletRefundItem,
|
||||||
} from "../db.js";
|
} from "../db.js";
|
||||||
import { processDepositGroup } from "./deposits.js";
|
import { processDepositGroup } from "./deposits.js";
|
||||||
import { getExchangeDetails } from "./exchanges.js";
|
import { getExchangeDetails } from "./exchanges.js";
|
||||||
@ -34,6 +47,8 @@ import { getFundingPaytoUris } from "./reserves.js";
|
|||||||
import { processTip } from "./tip.js";
|
import { processTip } from "./tip.js";
|
||||||
import { processWithdrawGroup } from "./withdraw.js";
|
import { processWithdrawGroup } from "./withdraw.js";
|
||||||
|
|
||||||
|
const logger = new Logger("taler-wallet-core:transactions.ts");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an event ID from the type and the primary key for the event.
|
* Create an event ID from the type and the primary key for the event.
|
||||||
*/
|
*/
|
||||||
@ -404,13 +419,6 @@ export enum TombstoneTag {
|
|||||||
DeleteRefund = "delete-refund",
|
DeleteRefund = "delete-refund",
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function retryTransactionNow(
|
|
||||||
ws: InternalWalletState,
|
|
||||||
transactionId: string,
|
|
||||||
): Promise<void> {
|
|
||||||
const [type, ...rest] = transactionId.split(":");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immediately retry the underlying operation
|
* Immediately retry the underlying operation
|
||||||
* of a transaction.
|
* of a transaction.
|
||||||
@ -419,6 +427,8 @@ export async function retryTransaction(
|
|||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
transactionId: string,
|
transactionId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
logger.info(`retrying transaction ${transactionId}`);
|
||||||
|
|
||||||
const [type, ...rest] = transactionId.split(":");
|
const [type, ...rest] = transactionId.split(":");
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -854,7 +854,10 @@ async function resetWithdrawalGroupRetry(
|
|||||||
withdrawalGroupId: string,
|
withdrawalGroupId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await ws.db
|
await ws.db
|
||||||
.mktx((x) => ({ withdrawalGroups: x.withdrawalGroups }))
|
.mktx((x) => ({
|
||||||
|
withdrawalGroups: x.withdrawalGroups,
|
||||||
|
reserves: x.reserves,
|
||||||
|
}))
|
||||||
.runReadWrite(async (tx) => {
|
.runReadWrite(async (tx) => {
|
||||||
const x = await tx.withdrawalGroups.get(withdrawalGroupId);
|
const x = await tx.withdrawalGroups.get(withdrawalGroupId);
|
||||||
if (x) {
|
if (x) {
|
||||||
@ -879,9 +882,27 @@ async function processWithdrawGroupImpl(
|
|||||||
return tx.withdrawalGroups.get(withdrawalGroupId);
|
return tx.withdrawalGroups.get(withdrawalGroupId);
|
||||||
});
|
});
|
||||||
if (!withdrawalGroup) {
|
if (!withdrawalGroup) {
|
||||||
logger.trace("withdraw session doesn't exist");
|
// Withdrawal group doesn't exist yet, but reserve might exist
|
||||||
|
// (and reference the yet to be created withdrawal group)
|
||||||
|
const reservePub = await ws.db
|
||||||
|
.mktx((x) => ({ reserves: x.reserves }))
|
||||||
|
.runReadOnly(async (tx) => {
|
||||||
|
const r = await tx.reserves.indexes.byInitialWithdrawalGroupId.get(
|
||||||
|
withdrawalGroupId,
|
||||||
|
);
|
||||||
|
if (r) {
|
||||||
|
return r.reservePub;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
if (!reservePub) {
|
||||||
|
logger.warn(
|
||||||
|
"withdrawal group doesn't exist (and reserve doesn't exist either)",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
return await ws.reserveOps.processReserve(ws, reservePub, forceNow);
|
||||||
|
}
|
||||||
|
|
||||||
await ws.exchangeOps.updateExchangeFromUrl(
|
await ws.exchangeOps.updateExchangeFromUrl(
|
||||||
ws,
|
ws,
|
||||||
|
@ -103,6 +103,7 @@ import {
|
|||||||
MerchantOperations,
|
MerchantOperations,
|
||||||
NotificationListener,
|
NotificationListener,
|
||||||
RecoupOperations,
|
RecoupOperations,
|
||||||
|
ReserveOperations,
|
||||||
} from "./common.js";
|
} from "./common.js";
|
||||||
import {
|
import {
|
||||||
runIntegrationTest,
|
runIntegrationTest,
|
||||||
@ -1122,6 +1123,10 @@ class InternalWalletStateImpl implements InternalWalletState {
|
|||||||
getMerchantInfo: getMerchantInfo,
|
getMerchantInfo: getMerchantInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
reserveOps: ReserveOperations = {
|
||||||
|
processReserve: processReserve,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Promises that are waiting for a particular resource.
|
* Promises that are waiting for a particular resource.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user