From ee48a39eb370e65564317f7c77e2cd52e8a0c42f Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 14 Sep 2023 10:56:34 -0300 Subject: [PATCH] merchant payment --- .../src/util/coinSelection.test.ts | 103 ++++++++++++++---- .../src/util/coinSelection.ts | 5 +- 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/packages/taler-wallet-core/src/util/coinSelection.test.ts b/packages/taler-wallet-core/src/util/coinSelection.test.ts index 2a322c4a9..f809c4e60 100644 --- a/packages/taler-wallet-core/src/util/coinSelection.test.ts +++ b/packages/taler-wallet-core/src/util/coinSelection.test.ts @@ -24,23 +24,7 @@ import { TransactionAmountMode, } from "@gnu-taler/taler-util"; import test, { ExecutionContext } from "ava"; -import { AvailableDenom, testing_greedySelectPeer } from "./coinSelection.js" - -type Tester = { - deep: { - equal(another: T): ReturnType; - equals(another: T): ReturnType; - } -} - -function expect(t: ExecutionContext, thing: T): Tester { - return { - deep: { - equal: (another: T) => t.deepEqual(thing, another), - equals: (another: T) => t.deepEqual(thing, another), - }, - }; -} +import { AvailableDenom, testing_greedySelectPeer, testing_selectGreedy } from "./coinSelection.js" const inTheDistantFuture = AbsoluteTime.toProtocolTimestamp( AbsoluteTime.addDuration(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 })) @@ -49,7 +33,7 @@ const inThePast = AbsoluteTime.toProtocolTimestamp( AbsoluteTime.subtractDuraction(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 })) ) -test("should select the coin", (t) => { +test("p2p: should select the coin", (t) => { const instructedAmount = Amounts.parseOrThrow("LOCAL:2") const tally = { amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), @@ -84,7 +68,7 @@ test("should select the coin", (t) => { }); -test("should select 3 coins", (t) => { +test("p2p: should select 3 coins", (t) => { const instructedAmount = Amounts.parseOrThrow("LOCAL:20") const tally = { amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), @@ -123,7 +107,7 @@ test("should select 3 coins", (t) => { }); -test("can't select since the instructed amount is too high", (t) => { +test("p2p: can't select since the instructed amount is too high", (t) => { const instructedAmount = Amounts.parseOrThrow("LOCAL:60") const tally = { amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), @@ -151,6 +135,68 @@ test("can't select since the instructed amount is too high", (t) => { }); +test("pay: select one coin to pay with fee", (t) => { + const payment = Amounts.parseOrThrow("LOCAL:2") + const exchangeWireFee = Amounts.parseOrThrow("LOCAL:0.1") + const zero = Amounts.zeroOfCurrency(payment.currency) + const tally = { + amountPayRemaining: payment, + amountWireFeeLimitRemaining: zero, + amountDepositFeeLimitRemaining: zero, + customerDepositFees: zero, + customerWireFees: zero, + wireFeeCoveredForExchange: new Set(), + lastDepositFee: zero, + }; + const coins = testing_selectGreedy( + { + "auditors": [], + "exchanges": [ + { + "exchangeBaseUrl": "http://exchange.localhost/", + "exchangePub": "E5M8CGRDHXF1RCVP3B8TQCTDYNQ7T4XHWR5SVEQRGVVMVME41VJ0" + } + ], + "contractTermsAmount": payment, + "depositFeeLimit": zero, + "wireFeeAmortization": 1, + "wireFeeLimit": zero, + "prevPayCoins": [], + "wireMethod": "x-taler-bank" + }, + createCandidates([{ + amount: "LOCAL:10", + numAvailable: 5, + depositFee: "LOCAL:0.1", + fromExchange: "http://exchange.localhost/", + }]), + {"http://exchange.localhost/": exchangeWireFee}, + tally + ); + + expect(t, coins).deep.equal({ + "hash0;32;http://exchange.localhost/": { + exchangeBaseUrl: "http://exchange.localhost/", + denomPubHash: "hash0", + maxAge: 32, + contributions: [ + Amounts.parseOrThrow("LOCAL:2.2"), + ], + } + }); + + expect(t, tally).deep.equal({ + amountPayRemaining: Amounts.parseOrThrow("LOCAL:2"), + amountWireFeeLimitRemaining: zero, + amountDepositFeeLimitRemaining: zero, + customerDepositFees: zero, + customerWireFees: zero, + wireFeeCoveredForExchange: new Set(), + lastDepositFee: zero, + }); + +}); + @@ -179,3 +225,20 @@ function createCandidates(ar: {amount: AmountString, depositFee: AmountString, n } }) } + +type Tester = { + deep: { + equal(another: T): ReturnType; + equals(another: T): ReturnType; + } +} + +function expect(t: ExecutionContext, thing: T): Tester { + return { + deep: { + equal: (another: T) => t.deepEqual(thing, another), + equals: (another: T) => t.deepEqual(thing, another), + }, + }; +} + diff --git a/packages/taler-wallet-core/src/util/coinSelection.ts b/packages/taler-wallet-core/src/util/coinSelection.ts index 0885215dd..0b1be881f 100644 --- a/packages/taler-wallet-core/src/util/coinSelection.ts +++ b/packages/taler-wallet-core/src/util/coinSelection.ts @@ -419,6 +419,9 @@ interface SelResult { }; } +export function testing_selectGreedy(...args: Parameters): ReturnType{ + return selectGreedy(...args) +} function selectGreedy( req: SelectPayCoinRequestNg, candidateDenoms: AvailableDenom[], @@ -930,7 +933,7 @@ function greedySelectPeer( ).amount; tally.lastDepositFee = Amounts.parseOrThrow(denom.feeDeposit); - + contributions.push(coinSpend); } if (contributions.length > 0) {