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: report more info


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: report more info about (missing) fees
Date: Wed, 27 Mar 2024 19:03:31 +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 30e5b7f6b wallet-core: report more info about (missing) fees
30e5b7f6b is described below

commit 30e5b7f6bf6fe7810f3fe0778e203b0e54d34b40
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Mar 27 19:03:26 2024 +0100

    wallet-core: report more info about (missing) fees
---
 packages/taler-util/src/wallet-types.ts         | 18 +++++++
 packages/taler-wallet-core/src/coinSelection.ts | 38 +++++++++++++++
 packages/taler-wallet-core/src/db.ts            | 10 ++++
 packages/taler-wallet-core/src/exchanges.ts     | 64 +++++++++++++++++++++++++
 4 files changed, 130 insertions(+)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 723e5a282..7b6da8a40 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -884,6 +884,11 @@ export interface PaymentInsufficientBalanceDetails {
       balanceReceiverAcceptable: AmountString;
       balanceReceiverDepositable: AmountString;
       maxEffectiveSpendAmount: AmountString;
+      /**
+       * Exchange doesn't have global fees configured for the relevant year,
+       * p2p payments aren't possible.
+       */
+      missingGlobalFees: boolean;
     };
   };
 }
@@ -1394,6 +1399,17 @@ export interface ExchangeListItem {
   exchangeUpdateStatus: ExchangeUpdateStatus;
   ageRestrictionOptions: number[];
 
+  /**
+   * P2P payments are disabled with this exchange
+   * (e.g. because no global fees are configured).
+   */
+  peerPaymentsDisabled: boolean;
+
+  /**
+   * Set to true if this exchange doesn't charge any fees.
+   */
+  noFees: boolean;
+
   scopeInfo: ScopeInfo | undefined;
 
   lastUpdateTimestamp: TalerPreciseTimestamp | undefined;
@@ -1473,6 +1489,8 @@ export const codecForExchangeListItem = (): 
Codec<ExchangeListItem> =>
     .property("scopeInfo", codecForScopeInfo())
     .property("lastUpdateErrorInfo", codecForAny())
     .property("lastUpdateTimestamp", codecOptional(codecForPreciseTimestamp))
+    .property("noFees", codecForBoolean())
+    .property("peerPaymentsDisabled", codecForBoolean())
     .build("ExchangeListItem");
 
 export const codecForExchangesListResponse = (): Codec<ExchangesListResponse> 
=>
diff --git a/packages/taler-wallet-core/src/coinSelection.ts 
b/packages/taler-wallet-core/src/coinSelection.ts
index 7c22f63db..cf323e586 100644
--- a/packages/taler-wallet-core/src/coinSelection.ts
+++ b/packages/taler-wallet-core/src/coinSelection.ts
@@ -36,6 +36,7 @@ import {
   checkLogicInvariant,
   CoinStatus,
   DenominationInfo,
+  ExchangeGlobalFees,
   ForcedCoinSel,
   InternationalizedString,
   j2s,
@@ -400,6 +401,16 @@ export async function reportInsufficientBalanceDetails(
     if (!exch.detailsPointer) {
       continue;
     }
+    let missingGlobalFees = false;
+    const exchWire = await getExchangeWireDetailsInTx(tx, exch.baseUrl);
+    if (!exchWire) {
+      missingGlobalFees = true;
+    } else {
+      const globalFees = getGlobalFees(exchWire);
+      if (!globalFees) {
+        missingGlobalFees = true;
+      }
+    }
     const exchDet = await getPaymentBalanceDetailsInTx(wex, tx, {
       restrictExchanges: {
         exchanges: [
@@ -431,6 +442,7 @@ export async function reportInsufficientBalanceDetails(
       maxEffectiveSpendAmount: Amounts.stringify(
         exchDet.maxEffectiveSpendAmount,
       ),
+      missingGlobalFees,
     };
   }
 
@@ -900,6 +912,24 @@ export function emptyTallyForPeerPayment(
   };
 }
 
+function getGlobalFees(
+  wireDetails: ExchangeWireDetails,
+): ExchangeGlobalFees | undefined {
+  const now = AbsoluteTime.now();
+  for (let gf of wireDetails.globalFees) {
+    const isActive = AbsoluteTime.isBetween(
+      now,
+      AbsoluteTime.fromProtocolTimestamp(gf.startDate),
+      AbsoluteTime.fromProtocolTimestamp(gf.endDate),
+    );
+    if (!isActive) {
+      continue;
+    }
+    return gf;
+  }
+  return undefined;
+}
+
 export async function selectPeerCoins(
   wex: WalletExecutionContext,
   req: PeerCoinSelectionRequest,
@@ -928,6 +958,14 @@ export async function selectPeerCoins(
         if (exch.detailsPointer?.currency !== currency) {
           continue;
         }
+        const exchWire = await getExchangeWireDetailsInTx(tx, exch.baseUrl);
+        if (!exchWire) {
+          continue;
+        }
+        const globalFees = getGlobalFees(exchWire);
+        if (!globalFees) {
+          continue;
+        }
         const candidatesRes = await selectPayCandidates(wex, tx, {
           instructedAmount,
           restrictExchanges: {
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index aad3b2d7b..92cf63ae1 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -688,6 +688,16 @@ export interface ExchangeEntryRecord {
    * receiving P2P payments.
    */
   currentMergeReserveRowId?: number;
+
+  /**
+   * Defaults to false.
+   */
+  peerPaymentsDisabled?: boolean;
+
+  /**
+   * Defaults to false.
+   */
+  noFees?: boolean;
 }
 
 export enum PlanchetStatus {
diff --git a/packages/taler-wallet-core/src/exchanges.ts 
b/packages/taler-wallet-core/src/exchanges.ts
index d501789a8..152bc76ce 100644
--- a/packages/taler-wallet-core/src/exchanges.ts
+++ b/packages/taler-wallet-core/src/exchanges.ts
@@ -309,6 +309,8 @@ async function makeExchangeListItem(
   return {
     exchangeBaseUrl: r.baseUrl,
     masterPub: exchangeDetails?.masterPublicKey,
+    noFees: r.noFees ?? false,
+    peerPaymentsDisabled: r.peerPaymentsDisabled ?? false,
     currency: exchangeDetails?.currency ?? r.presetCurrencyHint,
     exchangeUpdateStatus: getExchangeUpdateStatusFromRecord(r),
     exchangeEntryStatus: getExchangeEntryStatusFromRecord(r),
@@ -1177,6 +1179,61 @@ async function waitReadyExchange(
   }
 }
 
+function checkPeerPaymentsDisabled(
+  keysInfo: ExchangeKeysDownloadResult,
+): boolean {
+  const now = AbsoluteTime.now();
+  for (let gf of keysInfo.globalFees) {
+    const isActive = AbsoluteTime.isBetween(
+      now,
+      AbsoluteTime.fromProtocolTimestamp(gf.start_date),
+      AbsoluteTime.fromProtocolTimestamp(gf.end_date),
+    );
+    if (!isActive) {
+      continue;
+    }
+    return false;
+  }
+  // No global fees, we can't do p2p payments!
+  return true;
+}
+
+function checkNoFees(keysInfo: ExchangeKeysDownloadResult): boolean {
+  for (const gf of keysInfo.globalFees) {
+    if (!Amounts.isZero(gf.account_fee)) {
+      return false;
+    }
+    if (!Amounts.isZero(gf.history_fee)) {
+      return false;
+    }
+    if (!Amounts.isZero(gf.purse_fee)) {
+      return false;
+    }
+  }
+  for (const denom of keysInfo.currentDenominations) {
+    if (!Amounts.isZero(denom.fees.feeWithdraw)) {
+      return false;
+    }
+    if (!Amounts.isZero(denom.fees.feeDeposit)) {
+      return false;
+    }
+    if (!Amounts.isZero(denom.fees.feeRefund)) {
+      return false;
+    }
+    if (!Amounts.isZero(denom.fees.feeRefresh)) {
+      return false;
+    }
+  }
+  for (const wft of Object.values(keysInfo.wireFees)) {
+    for (const wf of wft) {
+      if (!Amounts.isZero(wf.wire_fee)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 /**
  * Update an exchange entry in the wallet's database
  * by fetching the /keys and /wire information.
@@ -1305,6 +1362,7 @@ export async function updateExchangeFromUrlHandler(
     keysInfo.globalFees,
     keysInfo.masterPublicKey,
   );
+
   if (keysInfo.baseUrl != exchangeBaseUrl) {
     logger.warn("exchange base URL mismatch");
     const errorDetail: TalerErrorDetail = makeErrorDetail(
@@ -1349,6 +1407,10 @@ export async function updateExchangeFromUrlHandler(
     }
   }
 
+  const now = AbsoluteTime.now();
+  let noFees = checkNoFees(keysInfo);
+  let peerPaymentsDisabled = checkPeerPaymentsDisabled(keysInfo);
+
   const updated = await wex.db.runReadWriteTx(
     [
       "exchanges",
@@ -1390,6 +1452,8 @@ export async function updateExchangeFromUrlHandler(
         wireInfo,
         ageMask,
       };
+      r.noFees = noFees;
+      r.peerPaymentsDisabled = peerPaymentsDisabled;
       r.tosCurrentEtag = tosDownload.tosEtag;
       if (existingDetails?.rowId) {
         newDetails.rowId = existingDetails.rowId;

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