diff options
author | Özgür Kesim <oec-taler@kesim.org> | 2023-09-14 12:13:35 +0200 |
---|---|---|
committer | Özgür Kesim <oec-taler@kesim.org> | 2023-09-14 12:13:35 +0200 |
commit | 35611f0bf9cf67638b171c2a300fab1797d3d8f0 (patch) | |
tree | d067d5d62ac2fd0d88b25d2c759cc2caa9485c00 /packages/taler-wallet-core/src/util/coinSelection.test.ts | |
parent | 64c19c8cde56699ab4aaf05a1ac6fea6a4e0e4ba (diff) | |
parent | a5960665245c4ffb625dd16923019e8c62c20159 (diff) |
Merge branch 'master' into age-withdraw
Diffstat (limited to 'packages/taler-wallet-core/src/util/coinSelection.test.ts')
-rw-r--r-- | packages/taler-wallet-core/src/util/coinSelection.test.ts | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/packages/taler-wallet-core/src/util/coinSelection.test.ts b/packages/taler-wallet-core/src/util/coinSelection.test.ts index b907eb160..2a322c4a9 100644 --- a/packages/taler-wallet-core/src/util/coinSelection.test.ts +++ b/packages/taler-wallet-core/src/util/coinSelection.test.ts @@ -17,9 +17,165 @@ import { AbsoluteTime, AgeRestriction, AmountJson, + AmountString, Amounts, + DenomKeyType, Duration, TransactionAmountMode, } from "@gnu-taler/taler-util"; import test, { ExecutionContext } from "ava"; +import { AvailableDenom, testing_greedySelectPeer } 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( + AbsoluteTime.addDuration(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 })) +) +const inThePast = AbsoluteTime.toProtocolTimestamp( + AbsoluteTime.subtractDuraction(AbsoluteTime.now(), Duration.fromSpec({ hours: 1 })) +) + +test("should select the coin", (t) => { + const instructedAmount = Amounts.parseOrThrow("LOCAL:2") + const tally = { + amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), + depositFeesAcc: Amounts.zeroOfCurrency(instructedAmount.currency), + lastDepositFee: Amounts.zeroOfCurrency(instructedAmount.currency), + }; + const coins = testing_greedySelectPeer( + createCandidates([{ + amount: "LOCAL:10", + numAvailable: 5, + depositFee: "LOCAL:0.1", + fromExchange: "http://exchange.localhost/", + }]), + instructedAmount, + tally + ); + + expect(t, coins).deep.equal({ + "hash0;32;http://exchange.localhost/": { + exchangeBaseUrl: "http://exchange.localhost/", + denomPubHash: "hash0", + maxAge: 32, + contributions: [Amounts.parseOrThrow("LOCAL:2")], + } + }); + + expect(t, tally).deep.equal({ + amountAcc: Amounts.parseOrThrow("LOCAL:2"), + depositFeesAcc: Amounts.parseOrThrow("LOCAL:0.1"), + lastDepositFee: Amounts.parseOrThrow("LOCAL:0.1"), + }); + +}); + +test("should select 3 coins", (t) => { + const instructedAmount = Amounts.parseOrThrow("LOCAL:20") + const tally = { + amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), + depositFeesAcc: Amounts.zeroOfCurrency(instructedAmount.currency), + lastDepositFee: Amounts.zeroOfCurrency(instructedAmount.currency), + }; + const coins = testing_greedySelectPeer( + createCandidates([{ + amount: "LOCAL:10", + numAvailable: 5, + depositFee: "LOCAL:0.1", + fromExchange: "http://exchange.localhost/", + }]), + instructedAmount, + tally + ); + + expect(t, coins).deep.equal({ + "hash0;32;http://exchange.localhost/": { + exchangeBaseUrl: "http://exchange.localhost/", + denomPubHash: "hash0", + maxAge: 32, + contributions: [ + Amounts.parseOrThrow("LOCAL:9.9"), + Amounts.parseOrThrow("LOCAL:9.9"), + Amounts.parseOrThrow("LOCAL:0.2") + ], + } + }); + + expect(t, tally).deep.equal({ + amountAcc: Amounts.parseOrThrow("LOCAL:20"), + depositFeesAcc: Amounts.parseOrThrow("LOCAL:0.3"), + lastDepositFee: Amounts.parseOrThrow("LOCAL:0.1"), + }); + +}); + +test("can't select since the instructed amount is too high", (t) => { + const instructedAmount = Amounts.parseOrThrow("LOCAL:60") + const tally = { + amountAcc: Amounts.zeroOfCurrency(instructedAmount.currency), + depositFeesAcc: Amounts.zeroOfCurrency(instructedAmount.currency), + lastDepositFee: Amounts.zeroOfCurrency(instructedAmount.currency), + }; + const coins = testing_greedySelectPeer( + createCandidates([{ + amount: "LOCAL:10", + numAvailable: 5, + depositFee: "LOCAL:0.1", + fromExchange: "http://exchange.localhost/", + }]), + instructedAmount, + tally + ); + + expect(t, coins).deep.equal(undefined); + + expect(t, tally).deep.equal({ + amountAcc: Amounts.parseOrThrow("LOCAL:49.5"), + depositFeesAcc: Amounts.parseOrThrow("LOCAL:0.5"), + lastDepositFee: Amounts.parseOrThrow("LOCAL:0.1"), + }); + +}); + + + + +function createCandidates(ar: {amount: AmountString, depositFee: AmountString, numAvailable: number, fromExchange: string}[]): AvailableDenom[] { + return ar.map((r,idx) => { + return { + "denomPub": { + "age_mask": 0, + "cipher": DenomKeyType.Rsa, + "rsa_public_key": "PPP" + }, + "denomPubHash": `hash${idx}`, + "value": r.amount, + "feeDeposit": r.depositFee, + "feeRefresh": "LOCAL:0", + "feeRefund": "LOCAL:0", + "feeWithdraw": "LOCAL:0", + "stampExpireDeposit": inTheDistantFuture, + "stampExpireLegal": inTheDistantFuture, + "stampExpireWithdraw": inTheDistantFuture, + "stampStart": inThePast, + "exchangeBaseUrl": r.fromExchange, + "numAvailable": r.numAvailable, + "maxAge": 32, + + } + }) +} |