merchant payment

This commit is contained in:
Sebastian 2023-09-14 10:56:34 -03:00
parent a596066524
commit ee48a39eb3
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
2 changed files with 87 additions and 21 deletions

View File

@ -24,23 +24,7 @@ import {
TransactionAmountMode, TransactionAmountMode,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import test, { ExecutionContext } from "ava"; import test, { ExecutionContext } from "ava";
import { AvailableDenom, testing_greedySelectPeer } from "./coinSelection.js" import { AvailableDenom, testing_greedySelectPeer, testing_selectGreedy } from "./coinSelection.js"
type Tester<T> = {
deep: {
equal(another: T): ReturnType<ExecutionContext["deepEqual"]>;
equals(another: T): ReturnType<ExecutionContext["deepEqual"]>;
}
}
function expect<T>(t: ExecutionContext, thing: T): Tester<T> {
return {
deep: {
equal: (another: T) => t.deepEqual(thing, another),
equals: (another: T) => t.deepEqual(thing, another),
},
};
}
const inTheDistantFuture = AbsoluteTime.toProtocolTimestamp( const inTheDistantFuture = AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.addDuration(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 })) AbsoluteTime.addDuration(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 }))
@ -49,7 +33,7 @@ const inThePast = AbsoluteTime.toProtocolTimestamp(
AbsoluteTime.subtractDuraction(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 })) 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 instructedAmount = Amounts.parseOrThrow("LOCAL:2")
const tally = { const tally = {
amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), 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 instructedAmount = Amounts.parseOrThrow("LOCAL:20")
const tally = { const tally = {
amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), 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 instructedAmount = Amounts.parseOrThrow("LOCAL:60")
const tally = { const tally = {
amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), 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<string>(),
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<T> = {
deep: {
equal(another: T): ReturnType<ExecutionContext["deepEqual"]>;
equals(another: T): ReturnType<ExecutionContext["deepEqual"]>;
}
}
function expect<T>(t: ExecutionContext, thing: T): Tester<T> {
return {
deep: {
equal: (another: T) => t.deepEqual(thing, another),
equals: (another: T) => t.deepEqual(thing, another),
},
};
}

View File

@ -419,6 +419,9 @@ interface SelResult {
}; };
} }
export function testing_selectGreedy(...args: Parameters<typeof selectGreedy>): ReturnType<typeof selectGreedy>{
return selectGreedy(...args)
}
function selectGreedy( function selectGreedy(
req: SelectPayCoinRequestNg, req: SelectPayCoinRequestNg,
candidateDenoms: AvailableDenom[], candidateDenoms: AvailableDenom[],
@ -930,7 +933,7 @@ function greedySelectPeer(
).amount; ).amount;
tally.lastDepositFee = Amounts.parseOrThrow(denom.feeDeposit); tally.lastDepositFee = Amounts.parseOrThrow(denom.feeDeposit);
contributions.push(coinSpend); contributions.push(coinSpend);
} }
if (contributions.length > 0) { if (contributions.length > 0) {