summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/withdraw.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-core/src/withdraw.ts')
-rw-r--r--packages/taler-wallet-core/src/withdraw.ts86
1 files changed, 81 insertions, 5 deletions
diff --git a/packages/taler-wallet-core/src/withdraw.ts b/packages/taler-wallet-core/src/withdraw.ts
index 0f70479a5..f27e9e132 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -95,10 +95,6 @@ import {
throwUnexpectedRequestError,
} from "@gnu-taler/taler-util/http";
import {
- selectForcedWithdrawalDenominations,
- selectWithdrawalDenominations,
-} from "./denomSelection.js";
-import {
PendingTaskType,
TaskIdStr,
TaskRunResult,
@@ -127,6 +123,10 @@ import {
WithdrawalRecordType,
timestampPreciseToDb,
} from "./db.js";
+import {
+ selectForcedWithdrawalDenominations,
+ selectWithdrawalDenominations,
+} from "./denomSelection.js";
import { isWithdrawableDenom } from "./denominations.js";
import {
ReadyExchangeSummary,
@@ -1935,7 +1935,8 @@ export async function getWithdrawalDetailsForUri(
uri: talerWithdrawUri,
});
}
- }).finally(() => {
+ })
+ .finally(() => {
ongoingChecks[talerWithdrawUri] = false;
});
}
@@ -2703,6 +2704,7 @@ async function waitWithdrawalRegistered(
wex: WalletExecutionContext,
ctx: WithdrawTransactionContext,
): Promise<void> {
+ // FIXME: Doesn't support cancellation yet
// FIXME: We should use Symbol.dispose magic here for cleanup!
const withdrawalNotifFlag = new AsyncFlag();
@@ -2914,3 +2916,77 @@ export async function createManualWithdrawal(
transactionId: ctx.transactionId,
};
}
+
+/**
+ * Wait until a refresh operation is final.
+ */
+export async function waitWithdrawalFinal(
+ wex: WalletExecutionContext,
+ withdrawalGroupId: string,
+): Promise<void> {
+ const ctx = new WithdrawTransactionContext(wex, withdrawalGroupId);
+ wex.taskScheduler.startShepherdTask(ctx.taskId);
+
+ // FIXME: Clean up using the new JS "using" / Symbol.dispose syntax.
+ const withdrawalNotifFlag = new AsyncFlag();
+ // Raise purchaseNotifFlag whenever we get a notification
+ // about our refresh.
+ const cancelNotif = wex.ws.addNotificationListener((notif) => {
+ if (
+ notif.type === NotificationType.TransactionStateTransition &&
+ notif.transactionId === ctx.transactionId
+ ) {
+ withdrawalNotifFlag.raise();
+ }
+ });
+ const unregisterOnCancelled = wex.cancellationToken.onCancelled(() => {
+ cancelNotif();
+ withdrawalNotifFlag.raise();
+ });
+
+ try {
+ await internalWaitWithdrawalFinal(ctx, withdrawalNotifFlag);
+ } catch (e) {
+ unregisterOnCancelled();
+ cancelNotif();
+ }
+}
+
+async function internalWaitWithdrawalFinal(
+ ctx: WithdrawTransactionContext,
+ flag: AsyncFlag,
+): Promise<void> {
+ while (true) {
+ if (ctx.wex.cancellationToken.isCancelled) {
+ throw Error("cancelled");
+ }
+
+ // Check if refresh is final
+ const res = await ctx.wex.db.runReadOnlyTx(
+ ["withdrawalGroups", "operationRetries"],
+ async (tx) => {
+ return {
+ wg: await tx.withdrawalGroups.get(ctx.withdrawalGroupId),
+ };
+ },
+ );
+ const { wg } = res;
+ if (!wg) {
+ // Must've been deleted, we consider that final.
+ return;
+ }
+ switch (wg.status) {
+ case WithdrawalGroupStatus.AbortedBank:
+ case WithdrawalGroupStatus.AbortedExchange:
+ case WithdrawalGroupStatus.Done:
+ case WithdrawalGroupStatus.FailedAbortingBank:
+ case WithdrawalGroupStatus.FailedBankAborted:
+ // Transaction is final
+ return;
+ }
+
+ // Wait for the next transition
+ await flag.wait();
+ flag.reset();
+ }
+}