diff options
Diffstat (limited to 'packages/taler-wallet-core/src/operations')
3 files changed, 4 insertions, 267 deletions
| diff --git a/packages/taler-wallet-core/src/operations/pay-peer-common.ts b/packages/taler-wallet-core/src/operations/pay-peer-common.ts index 4fdfecb4d..49f255eb9 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-common.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-common.ts @@ -43,8 +43,6 @@ import {  import { SpendCoinDetails } from "../crypto/cryptoImplementation.js";  import {    DenominationRecord, -  KycPendingInfo, -  KycUserType,    PeerPushPaymentCoinSelection,    ReserveRecord,  } from "../db.js"; @@ -52,68 +50,13 @@ import { InternalWalletState } from "../internal-wallet-state.js";  import { checkDbInvariant } from "../util/invariants.js";  import { getPeerPaymentBalanceDetailsInTx } from "./balance.js";  import { getTotalRefreshCost } from "./refresh.js"; +import type { PeerCoinInfo, PeerCoinSelectionRequest, SelectPeerCoinsResult, SelectedPeerCoin } from "../util/coinSelection.js";  const logger = new Logger("operations/peer-to-peer.ts"); -interface SelectedPeerCoin { -  coinPub: string; -  coinPriv: string; -  contribution: AmountString; -  denomPubHash: string; -  denomSig: UnblindedSignature; -  ageCommitmentProof: AgeCommitmentProof | undefined; -} - -interface PeerCoinSelectionDetails { -  exchangeBaseUrl: string; - -  /** -   * Info of Coins that were selected. -   */ -  coins: SelectedPeerCoin[]; - -  /** -   * How much of the deposit fees is the customer paying? -   */ -  depositFees: AmountJson; -} - -/** - * Information about a selected coin for peer to peer payments. - */ -interface CoinInfo { -  /** -   * Public key of the coin. -   */ -  coinPub: string; - -  coinPriv: string; - -  /** -   * Deposit fee for the coin. -   */ -  feeDeposit: AmountJson; - -  value: AmountJson; - -  denomPubHash: string; - -  denomSig: UnblindedSignature; - -  maxAge: number; - -  ageCommitmentProof?: AgeCommitmentProof; -} - -export type SelectPeerCoinsResult = -  | { type: "success"; result: PeerCoinSelectionDetails } -  | { -      type: "failure"; -      insufficientBalanceDetails: PayPeerInsufficientBalanceDetails; -    }; -  /**   * Get information about the coin selected for signatures + *   * @param ws   * @param csel   * @returns @@ -153,211 +96,7 @@ export async function queryCoinInfosForSelection(    return infos;  } -export interface PeerCoinRepair { -  exchangeBaseUrl: string; -  coinPubs: CoinPublicKeyString[]; -  contribs: AmountJson[]; -} - -export interface PeerCoinSelectionRequest { -  instructedAmount: AmountJson; -  /** -   * Instruct the coin selection to repair this coin -   * selection instead of selecting completely new coins. -   */ -  repair?: PeerCoinRepair; -} - -export async function selectPeerCoins( -  ws: InternalWalletState, -  req: PeerCoinSelectionRequest, -): Promise<SelectPeerCoinsResult> { -  const instructedAmount = req.instructedAmount; -  if (Amounts.isZero(instructedAmount)) { -    // Other parts of the code assume that we have at least -    // one coin to spend. -    throw new Error("amount of zero not allowed"); -  } -  return await ws.db -    .mktx((x) => [ -      x.exchanges, -      x.contractTerms, -      x.coins, -      x.coinAvailability, -      x.denominations, -      x.refreshGroups, -      x.peerPushPaymentInitiations, -    ]) -    .runReadWrite(async (tx) => { -      const exchanges = await tx.exchanges.iter().toArray(); -      const exchangeFeeGap: { [url: string]: AmountJson } = {}; -      const currency = Amounts.currencyOf(instructedAmount); -      for (const exch of exchanges) { -        if (exch.detailsPointer?.currency !== currency) { -          continue; -        } -        // FIXME: Can't we do this faster by using coinAvailability? -        const coins = ( -          await tx.coins.indexes.byBaseUrl.getAll(exch.baseUrl) -        ).filter((x) => x.status === CoinStatus.Fresh); -        const coinInfos: CoinInfo[] = []; -        for (const coin of coins) { -          const denom = await ws.getDenomInfo( -            ws, -            tx, -            coin.exchangeBaseUrl, -            coin.denomPubHash, -          ); -          if (!denom) { -            throw Error("denom not found"); -          } -          coinInfos.push({ -            coinPub: coin.coinPub, -            feeDeposit: Amounts.parseOrThrow(denom.feeDeposit), -            value: Amounts.parseOrThrow(denom.value), -            denomPubHash: denom.denomPubHash, -            coinPriv: coin.coinPriv, -            denomSig: coin.denomSig, -            maxAge: coin.maxAge, -            ageCommitmentProof: coin.ageCommitmentProof, -          }); -        } -        if (coinInfos.length === 0) { -          continue; -        } -        coinInfos.sort( -          (o1, o2) => -            -Amounts.cmp(o1.value, o2.value) || -            strcmp(o1.denomPubHash, o2.denomPubHash), -        ); -        let amountAcc = Amounts.zeroOfCurrency(currency); -        let depositFeesAcc = Amounts.zeroOfCurrency(currency); -        const resCoins: { -          coinPub: string; -          coinPriv: string; -          contribution: AmountString; -          denomPubHash: string; -          denomSig: UnblindedSignature; -          ageCommitmentProof: AgeCommitmentProof | undefined; -        }[] = []; -        let lastDepositFee = Amounts.zeroOfCurrency(currency); - -        if (req.repair) { -          for (let i = 0; i < req.repair.coinPubs.length; i++) { -            const contrib = req.repair.contribs[i]; -            const coin = await tx.coins.get(req.repair.coinPubs[i]); -            if (!coin) { -              throw Error("repair not possible, coin not found"); -            } -            const denom = await ws.getDenomInfo( -              ws, -              tx, -              coin.exchangeBaseUrl, -              coin.denomPubHash, -            ); -            checkDbInvariant(!!denom); -            resCoins.push({ -              coinPriv: coin.coinPriv, -              coinPub: coin.coinPub, -              contribution: Amounts.stringify(contrib), -              denomPubHash: coin.denomPubHash, -              denomSig: coin.denomSig, -              ageCommitmentProof: coin.ageCommitmentProof, -            }); -            const depositFee = Amounts.parseOrThrow(denom.feeDeposit); -            lastDepositFee = depositFee; -            amountAcc = Amounts.add( -              amountAcc, -              Amounts.sub(contrib, depositFee).amount, -            ).amount; -            depositFeesAcc = Amounts.add(depositFeesAcc, depositFee).amount; -          } -        } - -        for (const coin of coinInfos) { -          if (Amounts.cmp(amountAcc, instructedAmount) >= 0) { -            break; -          } -          const gap = Amounts.add( -            coin.feeDeposit, -            Amounts.sub(instructedAmount, amountAcc).amount, -          ).amount; -          const contrib = Amounts.min(gap, coin.value); -          amountAcc = Amounts.add( -            amountAcc, -            Amounts.sub(contrib, coin.feeDeposit).amount, -          ).amount; -          depositFeesAcc = Amounts.add(depositFeesAcc, coin.feeDeposit).amount; -          resCoins.push({ -            coinPriv: coin.coinPriv, -            coinPub: coin.coinPub, -            contribution: Amounts.stringify(contrib), -            denomPubHash: coin.denomPubHash, -            denomSig: coin.denomSig, -            ageCommitmentProof: coin.ageCommitmentProof, -          }); -          lastDepositFee = coin.feeDeposit; -        } -        if (Amounts.cmp(amountAcc, instructedAmount) >= 0) { -          const res: PeerCoinSelectionDetails = { -            exchangeBaseUrl: exch.baseUrl, -            coins: resCoins, -            depositFees: depositFeesAcc, -          }; -          return { type: "success", result: res }; -        } -        const diff = Amounts.sub(instructedAmount, amountAcc).amount; -        exchangeFeeGap[exch.baseUrl] = Amounts.add(lastDepositFee, diff).amount; - -        continue; -      } - -      // We were unable to select coins. -      // Now we need to produce error details. - -      const infoGeneral = await getPeerPaymentBalanceDetailsInTx(ws, tx, { -        currency, -      }); - -      const perExchange: PayPeerInsufficientBalanceDetails["perExchange"] = {}; - -      let maxFeeGapEstimate = Amounts.zeroOfCurrency(currency); - -      for (const exch of exchanges) { -        if (exch.detailsPointer?.currency !== currency) { -          continue; -        } -        const infoExchange = await getPeerPaymentBalanceDetailsInTx(ws, tx, { -          currency, -          restrictExchangeTo: exch.baseUrl, -        }); -        let gap = -          exchangeFeeGap[exch.baseUrl] ?? Amounts.zeroOfCurrency(currency); -        if (Amounts.cmp(infoExchange.balanceMaterial, instructedAmount) < 0) { -          // Show fee gap only if we should've been able to pay with the material amount -          gap = Amounts.zeroOfCurrency(currency); -        } -        perExchange[exch.baseUrl] = { -          balanceAvailable: Amounts.stringify(infoExchange.balanceAvailable), -          balanceMaterial: Amounts.stringify(infoExchange.balanceMaterial), -          feeGapEstimate: Amounts.stringify(gap), -        }; - -        maxFeeGapEstimate = Amounts.max(maxFeeGapEstimate, gap); -      } - -      const errDetails: PayPeerInsufficientBalanceDetails = { -        amountRequested: Amounts.stringify(instructedAmount), -        balanceAvailable: Amounts.stringify(infoGeneral.balanceAvailable), -        balanceMaterial: Amounts.stringify(infoGeneral.balanceMaterial), -        feeGapEstimate: Amounts.stringify(maxFeeGapEstimate), -        perExchange, -      }; - -      return { type: "failure", insufficientBalanceDetails: errDetails }; -    }); -}  export async function getTotalPeerPaymentCost(    ws: InternalWalletState, diff --git a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts index 8ba84585c..0de91bf97 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-pull-debit.ts @@ -68,11 +68,9 @@ import {    spendCoins,  } from "./common.js";  import { -  PeerCoinRepair,    codecForExchangePurseStatus,    getTotalPeerPaymentCost,    queryCoinInfosForSelection, -  selectPeerCoins,  } from "./pay-peer-common.js";  import {    constructTransactionIdentifier, @@ -80,6 +78,7 @@ import {    parseTransactionIdentifier,    stopLongpolling,  } from "./transactions.js"; +import { PeerCoinRepair, selectPeerCoins } from "../util/coinSelection.js";  const logger = new Logger("pay-peer-pull-debit.ts"); diff --git a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts index c853bc0ef..2349e5c4a 100644 --- a/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts +++ b/packages/taler-wallet-core/src/operations/pay-peer-push-debit.ts @@ -68,17 +68,16 @@ import {    spendCoins,  } from "./common.js";  import { -  PeerCoinRepair,    codecForExchangePurseStatus,    getTotalPeerPaymentCost,    queryCoinInfosForSelection, -  selectPeerCoins,  } from "./pay-peer-common.js";  import {    constructTransactionIdentifier,    notifyTransition,    stopLongpolling,  } from "./transactions.js"; +import { PeerCoinRepair, selectPeerCoins } from "../util/coinSelection.js";  const logger = new Logger("pay-peer-push-debit.ts"); | 
