gnunet-svn
[Top][All Lists]
Advanced

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

[taler-typescript-core] branch master updated: fix test, simplify


From: gnunet
Subject: [taler-typescript-core] branch master updated: fix test, simplify
Date: Thu, 16 Jan 2025 15:39:24 +0100

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 87d3eb80c fix test, simplify
87d3eb80c is described below

commit 87d3eb80c6ddb1b24740e073705d515d12f3e9f4
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Jan 16 15:39:19 2025 +0100

    fix test, simplify
---
 .../src/integrationtests/test-bank-wop.ts          |  32 +++++-
 .../integrationtests/test-withdrawal-conflict.ts   |  38 ++++---
 packages/taler-util/src/codec.ts                   |   3 +
 .../taler-util/src/http-client/bank-integration.ts |   3 +-
 packages/taler-util/src/types-taler-common.ts      |   1 +
 packages/taler-util/src/types-taler-corebank.ts    |   3 +
 .../src/types-taler-wallet-transactions.ts         |   2 +
 packages/taler-util/src/types-taler-wallet.ts      |  13 ++-
 packages/taler-wallet-core/src/testing.ts          |  23 ++--
 packages/taler-wallet-core/src/withdraw.ts         | 126 +++++++++++++--------
 10 files changed, 161 insertions(+), 83 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-bank-wop.ts 
b/packages/taler-harness/src/integrationtests/test-bank-wop.ts
index a07ed9920..d857884c7 100644
--- a/packages/taler-harness/src/integrationtests/test-bank-wop.ts
+++ b/packages/taler-harness/src/integrationtests/test-bank-wop.ts
@@ -18,6 +18,8 @@
  * Imports.
  */
 import {
+  createEddsaKeyPair,
+  encodeCrock,
   j2s,
   narrowOpSuccessOrThrow,
   TalerBankIntegrationHttpClient,
@@ -35,7 +37,8 @@ import { GlobalTestState } from "../harness/harness.js";
 export async function runBankWopTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { bank } = await createSimpleTestkudosEnvironmentV3(t);
+  const { bank, exchange, exchangeBankAccount } =
+    await createSimpleTestkudosEnvironmentV3(t);
 
   const bankClientNg = new TalerCoreBankHttpClient(bank.corebankApiBaseUrl);
 
@@ -48,15 +51,34 @@ export async function runBankWopTest(t: GlobalTestState) {
   narrowOpSuccessOrThrow("", withdrawalRes);
 
   const biClient = new TalerBankIntegrationHttpClient(
-    `${bank.corebankApiBaseUrl}/taler-integration/`,
+    `${bank.corebankApiBaseUrl}taler-integration/`,
   );
 
-  const wopStatus = await biClient.getWithdrawalOperationById(
-    withdrawalRes.body.withdrawal_id,
-  );
+  const wopid = withdrawalRes.body.withdrawal_id;
+
+  const wopStatus = await biClient.getWithdrawalOperationById(wopid);
   narrowOpSuccessOrThrow("", wopStatus);
 
   console.log(`${j2s(wopStatus)}`);
+
+  const keyPair = createEddsaKeyPair();
+
+  const postRes = await biClient.completeWithdrawalOperationById(wopid, {
+    selected_exchange: exchangeBankAccount.accountPaytoUri,
+    reserve_pub: encodeCrock(keyPair.eddsaPub),
+  });
+  narrowOpSuccessOrThrow("", postRes);
+
+  const confirmResp = await bankClientNg.confirmWithdrawalById(
+    bankUser,
+    {},
+    wopid,
+  );
+  narrowOpSuccessOrThrow("", confirmResp);
+
+  const wopStatus2 = await biClient.getWithdrawalOperationById(wopid);
+  narrowOpSuccessOrThrow("", wopStatus2);
+  console.log(`status after: ${j2s(wopStatus2.body)}`);
 }
 
 runBankWopTest.suites = ["wallet"];
diff --git 
a/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts 
b/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
index 576890801..757cf6e6d 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-conflict.ts
@@ -22,6 +22,7 @@ import {
   TransactionIdStr,
   TransactionMajorState,
   TransactionMinorState,
+  TransactionStatePattern,
   j2s,
 } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
@@ -131,30 +132,31 @@ export async function runWithdrawalConflictTest(t: 
GlobalTestState) {
   // One wallet will succeed, another one will have an aborted transaction.
   // Order is non-determinstic.
 
+  // The "aborted(bank)" state is only present because the 
taler-exchange-fakebank
+  // returns 404 when one wallet completes the withdrawal, which is a
+  // bug.
+  const expectedFinalStates = [
+    {
+      major: TransactionMajorState.Done,
+    },
+    {
+      major: TransactionMajorState.Aborted,
+      minor: "*",
+    },
+    {
+      major: TransactionMajorState.Failed,
+      minor: "*",
+    },
+  ] satisfies TransactionStatePattern[];
+
   await walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
     transactionId: wMainPrepareResp.transactionId as TransactionIdStr,
-    txState: [
-      {
-        major: TransactionMajorState.Done,
-      },
-      {
-        major: TransactionMajorState.Aborted,
-        minor: TransactionMinorState.CompletedByOtherWallet,
-      },
-    ],
+    txState: expectedFinalStates,
   });
 
   await w2.walletClient.call(WalletApiOperation.TestingWaitTransactionState, {
     transactionId: w2PrepareResp.transactionId as TransactionIdStr,
-    txState: [
-      {
-        major: TransactionMajorState.Done,
-      },
-      {
-        major: TransactionMajorState.Aborted,
-        minor: TransactionMinorState.CompletedByOtherWallet,
-      },
-    ],
+    txState: expectedFinalStates,
   });
 }
 
diff --git a/packages/taler-util/src/codec.ts b/packages/taler-util/src/codec.ts
index 4c02fb1d7..cbbfff23c 100644
--- a/packages/taler-util/src/codec.ts
+++ b/packages/taler-util/src/codec.ts
@@ -114,6 +114,9 @@ class ObjectCodecBuilder<OutputType, PartialOutputType> {
     return this as any;
   }
 
+  /**
+   * Do not log warnings if the object has extra properties.
+   */
   allowExtra(): ObjectCodecBuilder<OutputType, PartialOutputType> {
     this._allowExtra = true;
     return this;
diff --git a/packages/taler-util/src/http-client/bank-integration.ts 
b/packages/taler-util/src/http-client/bank-integration.ts
index 17c5337c2..e25c88962 100644
--- a/packages/taler-util/src/http-client/bank-integration.ts
+++ b/packages/taler-util/src/http-client/bank-integration.ts
@@ -127,8 +127,9 @@ export class TalerBankIntegrationHttpClient {
   }
 
   /**
-   * 
https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid
+   * FIXME: This is a misnomer!
    *
+   * 
https://docs.taler.net/core/api-bank-integration.html#post-$BANK_API_BASE_URL-withdrawal-operation-$wopid
    */
   async completeWithdrawalOperationById(
     woid: string,
diff --git a/packages/taler-util/src/types-taler-common.ts 
b/packages/taler-util/src/types-taler-common.ts
index ee7be5176..38fd51954 100644
--- a/packages/taler-util/src/types-taler-common.ts
+++ b/packages/taler-util/src/types-taler-common.ts
@@ -232,6 +232,7 @@ export const codecForTalerCommonConfigResponse =
       .allowExtra()
       .property("name", codecForString())
       .property("version", codecForString())
+      .allowExtra()
       .build("TalerCommonConfigResponse");
 
 export enum ExchangeProtocolVersion {
diff --git a/packages/taler-util/src/types-taler-corebank.ts 
b/packages/taler-util/src/types-taler-corebank.ts
index b9722c1f7..bf94112e3 100644
--- a/packages/taler-util/src/types-taler-corebank.ts
+++ b/packages/taler-util/src/types-taler-corebank.ts
@@ -61,6 +61,8 @@ export interface IntegrationConfig {
 
   // Name of the API.
   name: "taler-bank-integration";
+
+  implementation?: string;
 }
 
 export interface TalerCorebankConfigResponse {
@@ -673,6 +675,7 @@ export const codecForIntegrationBankConfig = (): 
Codec<IntegrationConfig> =>
     .property("version", codecForString())
     .property("currency", codecForString())
     .property("currency_specification", codecForCurrencySpecificiation())
+    .property("implementation", codecOptional(codecForString()))
     .build("TalerCorebankApi.IntegrationConfig");
 
 export const codecForCoreBankConfig = (): Codec<TalerCorebankConfigResponse> =>
diff --git a/packages/taler-util/src/types-taler-wallet-transactions.ts 
b/packages/taler-util/src/types-taler-wallet-transactions.ts
index fc7f12fd2..996a3190e 100644
--- a/packages/taler-util/src/types-taler-wallet-transactions.ts
+++ b/packages/taler-util/src/types-taler-wallet-transactions.ts
@@ -161,6 +161,8 @@ export interface TransactionState {
   minor?: TransactionMinorState;
 }
 
+export type TransactionStateWildcard = "*";
+
 export enum TransactionMajorState {
   // No state, only used when reporting transitions into the initial state
   None = "none",
diff --git a/packages/taler-util/src/types-taler-wallet.ts 
b/packages/taler-util/src/types-taler-wallet.ts
index 5291f304f..760c619e7 100644
--- a/packages/taler-util/src/types-taler-wallet.ts
+++ b/packages/taler-util/src/types-taler-wallet.ts
@@ -89,7 +89,11 @@ import {
   codecForMerchantContractTerms,
 } from "./types-taler-merchant.js";
 import { BackupRecovery } from "./types-taler-sync.js";
-import { TransactionState } from "./types-taler-wallet-transactions.js";
+import {
+  TransactionMajorState,
+  TransactionMinorState,
+  TransactionStateWildcard,
+} from "./types-taler-wallet-transactions.js";
 
 /**
  * Identifier for a transaction in the wallet.
@@ -3288,9 +3292,14 @@ export interface TestingWaitExchangeStateRequest {
   walletKycStatus?: ExchangeWalletKycStatus;
 }
 
+export interface TransactionStatePattern {
+  major: TransactionMajorState | TransactionStateWildcard;
+  minor?: TransactionMinorState | TransactionStateWildcard;
+}
+
 export interface TestingWaitTransactionRequest {
   transactionId: TransactionIdStr;
-  txState: TransactionState | TransactionState[];
+  txState: TransactionStatePattern | TransactionStatePattern[];
 }
 
 export interface TestingGetReserveHistoryRequest {
diff --git a/packages/taler-wallet-core/src/testing.ts 
b/packages/taler-wallet-core/src/testing.ts
index 5917c28e5..eeb439715 100644
--- a/packages/taler-wallet-core/src/testing.ts
+++ b/packages/taler-wallet-core/src/testing.ts
@@ -48,6 +48,7 @@ import {
   TransactionMajorState,
   TransactionMinorState,
   TransactionState,
+  TransactionStatePattern,
   TransactionType,
   URL,
   WithdrawTestBalanceRequest,
@@ -596,13 +597,23 @@ async function waitUntilTransactionPendingReady(
   });
 }
 
+function matchState(
+  st: TransactionState,
+  pat: TransactionStatePattern,
+): boolean {
+  return (
+    (pat.major === "*" || st.major === pat.major) &&
+    (pat.minor === "*" || st.minor === pat.minor)
+  );
+}
+
 /**
  * Wait until a transaction is in a particular state.
  */
 export async function waitTransactionState(
   wex: WalletExecutionContext,
   transactionId: string,
-  txState: TransactionState | TransactionState[],
+  txState: TransactionStatePattern | TransactionStatePattern[],
 ): Promise<void> {
   logger.info(
     `starting waiting for ${transactionId} to be in ${JSON.stringify(
@@ -616,19 +627,13 @@ export async function waitTransactionState(
       });
       if (Array.isArray(txState)) {
         for (const myState of txState) {
-          if (
-            tx.txState.major === myState.major &&
-            tx.txState.minor === myState.minor
-          ) {
+          if (matchState(tx.txState, myState)) {
             return true;
           }
         }
         return false;
       } else {
-        return (
-          tx.txState.major === txState.major &&
-          tx.txState.minor === txState.minor
-        );
+        return matchState(tx.txState, txState);
       }
     },
     filterNotification(notif) {
diff --git a/packages/taler-wallet-core/src/withdraw.ts 
b/packages/taler-wallet-core/src/withdraw.ts
index d469fa4b1..fd3bd476a 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -763,7 +763,7 @@ export function computeWithdrawalTransactionStatus(
   switch (wgRecord.status) {
     case WithdrawalGroupStatus.FailedBankAborted:
       return {
-        major: TransactionMajorState.Aborted,
+        major: TransactionMajorState.Failed,
       };
     case WithdrawalGroupStatus.Done:
       return {
@@ -1057,6 +1057,35 @@ async function processWithdrawalGroupBalanceKyc(
   }
 }
 
+/**
+ * Perform a simple transition of a withdrawal transaction
+ * from one state to another.
+ *
+ * If the transaction is in a different state, do not do anything.
+ */
+async function transitionSimple(
+  ctx: WithdrawTransactionContext,
+  from: WithdrawalGroupStatus,
+  to: WithdrawalGroupStatus,
+): Promise<void> {
+  await ctx.transition({}, async (rec) => {
+    switch (rec?.status) {
+      case from: {
+        rec.status = to;
+        return TransitionResult.transition(rec);
+      }
+    }
+    return TransitionResult.stay();
+  });
+}
+
+/**
+ * Handle state "dialog(proposed)" for a withdrawal transaction.
+ *
+ * In this state, we wait for the user to confirm
+ * and also monitor the state of the bank's withdrawal
+ * operation.
+ */
 async function processWithdrawalGroupDialogProposed(
   ctx: WithdrawTransactionContext,
   withdrawalGroup: WithdrawalGroupRecord,
@@ -1098,26 +1127,30 @@ async function processWithdrawalGroupDialogProposed(
     },
   );
 
-  // If the bank claims that the withdrawal operation is already
-  // pending, but we're still in DialogProposed, some other wallet
-  // must've completed the withdrawal, we're giving up.
-
   switch (resp.status) {
+    case HttpStatusCode.NotFound: {
+      // FIXME: Further inspect the error body
+      await transitionSimple(
+        ctx,
+        WithdrawalGroupStatus.DialogProposed,
+        WithdrawalGroupStatus.AbortedBank,
+      );
+      break;
+    }
     case HttpStatusCode.Ok: {
+      // If the bank claims that the withdrawal operation is already
+      // pending, but we're still in DialogProposed, some other wallet
+      // must've completed the withdrawal, we're giving up.
       const body = await readSuccessResponseJsonOrThrow(
         resp,
         codecForBankWithdrawalOperationStatus(),
       );
       if (body.status !== "pending") {
-        await ctx.transition({}, async (rec) => {
-          switch (rec?.status) {
-            case WithdrawalGroupStatus.DialogProposed: {
-              rec.status = WithdrawalGroupStatus.AbortedOtherWallet;
-              return TransitionResult.transition(rec);
-            }
-          }
-          return TransitionResult.stay();
-        });
+        await transitionSimple(
+          ctx,
+          WithdrawalGroupStatus.DialogProposed,
+          WithdrawalGroupStatus.AbortedOtherWallet,
+        );
       }
       break;
     }
@@ -2830,16 +2863,21 @@ async function registerReserveWithBank(
   });
 
   switch (httpResp.status) {
+    case HttpStatusCode.NotFound: {
+      // FIXME: Inspect particular status code
+      await transitionSimple(
+        ctx,
+        WithdrawalGroupStatus.PendingRegisteringBank,
+        WithdrawalGroupStatus.FailedBankAborted,
+      );
+      return TaskRunResult.progress();
+    }
     case HttpStatusCode.Conflict:
-      await ctx.transition({}, async (rec) => {
-        switch (rec?.status) {
-          case WithdrawalGroupStatus.PendingRegisteringBank: {
-            rec.status = WithdrawalGroupStatus.FailedBankAborted;
-            return TransitionResult.transition(rec);
-          }
-        }
-        return TransitionResult.stay();
-      });
+      await transitionSimple(
+        ctx,
+        WithdrawalGroupStatus.PendingRegisteringBank,
+        WithdrawalGroupStatus.FailedBankAborted,
+      );
       return TaskRunResult.progress();
   }
 
@@ -2935,32 +2973,24 @@ async function processBankRegisterReserve(
     cancellationToken: wex.cancellationToken,
   });
 
-  if (statusResp.status >= 400 && statusResp.status >= 499) {
-    let newSt: WithdrawalGroupStatus | undefined;
-    // FIXME: Consider looking at the exact status code
-    switch (statusResp.status) {
-      case HttpStatusCode.NotFound:
-        newSt = WithdrawalGroupStatus.FailedAbortingBank;
-        break;
-      case HttpStatusCode.Conflict:
-        newSt = WithdrawalGroupStatus.AbortedOtherWallet;
-        break;
-      default:
-        break;
-    }
-    if (newSt != null) {
-      // FIXME: Consider looking at the exact status code
-      await ctx.transition({}, async (rec) => {
-        switch (rec?.status) {
-          case WithdrawalGroupStatus.PendingRegisteringBank: {
-            rec.status = WithdrawalGroupStatus.FailedBankAborted;
-            return TransitionResult.transition(rec);
-          }
-        }
-        return TransitionResult.stay();
-      });
+  // FIXME: Consider looking at the exact taler error code
+  switch (statusResp.status) {
+    case HttpStatusCode.NotFound:
+      await transitionSimple(
+        ctx,
+        WithdrawalGroupStatus.PendingRegisteringBank,
+        WithdrawalGroupStatus.FailedBankAborted,
+      );
       return TaskRunResult.progress();
-    }
+    case HttpStatusCode.Conflict:
+      await transitionSimple(
+        ctx,
+        WithdrawalGroupStatus.PendingRegisteringBank,
+        WithdrawalGroupStatus.AbortedOtherWallet,
+      );
+      return TaskRunResult.progress();
+    default:
+      break;
   }
 
   const status = await readSuccessResponseJsonOrThrow(

-- 
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]