summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-03-07 11:33:41 +0100
committerFlorian Dold <florian@dold.me>2024-03-07 11:33:41 +0100
commit5ca3c7878da9a495c67ea7faed91c8dbce04e603 (patch)
tree2a194e94bba1415f4504f119bd3beb0ad33d4c81 /packages/taler-wallet-core
parent466e2b7643692aa6b7f76a193b84775008e17350 (diff)
downloadwallet-core-5ca3c7878da9a495c67ea7faed91c8dbce04e603.tar.gz
wallet-core-5ca3c7878da9a495c67ea7faed91c8dbce04e603.tar.bz2
wallet-core-5ca3c7878da9a495c67ea7faed91c8dbce04e603.zip
wallet-core: simplify/improve insufficient balance details computation
Diffstat (limited to 'packages/taler-wallet-core')
-rw-r--r--packages/taler-wallet-core/src/balance.ts167
-rw-r--r--packages/taler-wallet-core/src/coinSelection.ts10
2 files changed, 66 insertions, 111 deletions
diff --git a/packages/taler-wallet-core/src/balance.ts b/packages/taler-wallet-core/src/balance.ts
index 4c58814a1..26d348b39 100644
--- a/packages/taler-wallet-core/src/balance.ts
+++ b/packages/taler-wallet-core/src/balance.ts
@@ -59,8 +59,6 @@ import {
assertUnreachable,
BalanceFlag,
BalancesResponse,
- canonicalizeBaseUrl,
- checkLogicInvariant,
GetBalanceDetailRequest,
Logger,
parsePaytoUri,
@@ -487,100 +485,6 @@ export interface AcceptableExchanges {
depositableExchanges: string[];
}
-/**
- * Get all exchanges that are acceptable for a particular payment.
- */
-async function getAcceptableExchangeBaseUrlsInTx(
- wex: WalletExecutionContext,
- tx: WalletDbReadOnlyTransaction<["exchanges", "exchangeDetails"]>,
- req: PaymentRestrictionsForBalance,
-): Promise<AcceptableExchanges> {
- const acceptableExchangeUrls = new Set<string>();
- const depositableExchangeUrls = new Set<string>();
- // FIXME: We should have a DB index to look up all exchanges
- // for a particular auditor ...
-
- const canonExchanges = new Set<string>();
- const canonAuditors = new Set<string>();
-
- if (req.restrictExchanges) {
- for (const exchangeHandle of req.restrictExchanges.exchanges) {
- const normUrl = canonicalizeBaseUrl(exchangeHandle.exchangeBaseUrl);
- canonExchanges.add(normUrl);
- }
-
- for (const auditorHandle of req.restrictExchanges.auditors) {
- const normUrl = canonicalizeBaseUrl(auditorHandle.auditorBaseUrl);
- canonAuditors.add(normUrl);
- }
- }
-
- await tx.exchanges.iter().forEachAsync(async (exchange) => {
- const dp = exchange.detailsPointer;
- if (!dp) {
- return;
- }
- const { currency, masterPublicKey } = dp;
- const exchangeDetails = await tx.exchangeDetails.indexes.byPointer.get([
- exchange.baseUrl,
- currency,
- masterPublicKey,
- ]);
- if (!exchangeDetails) {
- return;
- }
-
- let acceptable = false;
-
- if (canonExchanges.has(exchange.baseUrl)) {
- acceptableExchangeUrls.add(exchange.baseUrl);
- acceptable = true;
- }
- for (const exchangeAuditor of exchangeDetails.auditors) {
- if (canonAuditors.has(exchangeAuditor.auditor_url)) {
- acceptableExchangeUrls.add(exchange.baseUrl);
- acceptable = true;
- break;
- }
- }
-
- if (!acceptable) {
- return;
- }
- // FIXME: Also consider exchange and auditor public key
- // instead of just base URLs?
-
- let wireMethodSupported = false;
-
- if (req.restrictWireMethods) {
- for (const acc of exchangeDetails.wireInfo.accounts) {
- const pp = parsePaytoUri(acc.payto_uri);
- checkLogicInvariant(!!pp);
- for (const wm of req.restrictWireMethods) {
- if (pp.targetType === wm) {
- wireMethodSupported = true;
- break;
- }
- if (wireMethodSupported) {
- break;
- }
- }
- }
- } else {
- wireMethodSupported = true;
- }
-
- acceptableExchangeUrls.add(exchange.baseUrl);
- if (wireMethodSupported) {
- depositableExchangeUrls.add(exchange.baseUrl);
- }
- });
- return {
- acceptableExchanges: [...acceptableExchangeUrls],
- depositableExchanges: [...depositableExchangeUrls],
- };
-}
-
export interface PaymentBalanceDetails {
/**
* Balance of type "available" (see balance.ts for definition).
@@ -648,8 +552,6 @@ export async function getPaymentBalanceDetailsInTx(
>,
req: PaymentRestrictionsForBalance,
): Promise<PaymentBalanceDetails> {
- const acceptability = await getAcceptableExchangeBaseUrlsInTx(wex, tx, req);
-
const d: PaymentBalanceDetails = {
balanceAvailable: Amounts.zeroOfCurrency(req.currency),
balanceMaterial: Amounts.zeroOfCurrency(req.currency),
@@ -691,38 +593,64 @@ export async function getPaymentBalanceDetailsInTx(
ca.freshCoinCount,
).amount;
- d.maxEffectiveSpendAmount = Amounts.add(
- d.maxEffectiveSpendAmount,
- Amounts.mult(ca.value, ca.freshCoinCount).amount,
- ).amount;
-
- d.maxEffectiveSpendAmount = Amounts.sub(
- d.maxEffectiveSpendAmount,
- Amounts.mult(denom.feeDeposit, ca.freshCoinCount).amount,
- ).amount;
-
let wireOkay = false;
if (req.restrictWireMethods == null) {
wireOkay = true;
} else {
for (const wm of req.restrictWireMethods) {
const wmf = findMatchingWire(wm, req.depositPaytoUri, wireDetails);
+ if (wmf) {
+ wireOkay = true;
+ break;
+ }
+ }
+ }
+
+ if (wireOkay) {
+ d.balanceExchangeDepositable = Amounts.add(
+ d.balanceExchangeDepositable,
+ coinAmount,
+ ).amount;
+ }
+
+ let ageOkay = ca.maxAge === 0 || ca.maxAge > req.minAge;
+
+ let merchantExchangeAcceptable = false;
+
+ if (!req.restrictExchanges) {
+ merchantExchangeAcceptable = true;
+ } else {
+ for (const ex of req.restrictExchanges.exchanges) {
+ if (ex.exchangeBaseUrl === ca.exchangeBaseUrl) {
+ merchantExchangeAcceptable = true;
+ break;
+ }
+ }
+ for (const acceptedAuditor of req.restrictExchanges.auditors) {
+ for (const exchangeAuditor of wireDetails.auditors) {
+ if (acceptedAuditor.auditorBaseUrl === exchangeAuditor.auditor_url) {
+ merchantExchangeAcceptable = true;
+ break;
+ }
+ }
}
}
+ const merchantExchangeDepositable = merchantExchangeAcceptable && wireOkay;
+
d.balanceAvailable = Amounts.add(d.balanceAvailable, coinAmount).amount;
d.balanceMaterial = Amounts.add(d.balanceMaterial, coinAmount).amount;
- if (ca.maxAge === 0 || ca.maxAge > req.minAge) {
+ if (ageOkay) {
d.balanceAgeAcceptable = Amounts.add(
d.balanceAgeAcceptable,
coinAmount,
).amount;
- if (acceptability.acceptableExchanges.includes(ca.exchangeBaseUrl)) {
+ if (merchantExchangeAcceptable) {
d.balanceMerchantAcceptable = Amounts.add(
d.balanceMerchantAcceptable,
coinAmount,
).amount;
- if (acceptability.depositableExchanges.includes(ca.exchangeBaseUrl)) {
+ if (merchantExchangeDepositable) {
d.balanceMerchantDepositable = Amounts.add(
d.balanceMerchantDepositable,
coinAmount,
@@ -730,6 +658,23 @@ export async function getPaymentBalanceDetailsInTx(
}
}
}
+
+ if (
+ ageOkay &&
+ wireOkay &&
+ merchantExchangeAcceptable &&
+ merchantExchangeDepositable
+ ) {
+ d.maxEffectiveSpendAmount = Amounts.add(
+ d.maxEffectiveSpendAmount,
+ Amounts.mult(ca.value, ca.freshCoinCount).amount,
+ ).amount;
+
+ d.maxEffectiveSpendAmount = Amounts.sub(
+ d.maxEffectiveSpendAmount,
+ Amounts.mult(denom.feeDeposit, ca.freshCoinCount).amount,
+ ).amount;
+ }
}
await tx.refreshGroups.iter().forEach((r) => {
diff --git a/packages/taler-wallet-core/src/coinSelection.ts b/packages/taler-wallet-core/src/coinSelection.ts
index 695be79ac..87b29a998 100644
--- a/packages/taler-wallet-core/src/coinSelection.ts
+++ b/packages/taler-wallet-core/src/coinSelection.ts
@@ -425,6 +425,16 @@ export async function reportInsufficientBalanceDetails(
balanceExchangeDepositable: Amounts.stringify(
exchDet.balanceExchangeDepositable,
),
+ balanceAgeAcceptable: Amounts.stringify(exchDet.balanceAgeAcceptable),
+ balanceMerchantAcceptable: Amounts.stringify(
+ exchDet.balanceMerchantAcceptable,
+ ),
+ balanceMerchantDepositable: Amounts.stringify(
+ exchDet.balanceMerchantDepositable,
+ ),
+ maxEffectiveSpendAmount: Amounts.stringify(
+ exchDet.maxEffectiveSpendAmount,
+ ),
};
}