summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/taler-util/src/wallet-types.ts4
-rw-r--r--packages/taler-wallet-core/src/balance.ts167
-rw-r--r--packages/taler-wallet-core/src/coinSelection.ts10
-rw-r--r--packages/taler-wallet-webextension/src/cta/Payment/stories.tsx6
4 files changed, 76 insertions, 111 deletions
diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts
index 8be8fc4a0..cfbed04dc 100644
--- a/packages/taler-util/src/wallet-types.ts
+++ b/packages/taler-util/src/wallet-types.ts
@@ -882,6 +882,10 @@ export interface PaymentInsufficientBalanceDetails {
balanceAvailable: AmountString;
balanceMaterial: AmountString;
balanceExchangeDepositable: AmountString;
+ balanceAgeAcceptable: AmountString;
+ balanceMerchantAcceptable: AmountString;
+ balanceMerchantDepositable: AmountString;
+ maxEffectiveSpendAmount: AmountString;
};
};
}
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,
+ ),
};
}
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/stories.tsx b/packages/taler-wallet-webextension/src/cta/Payment/stories.tsx
index 567b5c177..93b96c836 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Payment/stories.tsx
@@ -60,6 +60,7 @@ export const NoEnoughBalanceAvailable = tests.createExample(BaseView, {
balanceMerchantAcceptable: "USD:9" as AmountString,
balanceMerchantDepositable: "USD:9" as AmountString,
maxEffectiveSpendAmount: "USD:9.5" as AmountString,
+ balanceExchangeDepositable: "USD:9.5" as AmountString,
perExchange: {},
},
talerUri: "taler://pay/..",
@@ -101,6 +102,7 @@ export const NoEnoughBalanceMaterial = tests.createExample(BaseView, {
balanceMerchantAcceptable: "USD:9" as AmountString,
balanceMerchantDepositable: "USD:0" as AmountString,
maxEffectiveSpendAmount: "USD:9.5" as AmountString,
+ balanceExchangeDepositable: "USD:9.5" as AmountString,
perExchange: {},
},
talerUri: "taler://pay/..",
@@ -142,6 +144,7 @@ export const NoEnoughBalanceAgeAcceptable = tests.createExample(BaseView, {
balanceMerchantAcceptable: "USD:9" as AmountString,
balanceMerchantDepositable: "USD:9" as AmountString,
maxEffectiveSpendAmount: "USD:9.5" as AmountString,
+ balanceExchangeDepositable: "USD:9.5" as AmountString,
perExchange: {},
},
talerUri: "taler://pay/..",
@@ -184,6 +187,7 @@ export const NoEnoughBalanceMerchantAcceptable = tests.createExample(BaseView, {
balanceMerchantAcceptable: "USD:9" as AmountString,
balanceMerchantDepositable: "USD:9" as AmountString,
maxEffectiveSpendAmount: "USD:9.5" as AmountString,
+ balanceExchangeDepositable: "USD:9.5" as AmountString,
perExchange: {},
},
talerUri: "taler://pay/..",
@@ -227,6 +231,7 @@ export const NoEnoughBalanceMerchantDepositable = tests.createExample(
balanceMerchantAcceptable: "USD:10" as AmountString,
balanceMerchantDepositable: "USD:9" as AmountString,
maxEffectiveSpendAmount: "USD:9.5" as AmountString,
+ balanceExchangeDepositable: "USD:9.5" as AmountString,
perExchange: {},
},
talerUri: "taler://pay/..",
@@ -269,6 +274,7 @@ export const NoEnoughBalanceFeeGap = tests.createExample(BaseView, {
balanceMerchantAcceptable: "USD:10" as AmountString,
balanceMerchantDepositable: "USD:10" as AmountString,
maxEffectiveSpendAmount: "USD:9.5" as AmountString,
+ balanceExchangeDepositable: "USD:9.5" as AmountString,
perExchange: {},
},
talerUri: "taler://pay/..",