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: implement balanc


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: implement balance flags for UI badges
Date: Thu, 23 Nov 2023 12:57:19 +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 a0d746ad8 wallet-core: implement balance flags for UI badges
a0d746ad8 is described below

commit a0d746ad8d80490f9c2f1e017ff0c6a56b7d435c
Author: Florian Dold <florian@dold.me>
AuthorDate: Thu Nov 23 12:57:18 2023 +0100

    wallet-core: implement balance flags for UI badges
---
 packages/taler-util/src/wallet-types.ts            |  17 ++-
 packages/taler-wallet-core/src/db.ts               |  14 +++
 .../taler-wallet-core/src/operations/balance.ts    | 120 +++++++++++++++------
 .../taler-wallet-core/src/operations/pending.ts    |  23 ++--
 4 files changed, 123 insertions(+), 51 deletions(-)

diff --git a/packages/taler-util/src/wallet-types.ts 
b/packages/taler-util/src/wallet-types.ts
index 346528029..ba6f53cca 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -374,19 +374,31 @@ export const codecForAmountResponse = (): 
Codec<AmountResponse> =>
     .property("rawAmount", codecForAmountString())
     .build("AmountResponse");
 
+export enum BalanceFlag {
+  IncomingKyc = "incoming-kyc",
+  IncomingAml = "incoming-aml",
+  IncomingConfirmation = "incoming-confirmation",
+  OutgoingKyc = "outgoing-kyc",
+}
 export interface WalletBalance {
   scopeInfo: ScopeInfo;
   available: AmountString;
   pendingIncoming: AmountString;
   pendingOutgoing: AmountString;
 
-  // Does the balance for this currency have a pending
-  // transaction?
+  /**
+   * Does the balance for this currency have a pending
+   * transaction?
+   *
+   * FIXME: Represent as a flag!
+   */
   hasPendingTransactions: boolean;
 
   // Is there a pending transaction that would affect the balance
   // and requires user input?
   requiresUserInput: boolean;
+
+  flags: BalanceFlag[];
 }
 
 export const codecForScopeInfoGlobal = (): Codec<ScopeInfoGlobal> =>
@@ -481,6 +493,7 @@ export const codecForBalance = (): Codec<WalletBalance> =>
     .property("pendingIncoming", codecForAmountString())
     .property("pendingOutgoing", codecForAmountString())
     .property("requiresUserInput", codecForBoolean())
+    .property("flags", codecForAny()) // FIXME
     .build("Balance");
 
 export const codecForBalancesResponse = (): Codec<BalancesResponse> =>
diff --git a/packages/taler-wallet-core/src/db.ts 
b/packages/taler-wallet-core/src/db.ts
index 0cafae2a1..279b75bf5 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -19,6 +19,7 @@
  */
 import {
   Event,
+  GlobalIDB,
   IDBDatabase,
   IDBFactory,
   IDBObjectStore,
@@ -325,6 +326,14 @@ export enum WithdrawalGroupStatus {
   AbortedBank = 0x0503_0002,
 }
 
+/**
+ * Status range of nonfinal withdrawal groups.
+ */
+export const withdrawalGroupNonfinalRange = GlobalIDB.KeyRange.bound(
+  WithdrawalGroupStatus.PendingRegisteringBank,
+  WithdrawalGroupStatus.PendingAml,
+);
+
 /**
  * Extra info about a withdrawal that is used
  * with a bank-integrated withdrawal.
@@ -1686,6 +1695,11 @@ export enum DepositOperationStatus {
   Aborted = 0x0503_0000,
 }
 
+export const depositOperationNonfinalStatusRange = GlobalIDB.KeyRange.bound(
+  DepositOperationStatus.PendingDeposit,
+  DepositOperationStatus.PendingKyc,
+);
+
 export interface DepositTrackingInfo {
   // Raw wire transfer identifier of the deposit.
   wireTransferId: string;
diff --git a/packages/taler-wallet-core/src/operations/balance.ts 
b/packages/taler-wallet-core/src/operations/balance.ts
index 8034f78ea..6d396f6dd 100644
--- a/packages/taler-wallet-core/src/operations/balance.ts
+++ b/packages/taler-wallet-core/src/operations/balance.ts
@@ -54,6 +54,7 @@ import {
   AllowedExchangeInfo,
   AmountJson,
   Amounts,
+  BalanceFlag,
   BalancesResponse,
   canonicalizeBaseUrl,
   GetBalanceDetailRequest,
@@ -62,8 +63,11 @@ import {
   ScopeType,
 } from "@gnu-taler/taler-util";
 import {
+  depositOperationNonfinalStatusRange,
+  DepositOperationStatus,
   RefreshGroupRecord,
   WalletStoresV1,
+  withdrawalGroupNonfinalRange,
   WithdrawalGroupStatus,
 } from "../db.js";
 import { InternalWalletState } from "../internal-wallet-state.js";
@@ -81,6 +85,10 @@ interface WalletBalance {
   available: AmountJson;
   pendingIncoming: AmountJson;
   pendingOutgoing: AmountJson;
+  flagIncomingKyc: boolean;
+  flagIncomingAml: boolean;
+  flagIncomingConfirmation: boolean;
+  flagOutgoingKyc: boolean;
 }
 
 /**
@@ -109,6 +117,7 @@ export async function getBalancesInsideTransaction(
     coinAvailability: typeof WalletStoresV1.coinAvailability;
     refreshGroups: typeof WalletStoresV1.refreshGroups;
     withdrawalGroups: typeof WalletStoresV1.withdrawalGroups;
+    depositGroups: typeof WalletStoresV1.depositGroups;
   }>,
 ): Promise<BalancesResponse> {
   const balanceStore: Record<string, WalletBalance> = {};
@@ -124,6 +133,10 @@ export async function getBalancesInsideTransaction(
         available: Amounts.zeroOfCurrency(currency),
         pendingIncoming: Amounts.zeroOfCurrency(currency),
         pendingOutgoing: Amounts.zeroOfCurrency(currency),
+        flagIncomingAml: false,
+        flagIncomingConfirmation: false,
+        flagIncomingKyc: false,
+        flagOutgoingKyc: false,
       };
     }
     return balanceStore[currency];
@@ -145,42 +158,65 @@ export async function getBalancesInsideTransaction(
     ).amount;
   });
 
+  await tx.withdrawalGroups.indexes.byStatus
+    .iter(withdrawalGroupNonfinalRange)
+    .forEach((wgRecord) => {
+      const b = initBalance(
+        Amounts.currencyOf(wgRecord.denomsSel.totalWithdrawCost),
+      );
+      switch (wgRecord.status) {
+        case WithdrawalGroupStatus.AbortedBank:
+        case WithdrawalGroupStatus.AbortedExchange:
+        case WithdrawalGroupStatus.FailedAbortingBank:
+        case WithdrawalGroupStatus.FailedBankAborted:
+        case WithdrawalGroupStatus.Done:
+          // Does not count as pendingIncoming
+          return;
+        case WithdrawalGroupStatus.PendingReady:
+        case WithdrawalGroupStatus.AbortingBank:
+        case WithdrawalGroupStatus.PendingAml:
+          b.flagIncomingAml = true;
+          break;
+        case WithdrawalGroupStatus.PendingKyc:
+          b.flagIncomingKyc = true;
+          break;
+        case WithdrawalGroupStatus.PendingQueryingStatus:
+        case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
+        case WithdrawalGroupStatus.SuspendedReady:
+        case WithdrawalGroupStatus.SuspendedRegisteringBank:
+        case WithdrawalGroupStatus.SuspendedKyc:
+          b.flagIncomingKyc = true;
+          break;
+        case WithdrawalGroupStatus.SuspendedAbortingBank:
+        case WithdrawalGroupStatus.SuspendedAml:
+          b.flagIncomingAml = true;
+          break;
+        case WithdrawalGroupStatus.PendingRegisteringBank:
+        case WithdrawalGroupStatus.PendingWaitConfirmBank:
+          b.flagIncomingConfirmation = true;
+          break;
+        case WithdrawalGroupStatus.SuspendedQueryingStatus:
+          break;
+        default:
+          assertUnreachable(wgRecord.status);
+      }
+      b.pendingIncoming = Amounts.add(
+        b.pendingIncoming,
+        wgRecord.denomsSel.totalCoinValue,
+      ).amount;
+    });
+
   // FIXME: Use indexing to filter out final transactions.
-  await tx.withdrawalGroups.iter().forEach((wgRecord) => {
-    switch (wgRecord.status) {
-      case WithdrawalGroupStatus.AbortedBank:
-      case WithdrawalGroupStatus.AbortedExchange:
-      case WithdrawalGroupStatus.FailedAbortingBank:
-      case WithdrawalGroupStatus.FailedBankAborted:
-      case WithdrawalGroupStatus.Done:
-        // Does not count as pendingIncoming
-        return;
-      case WithdrawalGroupStatus.PendingReady:
-      case WithdrawalGroupStatus.AbortingBank:
-      case WithdrawalGroupStatus.PendingAml:
-      case WithdrawalGroupStatus.PendingKyc:
-      case WithdrawalGroupStatus.PendingQueryingStatus:
-      case WithdrawalGroupStatus.SuspendedWaitConfirmBank:
-      case WithdrawalGroupStatus.SuspendedReady:
-      case WithdrawalGroupStatus.SuspendedRegisteringBank:
-      case WithdrawalGroupStatus.SuspendedKyc:
-      case WithdrawalGroupStatus.SuspendedAbortingBank:
-      case WithdrawalGroupStatus.SuspendedAml:
-      case WithdrawalGroupStatus.PendingRegisteringBank:
-      case WithdrawalGroupStatus.PendingWaitConfirmBank:
-      case WithdrawalGroupStatus.SuspendedQueryingStatus:
-        break;
-      default:
-        assertUnreachable(wgRecord.status);
-    }
-    const b = initBalance(
-      Amounts.currencyOf(wgRecord.denomsSel.totalWithdrawCost),
-    );
-    b.pendingIncoming = Amounts.add(
-      b.pendingIncoming,
-      wgRecord.denomsSel.totalCoinValue,
-    ).amount;
-  });
+  await tx.depositGroups.indexes.byStatus
+    .iter(depositOperationNonfinalStatusRange)
+    .forEach((dgRecord) => {
+      const b = initBalance(Amounts.currencyOf(dgRecord.amount));
+      switch (dgRecord.operationStatus) {
+        case DepositOperationStatus.SuspendedKyc:
+        case DepositOperationStatus.PendingKyc:
+          b.flagOutgoingKyc = true;
+      }
+    });
 
   const balancesResponse: BalancesResponse = {
     balances: [],
@@ -190,6 +226,16 @@ export async function getBalancesInsideTransaction(
     .sort()
     .forEach((c) => {
       const v = balanceStore[c];
+      const flags: BalanceFlag[] = [];
+      if (v.flagIncomingAml) {
+        flags.push(BalanceFlag.IncomingAml);
+      }
+      if (v.flagIncomingKyc) {
+        flags.push(BalanceFlag.IncomingKyc);
+      }
+      if (v.flagIncomingConfirmation) {
+        flags.push(BalanceFlag.IncomingConfirmation);
+      }
       balancesResponse.balances.push({
         scopeInfo: {
           type: ScopeType.Global,
@@ -198,8 +244,11 @@ export async function getBalancesInsideTransaction(
         available: Amounts.stringify(v.available),
         pendingIncoming: Amounts.stringify(v.pendingIncoming),
         pendingOutgoing: Amounts.stringify(v.pendingOutgoing),
+        // FIXME: This field is basically not implemented, do we even need it?
         hasPendingTransactions: false,
+        // FIXME: This field is basically not implemented, do we even need it?
         requiresUserInput: false,
+        flags,
       });
     });
 
@@ -221,6 +270,7 @@ export async function getBalances(
       x.refreshGroups,
       x.purchases,
       x.withdrawalGroups,
+      x.depositGroups,
     ])
     .runReadOnly(async (tx) => {
       return getBalancesInsideTransaction(ws, tx);
diff --git a/packages/taler-wallet-core/src/operations/pending.ts 
b/packages/taler-wallet-core/src/operations/pending.ts
index 7641dcf33..282f84ad7 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -49,10 +49,12 @@ import {
   WalletStoresV1,
   WithdrawalGroupRecord,
   WithdrawalGroupStatus,
+  depositOperationNonfinalStatusRange,
   timestampAbsoluteFromDb,
   timestampOptionalAbsoluteFromDb,
   timestampPreciseFromDb,
   timestampPreciseToDb,
+  withdrawalGroupNonfinalRange,
 } from "../db.js";
 import { InternalWalletState } from "../internal-wallet-state.js";
 import {
@@ -205,12 +207,8 @@ export async function iterRecordsForWithdrawal(
 ): Promise<void> {
   let withdrawalGroupRecords: WithdrawalGroupRecord[];
   if (filter.onlyState === "nonfinal") {
-    const range = GlobalIDB.KeyRange.bound(
-      WithdrawalGroupStatus.PendingRegisteringBank,
-      WithdrawalGroupStatus.PendingAml,
-    );
     withdrawalGroupRecords = await tx.withdrawalGroups.indexes.byStatus.getAll(
-      range,
+      withdrawalGroupNonfinalRange,
     );
   } else {
     withdrawalGroupRecords =
@@ -238,7 +236,7 @@ async function gatherWithdrawalPending(
      * kyc pending operation don't give lifeness
      * since the user need to complete kyc procedure
      */
-    const userNeedToCompleteKYC = wsr.kycUrl !== undefined
+    const userNeedToCompleteKYC = wsr.kycUrl !== undefined;
     const now = AbsoluteTime.now();
     if (!opr) {
       opr = {
@@ -256,7 +254,7 @@ async function gatherWithdrawalPending(
         ws,
         opTag,
         timestampOptionalAbsoluteFromDb(opr.retryInfo?.nextRetry) ??
-        AbsoluteTime.now(),
+          AbsoluteTime.now(),
       ),
       givesLifeness: !userNeedToCompleteKYC,
       withdrawalGroupId: wsr.withdrawalGroupId,
@@ -276,10 +274,7 @@ export async function iterRecordsForDeposit(
   let dgs: DepositGroupRecord[];
   if (filter.onlyState === "nonfinal") {
     dgs = await tx.depositGroups.indexes.byStatus.getAll(
-      GlobalIDB.KeyRange.bound(
-        DepositOperationStatus.PendingDeposit,
-        DepositOperationStatus.PendingKyc,
-      ),
+      depositOperationNonfinalStatusRange,
     );
   } else {
     dgs = await tx.depositGroups.indexes.byStatus.getAll();
@@ -310,7 +305,7 @@ async function gatherDepositPending(
      * kyc pending operation don't give lifeness
      * since the user need to complete kyc procedure
      */
-    const userNeedToCompleteKYC = dg.kycInfo !== undefined
+    const userNeedToCompleteKYC = dg.kycInfo !== undefined;
     const opId = TaskIdentifiers.forDeposit(dg);
     const retryRecord = await tx.operationRetries.get(opId);
     const timestampDue =
@@ -554,7 +549,7 @@ async function gatherPeerPullInitiationPending(
        * kyc pending operation don't give lifeness
        * since the user need to complete kyc procedure
        */
-      const userNeedToCompleteKYC = pi.kycUrl !== undefined
+      const userNeedToCompleteKYC = pi.kycUrl !== undefined;
 
       resp.pendingOperations.push({
         type: PendingTaskType.PeerPullCredit,
@@ -712,7 +707,7 @@ async function gatherPeerPushCreditPending(
        * kyc pending operation don't give lifeness
        * since the user need to complete kyc procedure
        */
-      const userNeedToCompleteKYC = pi.kycUrl !== undefined
+      const userNeedToCompleteKYC = pi.kycUrl !== undefined;
 
       resp.pendingOperations.push({
         type: PendingTaskType.PeerPushCredit,

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