gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet-core: try to abort wit


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: try to abort withdrawals wallet-side with the bank
Date: Tue, 06 Jun 2023 17:07:13 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 002ab0dab wallet-core: try to abort withdrawals wallet-side with the 
bank
002ab0dab is described below

commit 002ab0dab7b83c5999b0f82c430e716c718251e6
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Jun 6 17:07:09 2023 +0200

    wallet-core: try to abort withdrawals wallet-side with the bank
---
 packages/taler-wallet-core/src/db.ts               |   2 +
 .../taler-wallet-core/src/operations/withdraw.ts   | 216 ++++++++++++++-------
 2 files changed, 147 insertions(+), 71 deletions(-)

diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index 195760831..9905fa370 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -210,6 +210,8 @@ export enum WithdrawalGroupStatus {
    * wired or not.
    */
   AbortedExchange = 60,
+
+  AbortedBank = 61,
 }
 
 /**
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index 7db6dcd2a..61cab6fbb 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -316,6 +316,7 @@ export async function abortWithdrawalTransaction(
         case WithdrawalGroupStatus.Finished:
         case WithdrawalGroupStatus.FailedBankAborted:
         case WithdrawalGroupStatus.AbortedExchange:
+        case WithdrawalGroupStatus.AbortedBank:
         case WithdrawalGroupStatus.FailedAbortingBank:
           // Not allowed
           throw Error("abort not allowed in current state");
@@ -481,6 +482,12 @@ export function computeWithdrawalTransactionStatus(
         major: TransactionMajorState.Aborted,
         minor: TransactionMinorState.Exchange,
       };
+
+    case WithdrawalGroupStatus.AbortedBank:
+      return {
+        major: TransactionMajorState.Aborted,
+        minor: TransactionMinorState.Bank,
+      };
   }
 }
 
@@ -507,7 +514,7 @@ export function computeWithdrawalTransactionActions(
     case WithdrawalGroupStatus.SuspendedQueryingStatus:
       return [TransactionAction.Resume, TransactionAction.Abort];
     case WithdrawalGroupStatus.SuspendedRegisteringBank:
-      return [TransactionAction.Resume, TransactionAction.Abort]
+      return [TransactionAction.Resume, TransactionAction.Abort];
     case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
       return [TransactionAction.Resume, TransactionAction.Abort];
     case WithdrawalGroupStatus.SuspendedReady:
@@ -519,11 +526,13 @@ export function computeWithdrawalTransactionActions(
     case WithdrawalGroupStatus.SuspendedAml:
       return [TransactionAction.Resume, TransactionAction.Abort];
     case WithdrawalGroupStatus.SuspendedKyc:
-      return [TransactionAction.Resume, TransactionAction.Abort]
+      return [TransactionAction.Resume, TransactionAction.Abort];
     case WithdrawalGroupStatus.FailedAbortingBank:
       return [TransactionAction.Delete];
     case WithdrawalGroupStatus.AbortedExchange:
       return [TransactionAction.Delete];
+    case WithdrawalGroupStatus.AbortedBank:
+      return [TransactionAction.Delete];
   }
 }
 
@@ -1270,87 +1279,61 @@ export interface WithdrawalGroupContext {
   wgRecord: WithdrawalGroupRecord;
 }
 
-export async function processWithdrawalGroup(
+async function processWithdrawalGroupAbortingBank(
   ws: InternalWalletState,
-  withdrawalGroupId: string,
+  withdrawalGroup: WithdrawalGroupRecord,
 ): Promise<OperationAttemptResult> {
-  logger.trace("processing withdrawal group", withdrawalGroupId);
-  const withdrawalGroup = await ws.db
-    .mktx((x) => [x.withdrawalGroups])
-    .runReadOnly(async (tx) => {
-      return tx.withdrawalGroups.get(withdrawalGroupId);
-    });
-
-  if (!withdrawalGroup) {
-    throw Error(`withdrawal group ${withdrawalGroupId} not found`);
-  }
-
-  const retryTag = TaskIdentifiers.forWithdrawal(withdrawalGroup);
+  const { withdrawalGroupId } = withdrawalGroup;
   const transactionId = constructTransactionIdentifier({
     tag: TransactionType.Withdrawal,
     withdrawalGroupId,
   });
 
-  // We're already running!
-  if (ws.activeLongpoll[retryTag]) {
-    logger.info("withdrawal group already in long-polling, returning!");
-    return {
-      type: OperationAttemptResultType.Longpoll,
-    };
+  const wgInfo = withdrawalGroup.wgInfo;
+  if (wgInfo.withdrawalType != WithdrawalRecordType.BankIntegrated) {
+    throw Error("invalid state (aborting(bank) without bank info");
   }
+  const abortUrl = getBankAbortUrl(wgInfo.bankInfo.talerWithdrawUri);
+  logger.info(`aborting withdrawal at ${abortUrl}`);
+  const abortResp = await ws.http.fetch(abortUrl, {
+    method: "POST",
+    body: {},
+  });
+  logger.info(`abort response status: ${abortResp.status}`);
 
-  switch (withdrawalGroup.status) {
-    case WithdrawalGroupStatus.PendingRegisteringBank:
-      await processReserveBankStatus(ws, withdrawalGroupId);
-      // FIXME: This will get called by the main task loop, why call it here?!
-      return await processWithdrawalGroup(ws, withdrawalGroupId);
-    case WithdrawalGroupStatus.PendingQueryingStatus: {
-      runLongpollAsync(ws, retryTag, (ct) => {
-        return queryReserve(ws, withdrawalGroupId, ct);
-      });
-      logger.trace(
-        "returning early from withdrawal for long-polling in background",
-      );
-      return {
-        type: OperationAttemptResultType.Longpoll,
-      };
-    }
-    case WithdrawalGroupStatus.PendingWaitConfirmBank: {
-      const res = await processReserveBankStatus(ws, withdrawalGroupId);
-      switch (res.status) {
-        case BankStatusResultCode.Aborted:
-        case BankStatusResultCode.Done:
-          return {
-            type: OperationAttemptResultType.Finished,
-            result: undefined,
-          };
-        case BankStatusResultCode.Waiting: {
-          return {
-            type: OperationAttemptResultType.Pending,
-            result: undefined,
-          };
-        }
+  const transitionInfo = await ws.db
+    .mktx((x) => [x.withdrawalGroups])
+    .runReadWrite(async (tx) => {
+      const wg = await tx.withdrawalGroups.get(withdrawalGroupId);
+      if (!wg) {
+        return undefined;
       }
-      break;
-    }
-    case WithdrawalGroupStatus.FailedBankAborted: {
-      // FIXME
+      const txStatusOld = computeWithdrawalTransactionStatus(wg);
+      wg.status = WithdrawalGroupStatus.AbortedBank;
+      wg.timestampFinish = TalerPreciseTimestamp.now();
+      const txStatusNew = computeWithdrawalTransactionStatus(wg);
+      await tx.withdrawalGroups.put(wg);
       return {
-        type: OperationAttemptResultType.Pending,
-        result: undefined,
+        oldTxState: txStatusOld,
+        newTxState: txStatusNew,
       };
-    }
-    case WithdrawalGroupStatus.Finished:
-      // We can try to withdraw, nothing needs to be done with the reserve.
-      break;
-    case WithdrawalGroupStatus.PendingReady:
-      // Continue with the actual withdrawal!
-      break;
-    default:
-      throw new InvariantViolatedError(
-        `unknown reserve record status: ${withdrawalGroup.status}`,
-      );
-  }
+    });
+  notifyTransition(ws, transactionId, transitionInfo);
+  return {
+    type: OperationAttemptResultType.Finished,
+    result: undefined,
+  };
+}
+
+async function processWithdrawalGroupPendingReady(
+  ws: InternalWalletState,
+  withdrawalGroup: WithdrawalGroupRecord,
+): Promise<OperationAttemptResult> {
+  const { withdrawalGroupId } = withdrawalGroup;
+  const transactionId = constructTransactionIdentifier({
+    tag: TransactionType.Withdrawal,
+    withdrawalGroupId,
+  });
 
   await ws.exchangeOps.updateExchangeFromUrl(
     ws,
@@ -1544,6 +1527,85 @@ export async function processWithdrawalGroup(
   };
 }
 
+export async function processWithdrawalGroup(
+  ws: InternalWalletState,
+  withdrawalGroupId: string,
+): Promise<OperationAttemptResult> {
+  logger.trace("processing withdrawal group", withdrawalGroupId);
+  const withdrawalGroup = await ws.db
+    .mktx((x) => [x.withdrawalGroups])
+    .runReadOnly(async (tx) => {
+      return tx.withdrawalGroups.get(withdrawalGroupId);
+    });
+
+  if (!withdrawalGroup) {
+    throw Error(`withdrawal group ${withdrawalGroupId} not found`);
+  }
+
+  const retryTag = TaskIdentifiers.forWithdrawal(withdrawalGroup);
+
+  // We're already running!
+  if (ws.activeLongpoll[retryTag]) {
+    logger.info("withdrawal group already in long-polling, returning!");
+    return {
+      type: OperationAttemptResultType.Longpoll,
+    };
+  }
+
+  switch (withdrawalGroup.status) {
+    case WithdrawalGroupStatus.PendingRegisteringBank:
+      await processReserveBankStatus(ws, withdrawalGroupId);
+      // FIXME: This will get called by the main task loop, why call it here?!
+      return await processWithdrawalGroup(ws, withdrawalGroupId);
+    case WithdrawalGroupStatus.PendingQueryingStatus: {
+      runLongpollAsync(ws, retryTag, (ct) => {
+        return queryReserve(ws, withdrawalGroupId, ct);
+      });
+      logger.trace(
+        "returning early from withdrawal for long-polling in background",
+      );
+      return {
+        type: OperationAttemptResultType.Longpoll,
+      };
+    }
+    case WithdrawalGroupStatus.PendingWaitConfirmBank: {
+      const res = await processReserveBankStatus(ws, withdrawalGroupId);
+      switch (res.status) {
+        case BankStatusResultCode.Aborted:
+        case BankStatusResultCode.Done:
+          return {
+            type: OperationAttemptResultType.Finished,
+            result: undefined,
+          };
+        case BankStatusResultCode.Waiting: {
+          return {
+            type: OperationAttemptResultType.Pending,
+            result: undefined,
+          };
+        }
+      }
+      break;
+    }
+    case WithdrawalGroupStatus.Finished:
+    case WithdrawalGroupStatus.FailedBankAborted: {
+      // FIXME
+      return {
+        type: OperationAttemptResultType.Pending,
+        result: undefined,
+      };
+    }
+    case WithdrawalGroupStatus.PendingReady:
+      // Continue with the actual withdrawal!
+      return await processWithdrawalGroupPendingReady(ws, withdrawalGroup);
+    case WithdrawalGroupStatus.AbortingBank:
+      return await processWithdrawalGroupAbortingBank(ws, withdrawalGroup);
+    default:
+      throw new InvariantViolatedError(
+        `unknown withdrawal group status: ${withdrawalGroup.status}`,
+      );
+  }
+}
+
 export async function checkWithdrawalKycStatus(
   ws: InternalWalletState,
   exchangeUrl: string,
@@ -1890,6 +1952,18 @@ export function getBankStatusUrl(talerWithdrawUri: 
string): string {
   return url.href;
 }
 
+export function getBankAbortUrl(talerWithdrawUri: string): string {
+  const uriResult = parseWithdrawUri(talerWithdrawUri);
+  if (!uriResult) {
+    throw Error(`can't parse withdrawal URL ${talerWithdrawUri}`);
+  }
+  const url = new URL(
+    `withdrawal-operation/${uriResult.withdrawalOperationId}/abort`,
+    uriResult.bankIntegrationApiBaseUrl,
+  );
+  return url.href;
+}
+
 async function registerReserveWithBank(
   ws: InternalWalletState,
   withdrawalGroupId: string,

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]