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: tolerate zero am


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: tolerate zero amounts in peer-push-debit and peer-pull-credit check
Date: Mon, 18 Nov 2024 20:02:38 +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 a00ae494c wallet-core: tolerate zero amounts in peer-push-debit and 
peer-pull-credit check
a00ae494c is described below

commit a00ae494c4be0a66b2ce884cba87aec912cf0ecd
Author: Florian Dold <florian@dold.me>
AuthorDate: Mon Nov 18 20:02:27 2024 +0100

    wallet-core: tolerate zero amounts in peer-push-debit and peer-pull-credit 
check
---
 .../src/integrationtests/test-peer-to-peer-pull.ts | 33 ++++++++++--
 .../src/integrationtests/test-peer-to-peer-push.ts |  9 ++++
 packages/taler-wallet-core/src/coinSelection.ts    |  4 +-
 packages/taler-wallet-core/src/exchanges.ts        | 63 ++++------------------
 .../taler-wallet-core/src/pay-peer-pull-credit.ts  | 21 ++++----
 .../taler-wallet-core/src/pay-peer-push-debit.ts   | 21 +++++++-
 packages/taler-wallet-core/src/withdraw.ts         |  5 +-
 7 files changed, 81 insertions(+), 75 deletions(-)

diff --git 
a/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts 
b/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts
index 6ad07efed..145cbcee6 100644
--- a/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts
+++ b/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts
@@ -23,6 +23,7 @@ import {
   Duration,
   j2s,
   NotificationType,
+  ScopeType,
   TalerCorebankApiClient,
   TransactionMajorState,
   TransactionMinorState,
@@ -30,16 +31,16 @@ import {
   WalletNotification,
 } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import {
-  ExchangeService,
-  GlobalTestState,
-  WalletClient,
-} from "../harness/harness.js";
 import {
   createSimpleTestkudosEnvironmentV3,
   createWalletDaemonWithClient,
   withdrawViaBankV3,
 } from "../harness/environments.js";
+import {
+  ExchangeService,
+  GlobalTestState,
+  WalletClient,
+} from "../harness/harness.js";
 
 /**
  * Run test for basic, bank-integrated withdrawal and payment.
@@ -104,6 +105,28 @@ async function checkNormalPeerPull(
     ),
   );
 
+  const checkPullCreditResp1 = await wallet1.client.call(
+    WalletApiOperation.CheckPeerPullCredit,
+    {
+      amount: "TESTKUDOS:5" as AmountString,
+      exchangeBaseUrl: exchange.baseUrl,
+    },
+  );
+
+  t.assertDeepEqual(checkPullCreditResp1.amountRaw, "TESTKUDOS:5");
+
+  const checkPullCreditResp2 = await wallet1.client.call(
+    WalletApiOperation.CheckPeerPullCredit,
+    {
+      amount: "TESTKUDOS:0" as AmountString,
+      exchangeBaseUrl: exchange.baseUrl,
+    },
+  );
+
+  t.assertDeepEqual(checkPullCreditResp2.amountRaw, "TESTKUDOS:0");
+  t.assertDeepEqual(checkPullCreditResp2.amountEffective, "TESTKUDOS:0");
+  t.assertDeepEqual(checkPullCreditResp2.numCoins, 0);
+
   const resp = await wallet1.client.call(
     WalletApiOperation.InitiatePeerPullCredit,
     {
diff --git 
a/packages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts 
b/packages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts
index 953ea6088..fcddd1da4 100644
--- a/packages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts
+++ b/packages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts
@@ -89,6 +89,15 @@ export async function runPeerToPeerPushTest(t: 
GlobalTestState) {
     ),
   );
 
+  {
+    const checkRespSmall = await w1.walletClient.call(
+      WalletApiOperation.CheckPeerPushDebit,
+      {
+        amount: "TESTKUDOS:0" as AmountString,
+      },
+    );
+  }
+
   const checkResp0 = await w1.walletClient.call(
     WalletApiOperation.CheckPeerPushDebit,
     {
diff --git a/packages/taler-wallet-core/src/coinSelection.ts 
b/packages/taler-wallet-core/src/coinSelection.ts
index de051d52e..1d9ccf9ad 100644
--- a/packages/taler-wallet-core/src/coinSelection.ts
+++ b/packages/taler-wallet-core/src/coinSelection.ts
@@ -1204,7 +1204,9 @@ export async function selectPeerCoinsInTx(
   if (Amounts.isZero(instructedAmount)) {
     // Other parts of the code assume that we have at least
     // one coin to spend.
-    throw new Error("peer-to-peer payment with amount of zero not supported");
+    throw new Error(
+      "coin selection for peer-to-peer payment with amount of zero not 
supported",
+    );
   }
 
   const exchanges = await tx.exchanges.iter().toArray();
diff --git a/packages/taler-wallet-core/src/exchanges.ts 
b/packages/taler-wallet-core/src/exchanges.ts
index c4e6b81bf..7e95d234b 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -3650,58 +3650,11 @@ export async function checkExchangeInScopeTx(
 export async function getPreferredExchangeForCurrency(
   wex: WalletExecutionContext,
   currency: string,
+  restrictScope?: ScopeInfo,
 ): Promise<string | undefined> {
-  // Find an exchange with the matching currency.
-  // Prefer exchanges with the most recent withdrawal.
-  const url = await wex.db.runReadOnlyTx(
-    { storeNames: ["exchanges"] },
-    async (tx) => {
-      const exchanges = await tx.exchanges.iter().toArray();
-      let candidate = undefined;
-      for (const e of exchanges) {
-        if (e.detailsPointer?.currency !== currency) {
-          continue;
-        }
-        if (!candidate) {
-          candidate = e;
-          continue;
-        }
-        if (candidate.lastWithdrawal && !e.lastWithdrawal) {
-          continue;
-        }
-        const exchangeLastWithdrawal = timestampOptionalPreciseFromDb(
-          e.lastWithdrawal,
-        );
-        const candidateLastWithdrawal = timestampOptionalPreciseFromDb(
-          candidate.lastWithdrawal,
-        );
-        if (exchangeLastWithdrawal && candidateLastWithdrawal) {
-          if (
-            AbsoluteTime.cmp(
-              AbsoluteTime.fromPreciseTimestamp(exchangeLastWithdrawal),
-              AbsoluteTime.fromPreciseTimestamp(candidateLastWithdrawal),
-            ) > 0
-          ) {
-            candidate = e;
-          }
-        }
-      }
-      if (candidate) {
-        return candidate.baseUrl;
-      }
-      return undefined;
-    },
-  );
-  return url;
-}
-
-/**
- * Find a preferred exchange based on when we withdrew last from this exchange.
- */
-export async function getPreferredExchangeForScope(
-  wex: WalletExecutionContext,
-  scope: ScopeInfo,
-): Promise<string | undefined> {
+  if (restrictScope) {
+    checkLogicInvariant(restrictScope.currency === currency);
+  }
   // Find an exchange with the matching currency.
   // Prefer exchanges with the most recent withdrawal.
   const url = await wex.db.runReadOnlyTx(
@@ -3717,11 +3670,13 @@ export async function getPreferredExchangeForScope(
       const exchanges = await tx.exchanges.iter().toArray();
       let candidate = undefined;
       for (const e of exchanges) {
-        const inScope = await checkExchangeInScopeTx(wex, tx, e.baseUrl, 
scope);
-        if (!inScope) {
+        if (e.detailsPointer?.currency !== currency) {
           continue;
         }
-        if (e.detailsPointer?.currency !== scope.currency) {
+        const inScope =
+          !restrictScope ||
+          (await checkExchangeInScopeTx(wex, tx, e.baseUrl, restrictScope));
+        if (!inScope) {
           continue;
         }
         if (!candidate) {
diff --git a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts 
b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
index a92d8e764..e5a9d9675 100644
--- a/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-pull-credit.ts
@@ -93,7 +93,6 @@ import {
   checkIncomingAmountLegalUnderKycBalanceThreshold,
   fetchFreshExchange,
   getPreferredExchangeForCurrency,
-  getPreferredExchangeForScope,
   getScopeForAllExchanges,
   handleStartExchangeWalletKyc,
 } from "./exchanges.js";
@@ -1356,6 +1355,8 @@ export async function internalCheckPeerPullCredit(
     `checking peer push debit for ${Amounts.stringify(instructedAmount)}`,
   );
 
+  // FIXME: Create helper to avoid code duplication with pull credit initiation
+
   let restrictScope: ScopeInfo;
   if (req.restrictScope) {
     restrictScope = req.restrictScope;
@@ -1371,14 +1372,11 @@ export async function internalCheckPeerPullCredit(
 
   logger.trace("checking peer-pull-credit fees");
 
-  let exchangeUrl: string | undefined;
-  if (req.exchangeBaseUrl) {
-    exchangeUrl = req.exchangeBaseUrl;
-  } else if (req.restrictScope) {
-    exchangeUrl = await getPreferredExchangeForScope(wex, req.restrictScope);
-  } else {
-    exchangeUrl = await getPreferredExchangeForCurrency(wex, currency);
-  }
+  const exchangeUrl = await getPreferredExchangeForCurrency(
+    wex,
+    restrictScope.currency,
+    restrictScope,
+  );
 
   if (!exchangeUrl) {
     throw Error("no exchange found for initiating a peer pull payment");
@@ -1392,10 +1390,9 @@ export async function internalCheckPeerPullCredit(
     Amounts.parseOrThrow(req.amount),
     undefined,
   );
+
   if (wi.selectedDenoms.selectedDenoms.length === 0) {
-    throw Error(
-      `unable to check pull payment from ${exchangeUrl}, can't select 
denominations for instructed amount (${req.amount}`,
-    );
+    logger.warn(`Amount for peer-pull-credit payment too low`);
   }
 
   logger.trace(`got withdrawal info`);
diff --git a/packages/taler-wallet-core/src/pay-peer-push-debit.ts 
b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
index 31d320259..fb2c98173 100644
--- a/packages/taler-wallet-core/src/pay-peer-push-debit.ts
+++ b/packages/taler-wallet-core/src/pay-peer-push-debit.ts
@@ -82,7 +82,10 @@ import {
   timestampProtocolFromDb,
   timestampProtocolToDb,
 } from "./db.js";
-import { getScopeForAllExchanges } from "./exchanges.js";
+import {
+  getPreferredExchangeForCurrency,
+  getScopeForAllExchanges,
+} from "./exchanges.js";
 import {
   codecForExchangePurseStatus,
   getTotalPeerPaymentCost,
@@ -468,6 +471,22 @@ async function internalCheckPeerPushDebit(
       url: req.exchangeBaseUrl,
     };
   }
+  if (Amounts.isZero(req.amount)) {
+    const exchangeBaseUrl = await getPreferredExchangeForCurrency(
+      wex,
+      currency,
+      restrictScope,
+    );
+    if (!exchangeBaseUrl) {
+      throw Error("no exchange found for payment");
+    }
+    return {
+      amountEffective: req.amount,
+      amountRaw: req.amount,
+      exchangeBaseUrl,
+      maxExpirationDate: TalerProtocolTimestamp.never(),
+    };
+  }
   const coinSelRes = await selectPeerCoins(wex, {
     instructedAmount,
     restrictScope,
diff --git a/packages/taler-wallet-core/src/withdraw.ts 
b/packages/taler-wallet-core/src/withdraw.ts
index 080e915d0..d1ed995a3 100644
--- a/packages/taler-wallet-core/src/withdraw.ts
+++ b/packages/taler-wallet-core/src/withdraw.ts
@@ -166,7 +166,7 @@ import {
   fetchFreshExchange,
   getExchangePaytoUri,
   getExchangeWireDetailsInTx,
-  getPreferredExchangeForScope,
+  getPreferredExchangeForCurrency,
   getScopeForAllExchanges,
   handleStartExchangeWalletKyc,
   listExchanges,
@@ -4021,8 +4021,9 @@ export async function 
internalGetWithdrawalDetailsForAmount(
   if (req.exchangeBaseUrl) {
     exchangeBaseUrl = req.exchangeBaseUrl;
   } else if (req.restrictScope) {
-    exchangeBaseUrl = await getPreferredExchangeForScope(
+    exchangeBaseUrl = await getPreferredExchangeForCurrency(
       wex,
+      req.restrictScope.currency,
       req.restrictScope,
     );
   }

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