gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: wallet-core: move getMaxDepos


From: gnunet
Subject: [taler-wallet-core] branch master updated: wallet-core: move getMaxDepositAmount to coinSelection.ts
Date: Mon, 09 Sep 2024 21:19:30 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 049b369f7 wallet-core: move getMaxDepositAmount to coinSelection.ts
049b369f7 is described below

commit 049b369f745edb5f8a2d7ec57d5af98ca81b05fa
Author: Florian Dold <florian@dold.me>
AuthorDate: Mon Sep 9 21:18:51 2024 +0200

    wallet-core: move getMaxDepositAmount to coinSelection.ts
    
    The function is now using the normal wallet-core coin selection
    infrastructure, leading to automatic support for credit/debit
    restrictions and less code duplication.
---
 packages/taler-util/src/types-taler-merchant.ts    |  46 ++----
 packages/taler-util/src/types-taler-wallet.ts      |   2 +
 packages/taler-util/src/types.test.ts              |  12 +-
 .../taler-wallet-core/src/coinSelection.test.ts    | 168 ++++++++++++++++++++-
 packages/taler-wallet-core/src/coinSelection.ts    | 121 ++++++++++++---
 packages/taler-wallet-core/src/deposits.ts         |  15 +-
 .../src/instructedAmountConversion.test.ts         | 143 ------------------
 .../src/instructedAmountConversion.ts              |  42 ------
 packages/taler-wallet-core/src/wallet.ts           |  10 +-
 9 files changed, 295 insertions(+), 264 deletions(-)

diff --git a/packages/taler-util/src/types-taler-merchant.ts 
b/packages/taler-util/src/types-taler-merchant.ts
index de3664b67..2d24e2d72 100644
--- a/packages/taler-util/src/types-taler-merchant.ts
+++ b/packages/taler-util/src/types-taler-merchant.ts
@@ -335,18 +335,6 @@ export interface MerchantAbortPayRefundSuccessStatus {
   exchange_pub: string;
 }
 
-/**
- * Information about an exchange as stored inside a
- * merchant's contract terms.
- */
-export interface ExchangeHandle {
-  // The exchange's base URL.
-  url: string;
-
-  // Master public key of the exchange.
-  master_pub: EddsaPublicKeyString;
-}
-
 export interface AuditorHandle {
   /**
    * Official name of the auditor.
@@ -531,7 +519,7 @@ export interface MerchantContractTerms {
   delivery_location?: Location;
 
   // Exchanges that the merchant accepts even if it does not accept any 
auditors that audit them.
-  exchanges: ExchangeHandle[];
+  exchanges: Exchange[];
 
   // List of products that are part of the purchase (see Product).
   products?: Product[];
@@ -667,12 +655,6 @@ export interface MerchantBlindSigWrapperV1 {
   blind_sig: string;
 }
 
-export const codecForExchangeHandle = (): Codec<ExchangeHandle> =>
-  buildCodecForObject<ExchangeHandle>()
-    .property("master_pub", codecForString())
-    .property("url", codecForString())
-    .build("ExchangeHandle");
-
 export const codecForAuditorHandle = (): Codec<AuditorHandle> =>
   buildCodecForObject<AuditorHandle>()
     .property("name", codecForString())
@@ -727,7 +709,7 @@ export const codecForMerchantContractTerms = (): 
Codec<MerchantContractTerms> =>
     .property("max_fee", codecForAmountString())
     .property("merchant", codecForMerchantInfo())
     .property("merchant_pub", codecForString())
-    .property("exchanges", codecForList(codecForExchangeHandle()))
+    .property("exchanges", codecForList(codecForExchange()))
     .property("products", codecOptional(codecForList(codecForProduct())))
     .property("extra", codecForAny())
     .property("minimum_age", codecOptional(codecForNumber()))
@@ -815,16 +797,13 @@ export interface PaymentResponse {
   pos_confirmation?: string;
 }
 export interface PaymentDeniedLegallyResponse {
-
   // Base URL of the exchanges that denied the payment.
   // The wallet should refresh the coins from these
   // exchanges, but may try to pay with coins from
   // other exchanges.
   exchange_base_urls: string[];
-
 }
 
-
 export interface PaymentStatusRequestParams {
   // Hash of the order’s contract terms (this is used to
   // authenticate the wallet/customer in case
@@ -1541,7 +1520,6 @@ export interface CategoryProductList {
 export interface ProductSummary {
   // Product ID to use.
   product_id: string;
-
 }
 
 export interface CategoryCreateRequest {
@@ -2698,6 +2676,7 @@ export interface Tax {
   // Amount paid in tax.
   tax: AmountString;
 }
+
 export interface Merchant {
   // The merchant's legal name of business.
   name: string;
@@ -2718,6 +2697,7 @@ export interface Merchant {
   // Some of the typical fields for a location (such as a street address) may 
be absent.
   jurisdiction?: Location;
 }
+
 // Delivery location, loosely modeled as a subset of
 // ISO20022's PostalAddress25.
 export interface Location {
@@ -2752,16 +2732,7 @@ export interface Location {
   // Free-form address lines, should not exceed 7 elements.
   address_lines?: string[];
 }
-interface Auditor {
-  // Official name.
-  name: string;
-
-  // Auditor's public key.
-  auditor_pub: EddsaPublicKey;
 
-  // Base URL of the auditor.
-  url: string;
-}
 export interface Exchange {
   // The exchange's base URL.
   url: string;
@@ -2873,10 +2844,11 @@ export const codecForPaymentResponse = (): 
Codec<PaymentResponse> =>
     .property("sig", codecForString())
     .build("TalerMerchantApi.PaymentResponse");
 
-export const codecForPaymentDeniedLegallyResponse = (): 
Codec<PaymentDeniedLegallyResponse> =>
-  buildCodecForObject<PaymentDeniedLegallyResponse>()
-    .property("exchange_base_urls", codecForList(codecForString()))
-    .build("TalerMerchantApi.PaymentDeniedLegallyResponse");
+export const codecForPaymentDeniedLegallyResponse =
+  (): Codec<PaymentDeniedLegallyResponse> =>
+    buildCodecForObject<PaymentDeniedLegallyResponse>()
+      .property("exchange_base_urls", codecForList(codecForString()))
+      .build("TalerMerchantApi.PaymentDeniedLegallyResponse");
 
 export const codecForStatusPaid = (): Codec<StatusPaid> =>
   buildCodecForObject<StatusPaid>()
diff --git a/packages/taler-util/src/types-taler-wallet.ts 
b/packages/taler-util/src/types-taler-wallet.ts
index 244640115..b788155c2 100644
--- a/packages/taler-util/src/types-taler-wallet.ts
+++ b/packages/taler-util/src/types-taler-wallet.ts
@@ -235,11 +235,13 @@ export const codecForConvertAmountRequest =
 
 export interface GetMaxDepositAmountRequest {
   currency: string;
+  depositPaytoUri?: string;
 }
 
 export const codecForGetMaxDepositAmountRequest =
   buildCodecForObject<GetMaxDepositAmountRequest>()
     .property("currency", codecForString())
+    .property("depositPaytoUri", codecOptional(codecForString()))
     .build("GetAmountRequest");
 
 export interface GetMaxDepositAmountResponse {
diff --git a/packages/taler-util/src/types.test.ts 
b/packages/taler-util/src/types.test.ts
index ed55fd16c..bea352128 100644
--- a/packages/taler-util/src/types.test.ts
+++ b/packages/taler-util/src/types.test.ts
@@ -15,15 +15,14 @@
  */
 
 import test from "ava";
-import { codecForContractTerms } from "./index.js";
+import { codecForContractTerms, MerchantContractTerms } from "./index.js";
 
 test("contract terms validation", (t) => {
   const c = {
     nonce: "123123123",
     h_wire: "123",
     amount: "EUR:1.5",
-    auditors: [],
-    exchanges: [{ master_pub: "foo", url: "foo" }],
+    exchanges: [{ master_pub: "foo", priority: 1, url: "foo" }],
     fulfillment_url: "foo",
     max_fee: "EUR:1.5",
     merchant_pub: "12345",
@@ -37,7 +36,7 @@ test("contract terms validation", (t) => {
     summary: "hello",
     timestamp: { t_s: 42 },
     wire_method: "test",
-  };
+  } satisfies MerchantContractTerms;
 
   codecForContractTerms().decode(c);
 
@@ -59,8 +58,7 @@ test("contract terms validation (locations)", (t) => {
     nonce: "123123123",
     h_wire: "123",
     amount: "EUR:1.5",
-    auditors: [],
-    exchanges: [{ master_pub: "foo", url: "foo" }],
+    exchanges: [{ master_pub: "foo", priority: 1, url: "foo" }],
     fulfillment_url: "foo",
     max_fee: "EUR:1.5",
     merchant_pub: "12345",
@@ -83,7 +81,7 @@ test("contract terms validation (locations)", (t) => {
       country: "FR",
       town: "Rennes",
     },
-  };
+  } satisfies MerchantContractTerms;
 
   const r = codecForContractTerms().decode(c);
 
diff --git a/packages/taler-wallet-core/src/coinSelection.test.ts 
b/packages/taler-wallet-core/src/coinSelection.test.ts
index c7cb2857e..a13838034 100644
--- a/packages/taler-wallet-core/src/coinSelection.test.ts
+++ b/packages/taler-wallet-core/src/coinSelection.test.ts
@@ -15,17 +15,21 @@
  */
 import {
   AbsoluteTime,
+  AmountJson,
   AmountString,
   Amounts,
   DenomKeyType,
+  DenominationPubKey,
   Duration,
+  TalerProtocolTimestamp,
   j2s,
 } from "@gnu-taler/taler-util";
 import test from "ava";
 import {
-  AvailableDenom,
+  AvailableCoinsOfDenom,
   CoinSelectionTally,
   emptyTallyForPeerPayment,
+  testing_getMaxDepositAmountForAvailableCoins,
   testing_selectGreedy,
 } from "./coinSelection.js";
 
@@ -180,7 +184,7 @@ function createCandidates(
     numAvailable: number;
     fromExchange: string;
   }[],
-): AvailableDenom[] {
+): AvailableCoinsOfDenom[] {
   return ar.map((r, idx) => {
     return {
       denomPub: {
@@ -279,3 +283,163 @@ test("p2p: regression STATER", (t) => {
   );
   t.assert(!!res);
 });
+
+function makeCurrencyHelper(currency: string) {
+  return (sx: TemplateStringsArray, ...vx: any[]) => {
+    const s = String.raw({ raw: sx }, ...vx);
+    return Amounts.parseOrThrow(`${currency}:${s}`);
+  };
+}
+
+type TestCoin = [AmountJson, number];
+
+const kudos = makeCurrencyHelper("kudos");
+
+function defaultFeeConfig(
+  value: AmountJson,
+  totalAvailable: number,
+): AvailableCoinsOfDenom {
+  return {
+    denomPub: undefined as any as DenominationPubKey,
+    denomPubHash: "123",
+    feeDeposit: `KUDOS:0.01`,
+    feeRefresh: `KUDOS:0.01`,
+    feeRefund: `KUDOS:0.01`,
+    feeWithdraw: `KUDOS:0.01`,
+    exchangeBaseUrl: "2",
+    maxAge: 0,
+    numAvailable: totalAvailable,
+    stampExpireDeposit: TalerProtocolTimestamp.never(),
+    stampExpireLegal: TalerProtocolTimestamp.never(),
+    stampExpireWithdraw: TalerProtocolTimestamp.never(),
+    stampStart: TalerProtocolTimestamp.never(),
+    value: Amounts.stringify(value),
+  };
+}
+
+test("deposit max 35", (t) => {
+  const coinList: TestCoin[] = [
+    [kudos`2`, 5],
+    [kudos`5`, 5],
+  ];
+  const result = testing_getMaxDepositAmountForAvailableCoins(
+    {
+      currency: "KUDOS",
+    },
+    {
+      coinAvailability: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
+      currentWireFeePerExchange: {
+        "2": kudos`0`,
+      },
+    },
+  );
+  t.is(Amounts.stringifyValue(result.rawAmount), "34.9");
+  t.is(Amounts.stringifyValue(result.effectiveAmount), "35");
+});
+
+test("deposit max 35 with wirefee", (t) => {
+  const coinList: TestCoin[] = [
+    [kudos`2`, 5],
+    [kudos`5`, 5],
+  ];
+  const result = testing_getMaxDepositAmountForAvailableCoins(
+    {
+      currency: "KUDOS",
+    },
+    {
+      coinAvailability: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
+      currentWireFeePerExchange: {
+        "2": kudos`1`,
+      },
+    },
+  );
+  t.is(Amounts.stringifyValue(result.rawAmount), "33.9");
+  t.is(Amounts.stringifyValue(result.effectiveAmount), "35");
+});
+
+test("deposit max repeated denom", (t) => {
+  const coinList: TestCoin[] = [
+    [kudos`2`, 1],
+    [kudos`2`, 1],
+    [kudos`5`, 1],
+  ];
+  const result = testing_getMaxDepositAmountForAvailableCoins(
+    {
+      currency: "KUDOS",
+    },
+    {
+      coinAvailability: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
+      currentWireFeePerExchange: {
+        "2": kudos`0`,
+      },
+    },
+  );
+  t.is(Amounts.stringifyValue(result.rawAmount), "8.97");
+  t.is(Amounts.stringifyValue(result.effectiveAmount), "9");
+});
+
+test("demo: deposit max after withdraw raw 25", (t) => {
+  const coinList: TestCoin[] = [
+    [kudos`0.1`, 8],
+    [kudos`1`, 0],
+    [kudos`2`, 2],
+    [kudos`5`, 0],
+    [kudos`10`, 2],
+  ];
+  const result = testing_getMaxDepositAmountForAvailableCoins(
+    {
+      currency: "KUDOS",
+    },
+    {
+      coinAvailability: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
+      currentWireFeePerExchange: {
+        "2": kudos`0.01`,
+      },
+    },
+  );
+  t.is(Amounts.stringifyValue(result.effectiveAmount), "24.8");
+  t.is(Amounts.stringifyValue(result.rawAmount), "24.67");
+
+  // 8 x  0.1
+  // 2 x  0.2
+  // 2 x 10.0
+  // total effective 24.8
+  // deposit fee 12 x 0.01 = 0.12
+  // wire fee 0.01
+  // total raw: 24.8 - 0.13 = 24.67
+
+  // current wallet impl fee 0.14
+});
+
+test("demo: deposit max after withdraw raw 13", (t) => {
+  const coinList: TestCoin[] = [
+    [kudos`0.1`, 8],
+    [kudos`1`, 0],
+    [kudos`2`, 1],
+    [kudos`5`, 0],
+    [kudos`10`, 1],
+  ];
+  const result = testing_getMaxDepositAmountForAvailableCoins(
+    {
+      currency: "KUDOS",
+    },
+    {
+      coinAvailability: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
+      currentWireFeePerExchange: {
+        "2": kudos`0.01`,
+      },
+    },
+  );
+  t.is(Amounts.stringifyValue(result.effectiveAmount), "12.8");
+  t.is(Amounts.stringifyValue(result.rawAmount), "12.69");
+
+  // 8 x  0.1
+  // 1 x  0.2
+  // 1 x 10.0
+  // total effective 12.8
+  // deposit fee 10 x 0.01 = 0.10
+  // wire fee 0.01
+  // total raw: 12.8 - 0.11 = 12.69
+
+  // current wallet impl fee 0.14
+});
diff --git a/packages/taler-wallet-core/src/coinSelection.ts 
b/packages/taler-wallet-core/src/coinSelection.ts
index e6e7892ce..bf24a883a 100644
--- a/packages/taler-wallet-core/src/coinSelection.ts
+++ b/packages/taler-wallet-core/src/coinSelection.ts
@@ -38,6 +38,8 @@ import {
   DenominationInfo,
   ExchangeGlobalFees,
   ForcedCoinSel,
+  GetMaxDepositAmountRequest,
+  GetMaxDepositAmountResponse,
   j2s,
   Logger,
   parsePaytoUri,
@@ -180,18 +182,17 @@ async function internalSelectPayCoins(
   | undefined
 > {
   const { contractTermsAmount, depositFeeLimit } = req;
-  const [candidateDenoms, wireFeesPerExchange] = await selectPayCandidates(
-    wex,
-    tx,
-    {
-      restrictExchanges: req.restrictExchanges,
-      instructedAmount: req.contractTermsAmount,
-      restrictWireMethod: req.restrictWireMethod,
-      depositPaytoUri: req.depositPaytoUri,
-      requiredMinimumAge: req.requiredMinimumAge,
-      includePendingCoins,
-    },
-  );
+  const candidateRes = await selectPayCandidates(wex, tx, {
+    currency: Amounts.currencyOf(req.contractTermsAmount),
+    restrictExchanges: req.restrictExchanges,
+    restrictWireMethod: req.restrictWireMethod,
+    depositPaytoUri: req.depositPaytoUri,
+    requiredMinimumAge: req.requiredMinimumAge,
+    includePendingCoins,
+  });
+
+  const wireFeesPerExchange = candidateRes.currentWireFeePerExchange;
+  const candidateDenoms = candidateRes.coinAvailability;
 
   if (logger.shouldLogTrace()) {
     logger.trace(
@@ -589,7 +590,7 @@ export interface SelectGreedyRequest {
 
 function selectGreedy(
   req: SelectGreedyRequest,
-  candidateDenoms: AvailableDenom[],
+  candidateDenoms: AvailableCoinsOfDenom[],
   tally: CoinSelectionTally,
 ): SelResult | undefined {
   const selectedDenom: SelResult = {};
@@ -652,7 +653,7 @@ function selectGreedy(
 
 function selectForced(
   req: SelectPayCoinRequestNg,
-  candidateDenoms: AvailableDenom[],
+  candidateDenoms: AvailableCoinsOfDenom[],
 ): SelResult | undefined {
   const selectedDenom: SelResult = {};
 
@@ -713,7 +714,7 @@ export interface SelectPayCoinRequestNg {
   depositPaytoUri?: string;
 }
 
-export type AvailableDenom = DenominationInfo & {
+export type AvailableCoinsOfDenom = DenominationInfo & {
   maxAge: number;
   numAvailable: number;
 };
@@ -794,7 +795,7 @@ function checkExchangeAccepted(
 }
 
 interface SelectPayCandidatesRequest {
-  instructedAmount: AmountJson;
+  currency: string;
   restrictWireMethod: string | undefined;
   depositPaytoUri?: string;
   restrictExchanges: ExchangeRestrictionSpec | undefined;
@@ -808,18 +809,23 @@ interface SelectPayCandidatesRequest {
   includePendingCoins: boolean;
 }
 
+export interface PayCoinCandidates {
+  coinAvailability: AvailableCoinsOfDenom[];
+  currentWireFeePerExchange: Record<string, AmountJson>;
+}
+
 async function selectPayCandidates(
   wex: WalletExecutionContext,
   tx: WalletDbReadOnlyTransaction<
     ["exchanges", "coinAvailability", "exchangeDetails", "denominations"]
   >,
   req: SelectPayCandidatesRequest,
-): Promise<[AvailableDenom[], Record<string, AmountJson>]> {
+): Promise<PayCoinCandidates> {
   // FIXME: Use the existing helper (from balance.ts) to
   // get acceptable exchanges.
   logger.shouldLogTrace() &&
     logger.trace(`selecting available coin candidates for ${j2s(req)}`);
-  const denoms: AvailableDenom[] = [];
+  const denoms: AvailableCoinsOfDenom[] = [];
   const exchanges = await tx.exchanges.iter().toArray();
   const wfPerExchange: Record<string, AmountJson> = {};
   for (const exchange of exchanges) {
@@ -828,7 +834,7 @@ async function selectPayCandidates(
       exchange.baseUrl,
     );
     // 1. exchange has same currency
-    if (exchangeDetails?.currency !== req.instructedAmount.currency) {
+    if (exchangeDetails?.currency !== req.currency) {
       logger.shouldLogTrace() &&
         logger.trace(`skipping ${exchange.baseUrl} due to currency mismatch`);
       continue;
@@ -935,7 +941,10 @@ async function selectPayCandidates(
       Amounts.cmp(o1.feeDeposit, o2.feeDeposit) ||
       strcmp(o1.denomPubHash, o2.denomPubHash),
   );
-  return [denoms, wfPerExchange];
+  return {
+    coinAvailability: denoms,
+    currentWireFeePerExchange: wfPerExchange,
+  };
 }
 
 export interface PeerCoinSelectionDetails {
@@ -1072,7 +1081,7 @@ async function internalSelectPeerCoins(
   | undefined
 > {
   const candidatesRes = await selectPayCandidates(wex, tx, {
-    instructedAmount: req.instructedAmount,
+    currency: Amounts.currencyOf(req.instructedAmount),
     restrictExchanges: {
       auditors: [],
       exchanges: [
@@ -1085,7 +1094,7 @@ async function internalSelectPeerCoins(
     restrictWireMethod: undefined,
     includePendingCoins,
   });
-  const candidates = candidatesRes[0];
+  const candidates = candidatesRes.coinAvailability;
   if (logger.shouldLogTrace()) {
     logger.trace(`peer payment candidate coins: ${j2s(candidates)}`);
   }
@@ -1258,3 +1267,71 @@ export async function selectPeerCoins(
     },
   );
 }
+
+function getMaxDepositAmountForAvailableCoins(
+  req: GetMaxDepositAmountRequest,
+  candidateRes: PayCoinCandidates,
+): GetMaxDepositAmountResponse {
+  const wireFeeCoveredForExchange = new Set<string>();
+
+  let amountEffective = Amounts.zeroOfCurrency(req.currency);
+  let fees = Amounts.zeroOfCurrency(req.currency);
+
+  for (const cc of candidateRes.coinAvailability) {
+    if (!wireFeeCoveredForExchange.has(cc.exchangeBaseUrl)) {
+      fees = Amounts.add(
+        fees,
+        candidateRes.currentWireFeePerExchange[cc.exchangeBaseUrl],
+      ).amount;
+      wireFeeCoveredForExchange.add(cc.exchangeBaseUrl);
+    }
+
+    amountEffective = Amounts.add(
+      amountEffective,
+      Amounts.mult(cc.value, cc.numAvailable).amount,
+    ).amount;
+
+    fees = Amounts.add(
+      fees,
+      Amounts.mult(cc.feeDeposit, cc.numAvailable).amount,
+    ).amount;
+  }
+
+  return {
+    effectiveAmount: Amounts.stringify(amountEffective),
+    rawAmount: Amounts.stringify(Amounts.sub(amountEffective, fees).amount),
+  };
+}
+
+/**
+ * Only used for unit testing getMaxDepositAmountForAvailableCoins.
+ */
+export const testing_getMaxDepositAmountForAvailableCoins =
+  getMaxDepositAmountForAvailableCoins;
+
+export async function getMaxDepositAmount(
+  wex: WalletExecutionContext,
+  req: GetMaxDepositAmountRequest,
+): Promise<GetMaxDepositAmountResponse> {
+  return await wex.db.runReadOnlyTx(
+    {
+      storeNames: [
+        "exchanges",
+        "coinAvailability",
+        "denominations",
+        "exchangeDetails",
+      ],
+    },
+    async (tx): Promise<GetMaxDepositAmountResponse> => {
+      const candidateRes = await selectPayCandidates(wex, tx, {
+        currency: req.currency,
+        restrictExchanges: undefined,
+        restrictWireMethod: undefined,
+        depositPaytoUri: req.depositPaytoUri,
+        requiredMinimumAge: undefined,
+        includePendingCoins: true,
+      });
+      return getMaxDepositAmountForAvailableCoins(req, candidateRes);
+    },
+  );
+}
diff --git a/packages/taler-wallet-core/src/deposits.ts 
b/packages/taler-wallet-core/src/deposits.ts
index b27b0157f..0ca595e50 100644
--- a/packages/taler-wallet-core/src/deposits.ts
+++ b/packages/taler-wallet-core/src/deposits.ts
@@ -27,21 +27,21 @@ import {
   Amounts,
   BatchDepositRequestCoin,
   CancellationToken,
+  CheckDepositRequest,
+  CheckDepositResponse,
   CoinRefreshRequest,
   CreateDepositGroupRequest,
   CreateDepositGroupResponse,
   DepositGroupFees,
   DepositTransactionTrackingState,
   Duration,
+  Exchange,
   ExchangeBatchDepositRequest,
-  ExchangeHandle,
   ExchangeRefundRequest,
   HttpStatusCode,
   Logger,
   MerchantContractTerms,
   NotificationType,
-  CheckDepositRequest,
-  CheckDepositResponse,
   RefreshReason,
   SelectedProspectiveCoin,
   TalerError,
@@ -1740,7 +1740,7 @@ export async function internalCheckDepositGroup(
   const amount = Amounts.parseOrThrow(req.amount);
   const currency = Amounts.currencyOf(amount);
 
-  const exchangeInfos: ExchangeHandle[] = [];
+  const exchangeInfos: Exchange[] = [];
 
   await wex.db.runReadOnlyTx(
     { storeNames: ["exchangeDetails", "exchanges"] },
@@ -1753,6 +1753,7 @@ export async function internalCheckDepositGroup(
         }
         exchangeInfos.push({
           master_pub: details.masterPublicKey,
+          priority: 1,
           url: e.baseUrl,
         });
       }
@@ -1948,7 +1949,11 @@ export async function createDepositGroup(
   const wireSalt = encodeCrock(getRandomBytes(16));
   const wireHash = hashWire(req.depositPaytoUri, wireSalt);
   const contractTerms: MerchantContractTerms = {
-    exchanges: exchangeInfos,
+    exchanges: exchangeInfos.map((x) => ({
+      master_pub: x.master_pub,
+      priority: 1,
+      url: x.url,
+    })),
     amount: req.amount,
     max_fee: Amounts.stringify(amount),
     wire_method: depositPayto.targetType,
diff --git a/packages/taler-wallet-core/src/instructedAmountConversion.test.ts 
b/packages/taler-wallet-core/src/instructedAmountConversion.test.ts
index 03e702568..17c2439c7 100644
--- a/packages/taler-wallet-core/src/instructedAmountConversion.test.ts
+++ b/packages/taler-wallet-core/src/instructedAmountConversion.test.ts
@@ -26,7 +26,6 @@ import {
   CoinInfo,
   convertDepositAmountForAvailableCoins,
   convertWithdrawalAmountFromAvailableCoins,
-  getMaxDepositAmountForAvailableCoins,
 } from "./instructedAmountConversion.js";
 
 function makeCurrencyHelper(currency: string) {
@@ -254,76 +253,6 @@ test("deposit with wire fee raw 2", (t) => {
  *
  */
 
-test("deposit max 35", (t) => {
-  const coinList: Coin[] = [
-    [kudos`2`, 5],
-    [kudos`5`, 5],
-  ];
-  const result = getMaxDepositAmountForAvailableCoins(
-    {
-      list: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
-      exchanges: {
-        "2": {
-          wireFee: kudos`0.00`,
-          purseFee: kudos`0.00`,
-          creditDeadline: AbsoluteTime.never(),
-          debitDeadline: AbsoluteTime.never(),
-        },
-      },
-    },
-    "KUDOS",
-  );
-  t.is(Amounts.stringifyValue(result.raw), "34.9");
-  t.is(Amounts.stringifyValue(result.effective), "35");
-});
-
-test("deposit max 35 with wirefee", (t) => {
-  const coinList: Coin[] = [
-    [kudos`2`, 5],
-    [kudos`5`, 5],
-  ];
-  const result = getMaxDepositAmountForAvailableCoins(
-    {
-      list: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
-      exchanges: {
-        "2": {
-          wireFee: kudos`1`,
-          purseFee: kudos`0.00`,
-          creditDeadline: AbsoluteTime.never(),
-          debitDeadline: AbsoluteTime.never(),
-        },
-      },
-    },
-    "KUDOS",
-  );
-  t.is(Amounts.stringifyValue(result.raw), "33.9");
-  t.is(Amounts.stringifyValue(result.effective), "35");
-});
-
-test("deposit max repeated denom", (t) => {
-  const coinList: Coin[] = [
-    [kudos`2`, 1],
-    [kudos`2`, 1],
-    [kudos`5`, 1],
-  ];
-  const result = getMaxDepositAmountForAvailableCoins(
-    {
-      list: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
-      exchanges: {
-        "2": {
-          wireFee: kudos`0.00`,
-          purseFee: kudos`0.00`,
-          creditDeadline: AbsoluteTime.never(),
-          debitDeadline: AbsoluteTime.never(),
-        },
-      },
-    },
-    "KUDOS",
-  );
-  t.is(Amounts.stringifyValue(result.raw), "8.97");
-  t.is(Amounts.stringifyValue(result.effective), "9");
-});
-
 /**
  * Making a withdrawal with effective amount
  *
@@ -663,42 +592,6 @@ test("demo: withdraw raw 25", (t) => {
   //shows fee = 0.2
 });
 
-test("demo: deposit max after withdraw raw 25", (t) => {
-  const coinList: Coin[] = [
-    [kudos`0.1`, 8],
-    [kudos`1`, 0],
-    [kudos`2`, 2],
-    [kudos`5`, 0],
-    [kudos`10`, 2],
-  ];
-  const result = getMaxDepositAmountForAvailableCoins(
-    {
-      list: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
-      exchanges: {
-        one: {
-          wireFee: kudos`0.01`,
-          purseFee: kudos`0.00`,
-          creditDeadline: AbsoluteTime.never(),
-          debitDeadline: AbsoluteTime.never(),
-        },
-      },
-    },
-    "KUDOS",
-  );
-  t.is(Amounts.stringifyValue(result.effective), "24.8");
-  t.is(Amounts.stringifyValue(result.raw), "24.67");
-
-  // 8 x  0.1
-  // 2 x  0.2
-  // 2 x 10.0
-  // total effective 24.8
-  // deposit fee 12 x 0.01 = 0.12
-  // wire fee 0.01
-  // total raw: 24.8 - 0.13 = 24.67
-
-  // current wallet impl fee 0.14
-});
-
 test("demo: withdraw raw 13", (t) => {
   const coinList: Coin[] = [
     [kudos`0.1`, 0],
@@ -729,39 +622,3 @@ test("demo: withdraw raw 13", (t) => {
   //current wallet impl: hides the left in reserve fee
   //shows fee = 0.2
 });
-
-test("demo: deposit max after withdraw raw 13", (t) => {
-  const coinList: Coin[] = [
-    [kudos`0.1`, 8],
-    [kudos`1`, 0],
-    [kudos`2`, 1],
-    [kudos`5`, 0],
-    [kudos`10`, 1],
-  ];
-  const result = getMaxDepositAmountForAvailableCoins(
-    {
-      list: coinList.map(([v, t]) => defaultFeeConfig(v, t)),
-      exchanges: {
-        one: {
-          wireFee: kudos`0.01`,
-          purseFee: kudos`0.00`,
-          creditDeadline: AbsoluteTime.never(),
-          debitDeadline: AbsoluteTime.never(),
-        },
-      },
-    },
-    "KUDOS",
-  );
-  t.is(Amounts.stringifyValue(result.effective), "12.8");
-  t.is(Amounts.stringifyValue(result.raw), "12.69");
-
-  // 8 x  0.1
-  // 1 x  0.2
-  // 1 x 10.0
-  // total effective 12.8
-  // deposit fee 10 x 0.01 = 0.10
-  // wire fee 0.01
-  // total raw: 12.8 - 0.11 = 12.69
-
-  // current wallet impl fee 0.14
-});
diff --git a/packages/taler-wallet-core/src/instructedAmountConversion.ts 
b/packages/taler-wallet-core/src/instructedAmountConversion.ts
index cbdd643a0..c0f835dfa 100644
--- a/packages/taler-wallet-core/src/instructedAmountConversion.ts
+++ b/packages/taler-wallet-core/src/instructedAmountConversion.ts
@@ -23,7 +23,6 @@ import {
   Amounts,
   ConvertAmountRequest,
   Duration,
-  GetMaxDepositAmountRequest,
   TransactionAmountMode,
   TransactionType,
   checkDbInvariant,
@@ -429,47 +428,6 @@ export function convertDepositAmountForAvailableCoins(
   return result;
 }
 
-export async function getMaxDepositAmount(
-  wex: WalletExecutionContext,
-  req: GetMaxDepositAmountRequest,
-): Promise<AmountResponse> {
-  const denoms = await getAvailableCoins(
-    wex,
-    TransactionType.Deposit,
-    req.currency,
-    {},
-  );
-
-  const result = getMaxDepositAmountForAvailableCoins(denoms, req.currency);
-  return {
-    effectiveAmount: Amounts.stringify(result.effective),
-    rawAmount: Amounts.stringify(result.raw),
-  };
-}
-
-export function getMaxDepositAmountForAvailableCoins(
-  denoms: AvailableCoins,
-  currency: string,
-): AmountWithFee {
-  const zero = Amounts.zeroOfCurrency(currency);
-  if (!denoms.list.length) {
-    // no coins in the database
-    return { effective: zero, raw: zero };
-  }
-
-  const result = getTotalEffectiveAndRawForDeposit(
-    denoms.list.map((info) => {
-      return { info, size: info.totalAvailable ?? 0 };
-    }),
-    currency,
-  );
-
-  const wireFee = Object.values(denoms.exchanges)[0]?.wireFee ?? zero;
-  result.raw = Amounts.sub(result.raw, wireFee).amount;
-
-  return result;
-}
-
 export async function convertWithdrawalAmount(
   wex: WalletExecutionContext,
   req: ConvertAmountRequest,
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index a4ed7db1c..4b01cec60 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -133,6 +133,7 @@ import {
   codecForAny,
   codecForApplyDevExperiment,
   codecForCanonicalizeBaseUrlRequest,
+  codecForCheckDepositRequest,
   codecForCheckPayTemplateRequest,
   codecForCheckPeerPullPaymentRequest,
   codecForCheckPeerPushDebitRequest,
@@ -148,7 +149,6 @@ import {
   codecForFailTransactionRequest,
   codecForForceRefreshRequest,
   codecForForgetKnownBankAccounts,
-  codecForGetMaxDepositAmountRequest,
   codecForGetBalanceDetailRequest,
   codecForGetBankingChoicesForPaytoRequest,
   codecForGetContractTermsDetails,
@@ -157,6 +157,7 @@ import {
   codecForGetExchangeEntryByUrlRequest,
   codecForGetExchangeResourcesRequest,
   codecForGetExchangeTosRequest,
+  codecForGetMaxDepositAmountRequest,
   codecForGetQrCodesForPaytoRequest,
   codecForGetWithdrawalDetailsForAmountRequest,
   codecForGetWithdrawalDetailsForUri,
@@ -170,7 +171,6 @@ import {
   codecForListExchangesForScopedCurrencyRequest,
   codecForListKnownBankAccounts,
   codecForPrepareBankIntegratedWithdrawalRequest,
-  codecForCheckDepositRequest,
   codecForPreparePayRequest,
   codecForPreparePayTemplateRequest,
   codecForPreparePeerPullPaymentRequest,
@@ -233,6 +233,7 @@ import {
   setWalletDeviceId,
 } from "./backup/index.js";
 import { getBalanceDetail, getBalances } from "./balance.js";
+import { getMaxDepositAmount } from "./coinSelection.js";
 import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js";
 import {
   CryptoDispatcher,
@@ -276,10 +277,7 @@ import {
   listExchanges,
   lookupExchangeByUri,
 } from "./exchanges.js";
-import {
-  convertDepositAmount,
-  getMaxDepositAmount,
-} from "./instructedAmountConversion.js";
+import { convertDepositAmount } from "./instructedAmountConversion.js";
 import {
   ObservableDbAccess,
   ObservableTaskScheduler,

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]