aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/operations
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-11-23 12:57:18 +0100
committerFlorian Dold <florian@dold.me>2023-11-23 12:57:18 +0100
commita0d746ad8d80490f9c2f1e017ff0c6a56b7d435c (patch)
treedc1f8ecebb07325c626ee06d1a7311faf09a0847 /packages/taler-wallet-core/src/operations
parent305c513c2bcc2b25fe57cf0ed9723781944f9f3f (diff)
wallet-core: implement balance flags for UI badges
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
-rw-r--r--packages/taler-wallet-core/src/operations/balance.ts120
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts23
2 files changed, 94 insertions, 49 deletions
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,