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,harness: introduc


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core,harness: introduce reserveIsReady flag, test tx lifeycle
Date: Mon, 13 Feb 2023 13:15:59 +0100

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 22cb8adaa wallet-core,harness: introduce reserveIsReady flag, test tx 
lifeycle
22cb8adaa is described below

commit 22cb8adaa6d9584ad7638b9019b6d0c3eb7158bf
Author: Florian Dold <florian@dold.me>
AuthorDate: Mon Feb 13 13:15:47 2023 +0100

    wallet-core,harness: introduce reserveIsReady flag, test tx lifeycle
---
 packages/taler-harness/src/harness/harness.ts      | 47 ++++++++---
 packages/taler-harness/src/harness/helpers.ts      | 25 +++++-
 .../taler-harness/src/integrationtests/test-kyc.ts |  2 +-
 .../test-withdrawal-bank-integrated.ts             | 96 +++++++++++++++++++---
 packages/taler-util/src/notifications.ts           | 22 ++++-
 packages/taler-util/src/transactions-types.ts      | 10 +++
 .../src/operations/transactions.ts                 |  7 ++
 .../taler-wallet-core/src/operations/withdraw.ts   | 24 +++++-
 8 files changed, 200 insertions(+), 33 deletions(-)

diff --git a/packages/taler-harness/src/harness/harness.ts 
b/packages/taler-harness/src/harness/harness.ts
index 275592091..0b7ba14cf 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -1169,6 +1169,29 @@ export class ExchangeService implements 
ExchangeServiceInterface {
     return !!this.exchangeWirewatchProc || !!this.exchangeHttpProc;
   }
 
+  /**
+   * Stop the wirewatch service (which runs by default).
+   *
+   * Useful for some tests.
+   */
+  async stopWirewatch(): Promise<void> {
+    const wirewatch = this.exchangeWirewatchProc;
+    if (wirewatch) {
+      wirewatch.proc.kill("SIGTERM");
+      await wirewatch.wait();
+      this.exchangeWirewatchProc = undefined;
+    }
+  }
+
+  async startWirewatch(): Promise<void> {
+    const wirewatch = this.exchangeWirewatchProc;
+    if (wirewatch) {
+      logger.warn("wirewatch already running");
+    } else {
+      this.internalCreateWirewatchProc();
+    }
+  }
+
   async stop(): Promise<void> {
     const wirewatch = this.exchangeWirewatchProc;
     if (wirewatch) {
@@ -1332,6 +1355,19 @@ export class ExchangeService implements 
ExchangeServiceInterface {
     );
   }
 
+  private internalCreateWirewatchProc() {
+    this.exchangeWirewatchProc = this.globalState.spawnService(
+      "taler-exchange-wirewatch",
+      [
+        "-c",
+        this.configFilename,
+        "--longpoll-timeout=5s",
+        ...this.timetravelArgArr,
+      ],
+      `exchange-wirewatch-${this.name}`,
+    );
+  }
+
   async start(): Promise<void> {
     if (this.isRunning()) {
       throw Error("exchange is already running");
@@ -1360,16 +1396,7 @@ export class ExchangeService implements 
ExchangeServiceInterface {
       `exchange-crypto-rsa-${this.name}`,
     );
 
-    this.exchangeWirewatchProc = this.globalState.spawnService(
-      "taler-exchange-wirewatch",
-      [
-        "-c",
-        this.configFilename,
-        "--longpoll-timeout=5s",
-        ...this.timetravelArgArr,
-      ],
-      `exchange-wirewatch-${this.name}`,
-    );
+    this.internalCreateWirewatchProc();
 
     this.exchangeHttpProc = this.globalState.spawnService(
       "taler-exchange-httpd",
diff --git a/packages/taler-harness/src/harness/helpers.ts 
b/packages/taler-harness/src/harness/helpers.ts
index 4c2ca80a7..ad77ce6ca 100644
--- a/packages/taler-harness/src/harness/helpers.ts
+++ b/packages/taler-harness/src/harness/helpers.ts
@@ -209,7 +209,7 @@ export async function createSimpleTestkudosEnvironmentV2(
   t: GlobalTestState,
   coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => x("TESTKUDOS")),
   opts: EnvOptions = {},
-): Promise<SimpleTestEnvironment> {
+): Promise<SimpleTestEnvironmentNg> {
   const db = await setupDb(t);
 
   const bank = await BankService.create(t, {
@@ -293,15 +293,32 @@ export async function createSimpleTestkudosEnvironmentV2(
     ),
   });
 
-  console.log("setup done!");
+  const walletService = new WalletService(t, {
+    name: "wallet",
+    useInMemoryDb: true,
+  });
+  await walletService.start();
+  await walletService.pingUntilAvailable();
 
-  const wallet = new WalletCli(t);
+  const walletClient = new WalletClient({
+    unixPath: walletService.socketPath,
+    onNotification(n) {
+      console.log("got notification", n);
+    },
+  });
+  await walletClient.connect();
+  await walletClient.client.call(WalletApiOperation.InitWallet, {
+    skipDefaults: true,
+  });
+
+  console.log("setup done!");
 
   return {
     commonDb: db,
     exchange,
     merchant,
-    wallet,
+    walletClient,
+    walletService,
     bank,
     exchangeBankAccount,
   };
diff --git a/packages/taler-harness/src/integrationtests/test-kyc.ts 
b/packages/taler-harness/src/integrationtests/test-kyc.ts
index b08db66f7..490673cee 100644
--- a/packages/taler-harness/src/integrationtests/test-kyc.ts
+++ b/packages/taler-harness/src/integrationtests/test-kyc.ts
@@ -307,7 +307,7 @@ export async function runKycTest(t: GlobalTestState) {
   // Withdraw
 
   const kycNotificationCond = walletClient.waitForNotificationCond((x) => {
-    if (x.type === NotificationType.WithdrawalKycRequested) {
+    if (x.type === NotificationType.WithdrawalGroupKycRequested) {
       return x;
     }
     return false;
diff --git 
a/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
 
b/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
index dc7298e5d..c98c18db5 100644
--- 
a/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
+++ 
b/packages/taler-harness/src/integrationtests/test-withdrawal-bank-integrated.ts
@@ -18,13 +18,13 @@
  * Imports.
  */
 import { GlobalTestState } from "../harness/harness.js";
-import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
+import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js";
 import {
   WalletApiOperation,
   BankApi,
   BankAccessApi,
 } from "@gnu-taler/taler-wallet-core";
-import { j2s } from "@gnu-taler/taler-util";
+import { j2s, NotificationType, TransactionType, WithdrawalType } from 
"@gnu-taler/taler-util";
 
 /**
  * Run test for basic, bank-integrated withdrawal.
@@ -32,7 +32,8 @@ import { j2s } from "@gnu-taler/taler-util";
 export async function runWithdrawalBankIntegratedTest(t: GlobalTestState) {
   // Set up test environment
 
-  const { wallet, bank, exchange } = await createSimpleTestkudosEnvironment(t);
+  const { walletClient, bank, exchange } =
+    await createSimpleTestkudosEnvironmentV2(t);
 
   // Create a withdrawal operation
 
@@ -45,46 +46,117 @@ export async function runWithdrawalBankIntegratedTest(t: 
GlobalTestState) {
 
   // Hand it to the wallet
 
-  const r1 = await wallet.client.call(
+  const r1 = await walletClient.client.call(
     WalletApiOperation.GetWithdrawalDetailsForUri,
     {
       talerWithdrawUri: wop.taler_withdraw_uri,
     },
   );
 
-  await wallet.runPending();
-
   // Withdraw
 
-  const r2 = await wallet.client.call(
+  const withdrawalBankConfirmedCond = walletClient.waitForNotificationCond(
+    (x) => {
+      return x.type === NotificationType.WithdrawalGroupBankConfirmed;
+    },
+  );
+
+  const withdrawalFinishedCond = walletClient.waitForNotificationCond((x) => {
+    return x.type === NotificationType.WithdrawGroupFinished;
+  });
+
+  const withdrawalReserveReadyCond = walletClient.waitForNotificationCond(
+    (x) => {
+      return x.type === NotificationType.WithdrawalGroupReserveReady;
+    },
+  );
+
+  const r2 = await walletClient.client.call(
     WalletApiOperation.AcceptBankIntegratedWithdrawal,
     {
       exchangeBaseUrl: exchange.baseUrl,
       talerWithdrawUri: wop.taler_withdraw_uri,
     },
   );
+
   // Do it twice to check idempotency
-  const r3 = await wallet.client.call(
+  const r3 = await walletClient.client.call(
     WalletApiOperation.AcceptBankIntegratedWithdrawal,
     {
       exchangeBaseUrl: exchange.baseUrl,
       talerWithdrawUri: wop.taler_withdraw_uri,
     },
   );
-  await wallet.runPending();
+
+  await exchange.stopWirewatch();
+
+  // Check status before withdrawal is confirmed by bank.
+  {
+    const txn = await walletClient.client.call(
+      WalletApiOperation.GetTransactions,
+      {},
+    );
+    console.log("transactions before confirmation:", j2s(txn));
+    const tx0 = txn.transactions[0];
+    t.assertTrue(tx0.type === TransactionType.Withdrawal);
+    t.assertTrue(tx0.withdrawalDetails.type === 
WithdrawalType.TalerBankIntegrationApi);
+    t.assertTrue(tx0.withdrawalDetails.confirmed === false);
+    t.assertTrue(tx0.withdrawalDetails.reserveIsReady === false);
+  }
 
   // Confirm it
 
   await BankApi.confirmWithdrawalOperation(bank, user, wop);
 
-  await wallet.runUntilDone();
+  await withdrawalBankConfirmedCond;
+
+  // Check status after withdrawal is confirmed by bank,
+  // but before funds are wired to the exchange.
+  {
+    const txn = await walletClient.client.call(
+      WalletApiOperation.GetTransactions,
+      {},
+    );
+    console.log("transactions after confirmation:", j2s(txn));
+    const tx0 = txn.transactions[0];
+    t.assertTrue(tx0.type === TransactionType.Withdrawal);
+    t.assertTrue(tx0.withdrawalDetails.type === 
WithdrawalType.TalerBankIntegrationApi);
+    t.assertTrue(tx0.withdrawalDetails.confirmed === true);
+    t.assertTrue(tx0.withdrawalDetails.reserveIsReady === false);
+  }
+
+  await exchange.startWirewatch();
+
+  await withdrawalReserveReadyCond;
+
+  // Check status after funds were wired.
+  {
+    const txn = await walletClient.client.call(
+      WalletApiOperation.GetTransactions,
+      {},
+    );
+    console.log("transactions after reserve ready:", j2s(txn));
+    const tx0 = txn.transactions[0];
+    t.assertTrue(tx0.type === TransactionType.Withdrawal);
+    t.assertTrue(tx0.withdrawalDetails.type === 
WithdrawalType.TalerBankIntegrationApi);
+    t.assertTrue(tx0.withdrawalDetails.confirmed === true);
+    t.assertTrue(tx0.withdrawalDetails.reserveIsReady === true);
+  }
+
+  await withdrawalFinishedCond;
 
   // Check balance
 
-  const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
+  const balResp = await walletClient.client.call(
+    WalletApiOperation.GetBalances,
+    {},
+  );
   t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available);
 
-  const txn = await wallet.client.call(WalletApiOperation.GetTransactions, {});
+  const txn = await walletClient.client.call(
+    WalletApiOperation.GetTransactions,
+    {},
+  );
   console.log(`transactions: ${j2s(txn)}`);
 }
 
diff --git a/packages/taler-util/src/notifications.ts 
b/packages/taler-util/src/notifications.ts
index 9d3ca32b0..823c4130d 100644
--- a/packages/taler-util/src/notifications.ts
+++ b/packages/taler-util/src/notifications.ts
@@ -62,7 +62,9 @@ export enum NotificationType {
   PendingOperationProcessed = "pending-operation-processed",
   ProposalRefused = "proposal-refused",
   ReserveRegisteredWithBank = "reserve-registered-with-bank",
-  WithdrawalKycRequested = "withdrawal-kyc-requested",
+  WithdrawalGroupKycRequested = "withdrawal-group-kyc-requested",
+  WithdrawalGroupBankConfirmed = "withdrawal-group-bank-confirmed",
+  WithdrawalGroupReserveReady = "withdrawal-group-reserve-ready",
   DepositOperationError = "deposit-operation-error",
 }
 
@@ -118,12 +120,22 @@ export interface RefreshMeltedNotification {
   type: NotificationType.RefreshMelted;
 }
 
-export interface WithdrawalKycRequested {
-  type: NotificationType.WithdrawalKycRequested;
+export interface WithdrawalGroupKycRequested {
+  type: NotificationType.WithdrawalGroupKycRequested;
   transactionId: string;
   kycUrl: string;
 }
 
+export interface WithdrawalGroupBankConfirmed {
+  type: NotificationType.WithdrawalGroupBankConfirmed;
+  transactionId: string;
+}
+
+export interface WithdrawalGroupReserveReady {
+  type: NotificationType.WithdrawalGroupReserveReady;
+  transactionId: string;
+}
+
 export interface RefreshRevealedNotification {
   type: NotificationType.RefreshRevealed;
 }
@@ -293,4 +305,6 @@ export type WalletNotification =
   | ReserveRegisteredWithBankNotification
   | ReserveNotYetFoundNotification
   | PayOperationSuccessNotification
-  | WithdrawalKycRequested;
+  | WithdrawalGroupKycRequested
+  | WithdrawalGroupBankConfirmed
+  | WithdrawalGroupReserveReady;
diff --git a/packages/taler-util/src/transactions-types.ts 
b/packages/taler-util/src/transactions-types.ts
index 7562b5884..d108d1a77 100644
--- a/packages/taler-util/src/transactions-types.ts
+++ b/packages/taler-util/src/transactions-types.ts
@@ -167,6 +167,11 @@ interface WithdrawalDetailsForManualTransfer {
 
   // Public key of the reserve
   reservePub: string;
+
+  /**
+   * Is the reserve ready for withdrawal?
+   */
+  reserveIsReady: boolean;
 }
 
 interface WithdrawalDetailsForTalerBankIntegrationApi {
@@ -187,6 +192,11 @@ interface WithdrawalDetailsForTalerBankIntegrationApi {
 
   // Public key of the reserve
   reservePub: string;
+
+  /**
+   * Is the reserve ready for withdrawal?
+   */
+  reserveIsReady: boolean;
 }
 
 // This should only be used for actual withdrawals
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts 
b/packages/taler-wallet-core/src/operations/transactions.ts
index 9951fd6b2..c1b82f9c9 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -55,6 +55,7 @@ import {
   PeerPushPaymentInitiationStatus,
   PeerPullPaymentIncomingStatus,
   TransactionStatus,
+  WithdrawalGroupStatus,
 } from "../db.js";
 import { InternalWalletState } from "../internal-wallet-state.js";
 import { assertUnreachable } from "../util/assertUnreachable.js";
@@ -515,6 +516,9 @@ function buildTransactionForBankIntegratedWithdraw(
       confirmed: wsr.wgInfo.bankInfo.timestampBankConfirmed ? true : false,
       reservePub: wsr.reservePub,
       bankConfirmationUrl: wsr.wgInfo.bankInfo.confirmUrl,
+      reserveIsReady:
+        wsr.status === WithdrawalGroupStatus.Finished ||
+        wsr.status === WithdrawalGroupStatus.Ready,
     },
     exchangeBaseUrl: wsr.exchangeBaseUrl,
     extendedStatus: wsr.timestampFinish
@@ -558,6 +562,9 @@ function buildTransactionForManualWithdraw(
       type: WithdrawalType.ManualTransfer,
       reservePub: withdrawalGroup.reservePub,
       exchangePaytoUris,
+      reserveIsReady:
+        withdrawalGroup.status === WithdrawalGroupStatus.Finished ||
+        withdrawalGroup.status === WithdrawalGroupStatus.Ready,
     },
     exchangeBaseUrl: withdrawalGroup.exchangeBaseUrl,
     extendedStatus: withdrawalGroup.timestampFinish
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts 
b/packages/taler-wallet-core/src/operations/withdraw.ts
index 28754c77e..bcc8600c7 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -987,6 +987,14 @@ async function queryReserve(
       await tx.withdrawalGroups.put(wg);
     });
 
+  ws.notify({
+    type: NotificationType.WithdrawalGroupReserveReady,
+    transactionId: makeTransactionId(
+      TransactionType.Withdrawal,
+      withdrawalGroupId,
+    ),
+  });
+
   return { ready: true };
 }
 
@@ -1250,7 +1258,12 @@ export async function processWithdrawalGroup(
 
   if (numKycRequired > 0) {
     if (kycInfo) {
-      await checkWithdrawalKycStatus(ws, withdrawalGroup, kycInfo, 
"individual");
+      await checkWithdrawalKycStatus(
+        ws,
+        withdrawalGroup,
+        kycInfo,
+        "individual",
+      );
       return {
         type: OperationAttemptResultType.Pending,
         result: undefined,
@@ -1310,7 +1323,7 @@ export async function checkWithdrawalKycStatus(
     const kycStatus = await kycStatusReq.json();
     logger.info(`kyc status: ${j2s(kycStatus)}`);
     ws.notify({
-      type: NotificationType.WithdrawalKycRequested,
+      type: NotificationType.WithdrawalGroupKycRequested,
       kycUrl: kycStatus.kyc_url,
       transactionId: makeTransactionId(
         TransactionType.Withdrawal,
@@ -1794,6 +1807,13 @@ async function processReserveBankStatus(
         const now = AbsoluteTime.toTimestamp(AbsoluteTime.now());
         r.wgInfo.bankInfo.timestampBankConfirmed = now;
         r.status = WithdrawalGroupStatus.QueryingStatus;
+        ws.notify({
+          type: NotificationType.WithdrawalGroupBankConfirmed,
+          transactionId: makeTransactionId(
+            TransactionType.Withdrawal,
+            r.withdrawalGroupId,
+          ),
+        });
       } else {
         logger.info("withdrawal: transfer not yet confirmed by bank");
         r.wgInfo.bankInfo.confirmUrl = status.confirm_transfer_url;

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