diff options
Diffstat (limited to 'packages/taler-wallet-core/src/operations/deposits.ts')
-rw-r--r-- | packages/taler-wallet-core/src/operations/deposits.ts | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/packages/taler-wallet-core/src/operations/deposits.ts b/packages/taler-wallet-core/src/operations/deposits.ts index 660fb8816..9abec89bf 100644 --- a/packages/taler-wallet-core/src/operations/deposits.ts +++ b/packages/taler-wallet-core/src/operations/deposits.ts @@ -57,12 +57,13 @@ import { WireFee, } from "@gnu-taler/taler-util"; import { + DenominationRecord, DepositGroupRecord, OperationStatus, TransactionStatus, } from "../db.js"; import { TalerError } from "@gnu-taler/taler-util"; -import { KycPendingInfo, KycUserType } from "../index.js"; +import { getTotalRefreshCost, KycPendingInfo, KycUserType } from "../index.js"; import { InternalWalletState } from "../internal-wallet-state.js"; import { readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; import { OperationAttemptResult } from "../util/retries.js"; @@ -556,9 +557,17 @@ export async function prepareDepositGroup( payCoinSel.coinSel, ); + const fees = await getTotalFeesForDepositAmount( + ws, + p.targetType, + amount, + payCoinSel.coinSel, + ); + return { totalDepositCost: Amounts.stringify(totalDepositCost), effectiveDepositAmount: Amounts.stringify(effectiveDepositAmount), + fees, }; } @@ -774,3 +783,83 @@ export async function getCounterpartyEffectiveDepositAmount( }); return Amounts.sub(Amounts.sum(amt).amount, Amounts.sum(fees).amount).amount; } + +/** + * Get the fee amount that will be charged when trying to deposit the + * specified amount using the selected coins and the wire method. + */ +export async function getTotalFeesForDepositAmount( + ws: InternalWalletState, + wireType: string, + total: AmountJson, + pcs: PayCoinSelection, +): Promise<DepositGroupFees> { + const wireFee: AmountJson[] = []; + const coinFee: AmountJson[] = []; + const refreshFee: AmountJson[] = []; + const exchangeSet: Set<string> = new Set(); + + await ws.db + .mktx((x) => [x.coins, x.denominations, x.exchanges, x.exchangeDetails]) + .runReadOnly(async (tx) => { + for (let i = 0; i < pcs.coinPubs.length; i++) { + const coin = await tx.coins.get(pcs.coinPubs[i]); + if (!coin) { + throw Error("can't calculate deposit amount, coin not found"); + } + const denom = await ws.getDenomInfo( + ws, + tx, + coin.exchangeBaseUrl, + coin.denomPubHash, + ); + if (!denom) { + throw Error("can't find denomination to calculate deposit amount"); + } + coinFee.push(Amounts.parseOrThrow(denom.feeDeposit)); + exchangeSet.add(coin.exchangeBaseUrl); + + const allDenoms = await tx.denominations.indexes.byExchangeBaseUrl + .iter(coin.exchangeBaseUrl) + .filter((x) => + Amounts.isSameCurrency( + DenominationRecord.getValue(x), + pcs.coinContributions[i], + ), + ); + const amountLeft = Amounts.sub( + denom.value, + pcs.coinContributions[i], + ).amount; + const refreshCost = getTotalRefreshCost(allDenoms, denom, amountLeft); + refreshFee.push(refreshCost); + } + + for (const exchangeUrl of exchangeSet.values()) { + const exchangeDetails = await getExchangeDetails(tx, exchangeUrl); + if (!exchangeDetails) { + continue; + } + const fee = exchangeDetails.wireInfo.feesForType[wireType]?.find( + (x) => { + return AbsoluteTime.isBetween( + AbsoluteTime.now(), + AbsoluteTime.fromTimestamp(x.startStamp), + AbsoluteTime.fromTimestamp(x.endStamp), + ); + }, + )?.wireFee; + if (fee) { + wireFee.push(Amounts.parseOrThrow(fee)); + } + } + }); + + return { + coin: Amounts.stringify(Amounts.sumOrZero(total.currency, coinFee).amount), + wire: Amounts.stringify(Amounts.sumOrZero(total.currency, wireFee).amount), + refresh: Amounts.stringify( + Amounts.sumOrZero(total.currency, refreshFee).amount, + ), + }; +} |