summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-core/src/pay-merchant.ts
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-03-06 21:15:30 +0100
committerFlorian Dold <florian@dold.me>2024-03-07 00:03:59 +0100
commit7ba1d1f3351e58a331e99337afea0fbedb6eb828 (patch)
tree60b7a485cd317c1fe55276acdc0e055cd9353bfb /packages/taler-wallet-core/src/pay-merchant.ts
parent618caa117111b9fed6a792b6816fc724483eb349 (diff)
downloadwallet-core-7ba1d1f3351e58a331e99337afea0fbedb6eb828.tar.gz
wallet-core-7ba1d1f3351e58a331e99337afea0fbedb6eb828.tar.bz2
wallet-core-7ba1d1f3351e58a331e99337afea0fbedb6eb828.zip
refactor coin selection, report maxEffectiveSpendAmount
Diffstat (limited to 'packages/taler-wallet-core/src/pay-merchant.ts')
-rw-r--r--packages/taler-wallet-core/src/pay-merchant.ts63
1 files changed, 29 insertions, 34 deletions
diff --git a/packages/taler-wallet-core/src/pay-merchant.ts b/packages/taler-wallet-core/src/pay-merchant.ts
index ed58dc404..a155d6298 100644
--- a/packages/taler-wallet-core/src/pay-merchant.ts
+++ b/packages/taler-wallet-core/src/pay-merchant.ts
@@ -111,6 +111,7 @@ import {
import { EddsaKeypair } from "./crypto/cryptoImplementation.js";
import {
CoinRecord,
+ DbCoinSelection,
DenominationRecord,
PurchaseRecord,
PurchaseStatus,
@@ -445,11 +446,11 @@ export async function getTotalPaymentCost(
wex: WalletExecutionContext,
pcs: PayCoinSelection,
): Promise<AmountJson> {
- const currency = Amounts.currencyOf(pcs.paymentAmount);
+ const currency = Amounts.currencyOf(pcs.customerDepositFees);
return wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
const costs: AmountJson[] = [];
- for (let i = 0; i < pcs.coinPubs.length; i++) {
- const coin = await tx.coins.get(pcs.coinPubs[i]);
+ for (let i = 0; i < pcs.coins.length; i++) {
+ const coin = await tx.coins.get(pcs.coins[i].coinPub);
if (!coin) {
throw Error("can't calculate payment cost, coin not found");
}
@@ -470,7 +471,7 @@ export async function getTotalPaymentCost(
);
const amountLeft = Amounts.sub(
denom.value,
- pcs.coinContributions[i],
+ pcs.coins[i].contribution,
).amount;
const refreshCost = getTotalRefreshCost(
allDenoms,
@@ -478,10 +479,10 @@ export async function getTotalPaymentCost(
amountLeft,
wex.ws.config.testing.denomselAllowLate,
);
- costs.push(Amounts.parseOrThrow(pcs.coinContributions[i]));
+ costs.push(Amounts.parseOrThrow(pcs.coins[i].contribution));
costs.push(refreshCost);
}
- const zero = Amounts.zeroOfAmount(pcs.paymentAmount);
+ const zero = Amounts.zeroOfAmount(pcs.customerDepositFees);
return Amounts.sum([zero, ...costs]).amount;
});
}
@@ -617,7 +618,8 @@ async function processDownloadProposal(
if (proposal.purchaseStatus != PurchaseStatus.PendingDownloadingProposal) {
logger.error(
- `unexpected state ${proposal.purchaseStatus}/${PurchaseStatus[proposal.purchaseStatus]
+ `unexpected state ${proposal.purchaseStatus}/${
+ PurchaseStatus[proposal.purchaseStatus]
} for ${ctx.transactionId} in processDownloadProposal`,
);
return TaskRunResult.finished();
@@ -873,7 +875,8 @@ async function createOrReusePurchase(
oldProposal.claimToken === claimToken
) {
logger.info(
- `Found old proposal (status=${PurchaseStatus[oldProposal.purchaseStatus]
+ `Found old proposal (status=${
+ PurchaseStatus[oldProposal.purchaseStatus]
}) for order ${orderId} at ${merchantBaseUrl}`,
);
if (oldProposal.purchaseStatus === PurchaseStatus.DialogShared) {
@@ -1137,26 +1140,10 @@ async function handleInsufficientFunds(
await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
for (let i = 0; i < payCoinSelection.coinPubs.length; i++) {
const coinPub = payCoinSelection.coinPubs[i];
- if (coinPub === brokenCoinPub) {
- continue;
- }
const contrib = payCoinSelection.coinContributions[i];
- const coin = await tx.coins.get(coinPub);
- if (!coin) {
- continue;
- }
- const denom = await tx.denominations.get([
- coin.exchangeBaseUrl,
- coin.denomPubHash,
- ]);
- if (!denom) {
- continue;
- }
prevPayCoins.push({
coinPub,
contribution: Amounts.parseOrThrow(contrib),
- exchangeBaseUrl: coin.exchangeBaseUrl,
- feeDeposit: Amounts.parseOrThrow(denom.fees.feeDeposit),
});
}
});
@@ -1199,7 +1186,11 @@ async function handleInsufficientFunds(
if (!payInfo) {
return;
}
- payInfo.payCoinSelection = res.coinSel;
+ // Convert to DB format
+ payInfo.payCoinSelection = {
+ coinContributions: res.coinSel.coins.map((x) => x.contribution),
+ coinPubs: res.coinSel.coins.map((x) => x.coinPub),
+ };
payInfo.payCoinSelectionUid = encodeCrock(getRandomBytes(32));
await tx.purchases.put(p);
await spendCoins(wex, tx, {
@@ -1286,13 +1277,14 @@ async function checkPaymentByProposalId(
purchase.purchaseStatus === PurchaseStatus.DialogProposed ||
purchase.purchaseStatus === PurchaseStatus.DialogShared
) {
+ const instructedAmount = Amounts.parseOrThrow(contractData.amount);
// If not already paid, check if we could pay for it.
const res = await selectPayCoins(wex, {
restrictExchanges: {
auditors: [],
exchanges: contractData.allowedExchanges,
},
- contractTermsAmount: Amounts.parseOrThrow(contractData.amount),
+ contractTermsAmount: instructedAmount,
depositFeeLimit: Amounts.parseOrThrow(contractData.maxDepositFee),
wireFeeAmortization: contractData.wireFeeAmortization ?? 1,
wireFeeLimit: Amounts.parseOrThrow(contractData.maxWireFee),
@@ -1327,7 +1319,7 @@ async function checkPaymentByProposalId(
transactionId,
proposalId: proposal.proposalId,
amountEffective: Amounts.stringify(totalCost),
- amountRaw: Amounts.stringify(res.coinSel.paymentAmount),
+ amountRaw: Amounts.stringify(instructedAmount),
contractTermsHash: d.contractData.contractTermsHash,
talerUri,
};
@@ -1599,7 +1591,7 @@ export async function preparePayForTemplate(
*/
export async function generateDepositPermissions(
wex: WalletExecutionContext,
- payCoinSel: PayCoinSelection,
+ payCoinSel: DbCoinSelection,
contractData: WalletContractData,
): Promise<CoinDepositPermission[]> {
const depositPermissions: CoinDepositPermission[] = [];
@@ -1608,7 +1600,7 @@ export async function generateDepositPermissions(
denom: DenominationRecord;
}> = [];
await wex.db.runReadOnlyTx(["coins", "denominations"], async (tx) => {
- for (let i = 0; i < payCoinSel.coinPubs.length; i++) {
+ for (let i = 0; i < payCoinSel.coinContributions.length; i++) {
const coin = await tx.coins.get(payCoinSel.coinPubs[i]);
if (!coin) {
throw Error("can't pay, allocated coin not found anymore");
@@ -1626,7 +1618,7 @@ export async function generateDepositPermissions(
}
});
- for (let i = 0; i < payCoinSel.coinPubs.length; i++) {
+ for (let i = 0; i < payCoinSel.coinContributions.length; i++) {
const { coin, denom } = coinWithDenom[i];
let wireInfoHash: string;
wireInfoHash = contractData.wireInfoHash;
@@ -1881,7 +1873,10 @@ export async function confirmPay(
case PurchaseStatus.DialogShared:
case PurchaseStatus.DialogProposed:
p.payInfo = {
- payCoinSelection: coinSelection,
+ payCoinSelection: {
+ coinContributions: coinSelection.coins.map((x) => x.contribution),
+ coinPubs: coinSelection.coins.map((x) => x.coinPub),
+ },
payCoinSelectionUid: encodeCrock(getRandomBytes(16)),
totalPayCost: Amounts.stringify(payCostInfo),
};
@@ -1895,9 +1890,9 @@ export async function confirmPay(
tag: TransactionType.Payment,
proposalId: proposalId,
}),
- coinPubs: coinSelection.coinPubs,
- contributions: coinSelection.coinContributions.map((x) =>
- Amounts.parseOrThrow(x),
+ coinPubs: coinSelection.coins.map((x) => x.coinPub),
+ contributions: coinSelection.coins.map((x) =>
+ Amounts.parseOrThrow(x.contribution),
),
refreshReason: RefreshReason.PayMerchant,
});