taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 7595228344db6e6a9ce934c1cb1a068153ced89f
parent 1397e87627bce6ecd7a2739670eb2f5eab3b99dc
Author: Antoine A <>
Date:   Thu, 10 Apr 2025 20:20:14 +0200

harness: clean and improve peer tests

Diffstat:
Mpackages/taler-harness/src/integrationtests/test-peer-pull-large.ts | 158++++++++++++++++++++++++-------------------------------------------------------
Apackages/taler-harness/src/integrationtests/test-peer-pull.ts | 214+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dpackages/taler-harness/src/integrationtests/test-peer-push-abort.ts | 92-------------------------------------------------------------------------------
Mpackages/taler-harness/src/integrationtests/test-peer-push-large.ts | 148++++++++++++++++++++++++++++++++-----------------------------------------------
Apackages/taler-harness/src/integrationtests/test-peer-push.ts | 358+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dpackages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts | 311-------------------------------------------------------------------------------
Dpackages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts | 287-------------------------------------------------------------------------------
Mpackages/taler-harness/src/integrationtests/testrunner.ts | 10++++------
8 files changed, 683 insertions(+), 895 deletions(-)

diff --git a/packages/taler-harness/src/integrationtests/test-peer-pull-large.ts b/packages/taler-harness/src/integrationtests/test-peer-pull-large.ts @@ -14,33 +14,22 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -/** - * Imports. - */ import { AbsoluteTime, - AmountString, Duration, - j2s, - NotificationType, - TalerCorebankApiClient, TransactionMajorState, TransactionMinorState, TransactionType, - WalletNotification, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { CoinConfig } from "../harness/denomStructures.js"; import { - createSimpleTestkudosEnvironmentV2, + createSimpleTestkudosEnvironmentV3, createWalletDaemonWithClient, withdrawViaBankV3, } from "../harness/environments.js"; import { - BankServiceHandle, - ExchangeService, GlobalTestState, - WalletClient, } from "../harness/harness.js"; const coinCommon = { @@ -63,6 +52,13 @@ const coinConfigList: CoinConfig[] = [ }, ]; +const purse_expiration = AbsoluteTime.toProtocolTimestamp( + AbsoluteTime.addDuration( + AbsoluteTime.now(), + Duration.fromSpec({ days: 2 }), + ), +); + /** * Test peer pull payments with a large number of coins. * @@ -71,135 +67,77 @@ const coinConfigList: CoinConfig[] = [ */ export async function runPeerPullLargeTest(t: GlobalTestState) { // Set up test environment - - const { bank, exchange } = await createSimpleTestkudosEnvironmentV2( - t, - coinConfigList, - ); - - let allW1Notifications: WalletNotification[] = []; - let allW2Notifications: WalletNotification[] = []; - - const w1 = await createWalletDaemonWithClient(t, { - name: "w1", - persistent: true, - handleNotification(wn) { - allW1Notifications.push(wn); - }, - }); - const w2 = await createWalletDaemonWithClient(t, { - name: "w2", - persistent: true, - handleNotification(wn) { - allW2Notifications.push(wn); - }, - }); + const [ + { walletClient: wallet1, bankClient, exchange }, + { walletClient: wallet2 }, + ] = await Promise.all([ + createSimpleTestkudosEnvironmentV3(t, coinConfigList), + createWalletDaemonWithClient(t, { + name: "w2" + }) + ]); // Withdraw digital cash into the wallet. - const wallet1 = w1.walletClient; - const wallet2 = w2.walletClient; - - await checkNormalPeerPull(t, bank, exchange, wallet1, wallet2); -} - -async function checkNormalPeerPull( - t: GlobalTestState, - bank: BankServiceHandle, - exchange: ExchangeService, - wallet1: WalletClient, - wallet2: WalletClient, -): Promise<void> { - t.logStep("starting withdrawal"); - const bankClient = new TalerCorebankApiClient(bank.corebankApiBaseUrl); const withdrawRes = await withdrawViaBankV3(t, { walletClient: wallet2, bankClient, exchange, amount: "TESTKUDOS:500", }); - await withdrawRes.withdrawalFinishedCond; - t.logStep("finished withdrawal"); - - const purseExpiration = AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration( - AbsoluteTime.now(), - Duration.fromSpec({ days: 2 }), - ), - ); - - const resp = await wallet1.client.call( + const initiate = await wallet1.call( WalletApiOperation.InitiatePeerPullCredit, { exchangeBaseUrl: exchange.baseUrl, partialContractTerms: { summary: "Hello World", - amount: "TESTKUDOS:200" as AmountString, - purse_expiration: purseExpiration, + amount: "TESTKUDOS:200", + purse_expiration, }, }, ); - const peerPullCreditReadyCond = wallet1.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === resp.transactionId && - x.newTxState.major === TransactionMajorState.Pending && - x.newTxState.minor === TransactionMinorState.Ready, - ); - - await peerPullCreditReadyCond; + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready + }, + }); - const creditTx = await wallet1.call(WalletApiOperation.GetTransactionById, { - transactionId: resp.transactionId, + const tx = await wallet1.call(WalletApiOperation.GetTransactionById, { + transactionId: initiate.transactionId, }); - t.assertDeepEqual(creditTx.type, TransactionType.PeerPullCredit); - t.assertTrue(!!creditTx.talerUri); + t.assertDeepEqual(tx.type, TransactionType.PeerPullCredit); + t.assertTrue(!!tx.talerUri); - const checkResp = await wallet2.client.call( + const prepare = await wallet2.client.call( WalletApiOperation.PreparePeerPullDebit, { - talerUri: creditTx.talerUri, + talerUri: tx.talerUri, }, ); - console.log(`checkResp: ${j2s(checkResp)}`); - - const peerPullCreditDoneCond = wallet1.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === resp.transactionId && - x.newTxState.major === TransactionMajorState.Done, - ); - - const peerPullDebitDoneCond = wallet2.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === checkResp.transactionId && - x.newTxState.major === TransactionMajorState.Done, - ); - await wallet2.client.call(WalletApiOperation.ConfirmPeerPullDebit, { - transactionId: checkResp.transactionId, + transactionId: prepare.transactionId, }); - await peerPullCreditDoneCond; - await peerPullDebitDoneCond; - - const txn1 = await wallet1.client.call( - WalletApiOperation.GetTransactions, - {}, - ); - - const txn2 = await wallet2.client.call( - WalletApiOperation.GetTransactions, - {}, - ); - - console.log(`txn1: ${j2s(txn1)}`); - console.log(`txn2: ${j2s(txn2)}`); + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }), + wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }) + ]); } runPeerPullLargeTest.suites = ["wallet", "slow"]; diff --git a/packages/taler-harness/src/integrationtests/test-peer-pull.ts b/packages/taler-harness/src/integrationtests/test-peer-pull.ts @@ -0,0 +1,214 @@ +/* + This file is part of GNU Taler + (C) 2020 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { + AbsoluteTime, + AmountString, + Duration, + TransactionMajorState, + TransactionMinorState, + TransactionType, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { + createSimpleTestkudosEnvironmentV3, + createWalletDaemonWithClient, + withdrawViaBankV3, +} from "../harness/environments.js"; +import { + GlobalTestState, +} from "../harness/harness.js"; + +const purse_expiration = AbsoluteTime.toProtocolTimestamp( + AbsoluteTime.addDuration( + AbsoluteTime.now(), + Duration.fromSpec({ days: 2 }), + ), +); + +/** + * Run a test for basic peer-pull payments. + */ +export async function runPeerPullTest(t: GlobalTestState) { + const [ + { walletClient: wallet1, bankClient, exchange }, + { walletClient: wallet2 }, + ] = await Promise.all([ + createSimpleTestkudosEnvironmentV3(t), + createWalletDaemonWithClient(t, { + name: "w2" + }) + ]); + + // Withdraw digital cash into the wallet. + const withdrawRes = await withdrawViaBankV3(t, { + walletClient: wallet2, + bankClient, + exchange, + amount: "TESTKUDOS:20", + }); + await withdrawRes.withdrawalFinishedCond; + + t.logStep("Check debit amount logic"); + { + await wallet1.call(WalletApiOperation.AddExchange, { + exchangeBaseUrl: exchange.baseUrl + }); + const [ + checkfive, + checkzero + ] = await Promise.all([ + wallet1.client.call( + WalletApiOperation.CheckPeerPullCredit, + { + amount: "TESTKUDOS:5" as AmountString, + exchangeBaseUrl: exchange.baseUrl, + }, + ), + wallet1.client.call( + WalletApiOperation.CheckPeerPullCredit, + { + amount: "TESTKUDOS:0" as AmountString, + exchangeBaseUrl: exchange.baseUrl, + }, + ), + ]); + + t.assertDeepEqual(checkfive.amountRaw, "TESTKUDOS:5"); + + t.assertDeepEqual(checkzero.amountRaw, "TESTKUDOS:0"); + t.assertDeepEqual(checkzero.amountEffective, "TESTKUDOS:0"); + t.assertDeepEqual(checkzero.numCoins, 0); + } + + t.logStep("P2P pull confirm"); + { + const initiate = await wallet1.client.call( + WalletApiOperation.InitiatePeerPullCredit, + { + exchangeBaseUrl: exchange.baseUrl, + partialContractTerms: { + summary: "Hello World", + amount: "TESTKUDOS:5", + purse_expiration, + }, + }, + ); + + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready + }, + }); + + const tx = await wallet1.call(WalletApiOperation.GetTransactionById, { + transactionId: initiate.transactionId, + }); + + t.assertDeepEqual(tx.type, TransactionType.PeerPullCredit); + t.assertTrue(!!tx.talerUri); + + const prepare = await wallet2.client.call( + WalletApiOperation.PreparePeerPullDebit, + { + talerUri: tx.talerUri, + }, + ); + + await wallet2.client.call(WalletApiOperation.ConfirmPeerPullDebit, { + transactionId: prepare.transactionId, + }); + + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }), + wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }) + ]); + } + + t.logStep("P2P pull abort"); + { + const initiate = await wallet1.client.call( + WalletApiOperation.InitiatePeerPullCredit, + { + exchangeBaseUrl: exchange.baseUrl, + partialContractTerms: { + summary: "Hello World", + amount: "TESTKUDOS:5" as AmountString, + purse_expiration, + }, + }, + ); + + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready, + }, + }); + + const tx = await wallet1.call(WalletApiOperation.GetTransactionById, { + transactionId: initiate.transactionId, + }); + + t.assertDeepEqual(tx.type, TransactionType.PeerPullCredit); + t.assertTrue(!!tx.talerUri); + + const prepare = await wallet2.client.call( + WalletApiOperation.PreparePeerPullDebit, + { + talerUri: tx.talerUri, + }, + ); + + await wallet1.call(WalletApiOperation.AbortTransaction, { + transactionId: initiate.transactionId, + }); + + await wallet2.client.call(WalletApiOperation.ConfirmPeerPullDebit, { + transactionId: prepare.transactionId, + }); + + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Aborted, + }, + }), + wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Aborted, + }, + }) + ]); + } +} + +runPeerPullTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/test-peer-push-abort.ts b/packages/taler-harness/src/integrationtests/test-peer-push-abort.ts @@ -1,92 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2020 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** - * Imports. - */ -import { - AbsoluteTime, - Duration, - TransactionMajorState, - TransactionMinorState, -} from "@gnu-taler/taler-util"; -import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; -import { - createSimpleTestkudosEnvironmentV3, - withdrawViaBankV3, -} from "../harness/environments.js"; -import { GlobalTestState } from "../harness/harness.js"; - -/** - * Run a test for aborting peer-push payments. - */ -export async function runPeerPushAbortTest(t: GlobalTestState) { - const { bank, bankClient, exchange, walletClient } = - await createSimpleTestkudosEnvironmentV3(t); - - const wres = await withdrawViaBankV3(t, { - walletClient, - bankClient, - exchange, - amount: "TESTKUDOS:20", - }); - - await wres.withdrawalFinishedCond; - - const purse_expiration = AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration( - AbsoluteTime.now(), - Duration.fromSpec({ days: 2 }), - ), - ); - - const pdi = await walletClient.call( - WalletApiOperation.InitiatePeerPushDebit, - { - partialContractTerms: { - amount: "TESTKUDOS:7", - summary: "Hi!", - purse_expiration, - }, - }, - ); - - await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { - transactionId: pdi.transactionId, - txState: { - major: TransactionMajorState.Pending, - minor: TransactionMinorState.Ready, - }, - }); - - await walletClient.call(WalletApiOperation.AbortTransaction, { - transactionId: pdi.transactionId, - }); - - await walletClient.call(WalletApiOperation.TestingWaitTransactionState, { - transactionId: pdi.transactionId, - txState: { - major: TransactionMajorState.Aborted, - }, - }); - - await walletClient.call(WalletApiOperation.TestingWaitRefreshesFinal, {}); - - const bal = await walletClient.call(WalletApiOperation.GetBalances, {}); - t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:18.88"); -} - -runPeerPushAbortTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/test-peer-push-large.ts b/packages/taler-harness/src/integrationtests/test-peer-push-large.ts @@ -1,6 +1,6 @@ /* This file is part of GNU Taler - (C) 2020 Taler Systems S.A. + (C) 2020-2025 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -14,25 +14,17 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -/** - * Imports. - */ import { AbsoluteTime, - AmountString, Duration, - NotificationType, - TalerCorebankApiClient, TransactionMajorState, TransactionMinorState, TransactionType, - WalletNotification, - j2s, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { CoinConfig } from "../harness/denomStructures.js"; import { - createSimpleTestkudosEnvironmentV2, + createSimpleTestkudosEnvironmentV3, createWalletDaemonWithClient, withdrawViaBankV3, } from "../harness/environments.js"; @@ -58,126 +50,104 @@ const coinConfigList: CoinConfig[] = [ }, ]; +const purse_expiration = AbsoluteTime.toProtocolTimestamp( + AbsoluteTime.addDuration( + AbsoluteTime.now(), + Duration.fromSpec({ days: 2 }), + ), +); + /** - * Run a test for a multi-batch peer push payment. + * Test peer push payments with a large number of coins. + * + * Since we use an artificallly large number of coins, this + * test is a bit slower than other tests. */ export async function runPeerPushLargeTest(t: GlobalTestState) { - const { bank, exchange } = await createSimpleTestkudosEnvironmentV2( - t, - coinConfigList, - ); - - let allW1Notifications: WalletNotification[] = []; - let allW2Notifications: WalletNotification[] = []; - - const w1 = await createWalletDaemonWithClient(t, { - name: "w1", - handleNotification(wn) { - allW1Notifications.push(wn); - }, - }); - const w2 = await createWalletDaemonWithClient(t, { - name: "w2", - handleNotification(wn) { - allW2Notifications.push(wn); - }, - }); + // Set up test environment + const [ + { walletClient: wallet1, bankClient, exchange }, + { walletClient: wallet2 }, + ] = await Promise.all([ + createSimpleTestkudosEnvironmentV3(t, coinConfigList), + createWalletDaemonWithClient(t, { + name: "w2" + }) + ]); // Withdraw digital cash into the wallet. - - const bankClient = new TalerCorebankApiClient(bank.baseUrl); - const withdrawRes = await withdrawViaBankV3(t, { - walletClient: w1.walletClient, + walletClient: wallet1, bankClient, exchange, amount: "TESTKUDOS:300", }); - await withdrawRes.withdrawalFinishedCond; - const purse_expiration = AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration( - AbsoluteTime.now(), - Duration.fromSpec({ days: 2 }), - ), - ); - - const checkResp0 = await w1.walletClient.call( + const check = await wallet1.call( WalletApiOperation.CheckPeerPushDebit, { - amount: "TESTKUDOS:200" as AmountString, + amount: "TESTKUDOS:200", }, ); + t.assertAmountEquals(check.amountEffective, "TESTKUDOS:200"); - t.assertAmountEquals(checkResp0.amountEffective, "TESTKUDOS:200"); - - const resp = await w1.walletClient.call( + const initiate = await wallet1.call( WalletApiOperation.InitiatePeerPushDebit, { partialContractTerms: { summary: "Hello World 🥺", - amount: "TESTKUDOS:200" as AmountString, + amount: "TESTKUDOS:200", purse_expiration, }, }, ); - console.log(resp); - - const peerPushReadyCond = w1.walletClient.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.newTxState.major === TransactionMajorState.Pending && - x.newTxState.minor === TransactionMinorState.Ready && - x.transactionId === resp.transactionId, - ); - - await peerPushReadyCond; + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready + }, + }); - const txDetails = await w1.walletClient.call( + const tx = await wallet1.call( WalletApiOperation.GetTransactionById, { - transactionId: resp.transactionId, + transactionId: initiate.transactionId, }, ); - t.assertDeepEqual(txDetails.type, TransactionType.PeerPushDebit); - t.assertTrue(!!txDetails.talerUri); + t.assertDeepEqual(tx.type, TransactionType.PeerPushDebit); + t.assertTrue(!!tx.talerUri); - const checkResp = await w2.walletClient.call( + const prepare = await wallet2.call( WalletApiOperation.PreparePeerPushCredit, { - talerUri: txDetails.talerUri, + talerUri: tx.talerUri, }, ); - console.log(checkResp); - - const acceptResp = await w2.walletClient.call( + await wallet2.call( WalletApiOperation.ConfirmPeerPushCredit, { - transactionId: checkResp.transactionId, + transactionId: prepare.transactionId, }, ); - console.log(acceptResp); - - await w2.walletClient.call( - WalletApiOperation.TestingWaitTransactionsFinal, - {}, - ); - - const txn1 = await w1.walletClient.call( - WalletApiOperation.GetTransactions, - {}, - ); - const txn2 = await w2.walletClient.call( - WalletApiOperation.GetTransactions, - {}, - ); - - console.log(`txn1: ${j2s(txn1)}`); - console.log(`txn2: ${j2s(txn2)}`); + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }), + wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }) + ]); } -runPeerPushLargeTest.suites = ["wallet"]; +runPeerPushLargeTest.suites = ["wallet", "slow"]; diff --git a/packages/taler-harness/src/integrationtests/test-peer-push.ts b/packages/taler-harness/src/integrationtests/test-peer-push.ts @@ -0,0 +1,358 @@ +/* + This file is part of GNU Taler + (C) 2020-2025 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +import { + AbsoluteTime, + Duration, + TalerErrorCode, + TransactionMajorState, + TransactionMinorState, + TransactionType, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { + createSimpleTestkudosEnvironmentV3, + createWalletDaemonWithClient, + withdrawViaBankV3, +} from "../harness/environments.js"; +import { GlobalTestState } from "../harness/harness.js"; + +const purse_expiration = AbsoluteTime.toProtocolTimestamp( + AbsoluteTime.addDuration( + AbsoluteTime.now(), + Duration.fromSpec({ days: 2 }), + ), +); + +/** + * Run a test for basic peer-push payments. + */ +export async function runPeerPushTest(t: GlobalTestState) { + const [ + { walletClient: wallet1, bankClient, exchange }, + { walletClient: wallet2 }, + ] = await Promise.all([ + createSimpleTestkudosEnvironmentV3(t), + createWalletDaemonWithClient(t, { + name: "w2" + }) + ]); + + // Withdraw digital cash into the wallet. + const withdrawRes = await withdrawViaBankV3(t, { + walletClient: wallet1, + bankClient, + exchange, + amount: "TESTKUDOS:20", + }); + await withdrawRes.withdrawalFinishedCond; + + t.logStep("Check debit amount logic"); + { + const [ + maxpeer, + checkzero, + checkfive + ] = await Promise.all([ + wallet1.call( + WalletApiOperation.GetMaxPeerPushDebitAmount, + { + currency: "TESTKUDOS" + } + ), + wallet1.call( + WalletApiOperation.CheckPeerPushDebit, + { + amount: "TESTKUDOS:0" + } + ), + wallet1.call( + WalletApiOperation.CheckPeerPushDebit, + { + amount: "TESTKUDOS:5" + } + ) + ]); + + t.assertDeepEqual(maxpeer.exchangeBaseUrl, exchange.baseUrl); + t.assertAmountEquals(maxpeer.rawAmount, "TESTKUDOS:19.1"); + t.assertAmountEquals(maxpeer.effectiveAmount, "TESTKUDOS:19.53"); + + t.assertAmountEquals(checkzero.amountRaw, "TESTKUDOS:0"); + t.assertAmountEquals(checkzero.amountEffective, "TESTKUDOS:0"); + + t.assertAmountEquals(checkfive.amountRaw, "TESTKUDOS:5"); + t.assertAmountEquals(checkfive.amountEffective, "TESTKUDOS:5.49"); + } + + t.logStep("P2P push confirm"); + { + const initiate = await wallet1.call( + WalletApiOperation.InitiatePeerPushDebit, + { + partialContractTerms: { + summary: "Hello World 🥺", + amount: "TESTKUDOS:5", + purse_expiration, + }, + }, + ); + + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready + }, + }); + + // Check balance update + { + const bal = await wallet1.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(bal.balances[0].pendingOutgoing, "TESTKUDOS:5.49"); + } + + const tx = await wallet1.call( + WalletApiOperation.GetTransactionById, + { transactionId: initiate.transactionId } + ); + t.assertDeepEqual(tx.type, TransactionType.PeerPushDebit); + t.assertTrue(!!tx.talerUri); + + const prepare = await wallet2.call( + WalletApiOperation.PreparePeerPushCredit, + { talerUri: tx.talerUri } + ); + { + const idempotent = await wallet2.call( + WalletApiOperation.PreparePeerPushCredit, + { talerUri: tx.talerUri } + ); + t.assertTrue(prepare.transactionId === idempotent.transactionId); + } + + await wallet2.call( + WalletApiOperation.ConfirmPeerPushCredit, + { transactionId: prepare.transactionId } + ); + await wallet2.call( + WalletApiOperation.ConfirmPeerPushCredit, + { transactionId: prepare.transactionId } + ); + + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }), + wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + }) + ]); + + const bal = await wallet1.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:14.04"); + + + // Check wallet1 scan after completion + const reprepare1 = await wallet1.call( + WalletApiOperation.PreparePeerPushCredit, + { talerUri: tx.talerUri } + ); // FIXME this should fails + await wallet1.call( + WalletApiOperation.ConfirmPeerPushCredit, + { transactionId: reprepare1.transactionId } + ); + // FIXME this should fail + + + // Check wallet2 rescan after completion + const reprepare2 = await wallet2.call( + WalletApiOperation.PreparePeerPushCredit, + { talerUri: tx.talerUri } + ); + t.assertTrue(prepare.transactionId === reprepare2.transactionId) + } + + t.logStep("P2P push insufficient balance"); + { + const ex1 = await t.assertThrowsTalerErrorAsync( + wallet1.call(WalletApiOperation.InitiatePeerPushDebit, { + partialContractTerms: { + summary: "(this will fail)", + amount: "TESTKUDOS:15", + purse_expiration, + }, + }) + ); + t.assertTrue(ex1.errorDetail.code === TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION); + // FIXME propagate the error correctly + // t.assertTrue(ex1.errorDetail.code === TalerErrorCode.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE); + } + + t.logStep("P2P push abort"); + { + const initiate = await wallet1.call( + WalletApiOperation.InitiatePeerPushDebit, + { + partialContractTerms: { + amount: "TESTKUDOS:7", + summary: "Hi!", + purse_expiration, + }, + }, + ); + + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready, + }, + }); + + const tx = await wallet1.call( + WalletApiOperation.GetTransactionById, + { + transactionId: initiate.transactionId, + }, + ); + t.assertDeepEqual(tx.type, TransactionType.PeerPushDebit); + t.assertTrue(!!tx.talerUri); + + const prepare = await wallet2.client.call( + WalletApiOperation.PreparePeerPushCredit, + { + talerUri: tx.talerUri, + }, + ); + + await wallet1.call(WalletApiOperation.AbortTransaction, { + transactionId: initiate.transactionId, + }); + + await wallet2.client.call(WalletApiOperation.ConfirmPeerPushCredit, { + transactionId: prepare.transactionId, + }); + + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Aborted, + }, + }), + // FIXME check wallet2 is also aborted + /*wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + })*/ + ]); + + const bal = await wallet1.call(WalletApiOperation.GetBalances, {}); + t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:13.49"); + } + + t.logStep("P2P push expire"); + { + const initiate = await wallet1.call( + WalletApiOperation.InitiatePeerPushDebit, + { + partialContractTerms: { + summary: "second tx, will expire", + amount: "TESTKUDOS:5", + purse_expiration, + }, + }, + ); + + await wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Pending, + minor: TransactionMinorState.Ready, + }, + }); + + const tx = await wallet1.call( + WalletApiOperation.GetTransactionById, + { + transactionId: initiate.transactionId, + }, + ); + t.assertDeepEqual(tx.type, TransactionType.PeerPushDebit); + t.assertTrue(!!tx.talerUri); + + const prepare = await wallet2.call(WalletApiOperation.PreparePeerPushCredit, { + talerUri: tx.talerUri, + }); + + const timetravelOffsetMs = Duration.toMilliseconds( + Duration.fromSpec({ days: 5 }), + ); + + console.log("stopping exchange to apply time-travel"); + + await exchange.stop(); + exchange.setTimetravel(timetravelOffsetMs); + await exchange.start(); + await exchange.pingUntilAvailable(); + + console.log("running expire"); + await exchange.runExpireOnce(); + console.log("done running expire"); + + console.log("purse should now be expired"); + + await Promise.all([ + wallet1.call(WalletApiOperation.TestingSetTimetravel, { + offsetMs: timetravelOffsetMs, + }), + wallet2.call(WalletApiOperation.TestingSetTimetravel, { + offsetMs: timetravelOffsetMs, + }), + ]); + + await wallet2.client.call(WalletApiOperation.ConfirmPeerPushCredit, { + transactionId: prepare.transactionId, + }); + + await Promise.all([ + wallet1.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: initiate.transactionId, + txState: { + major: TransactionMajorState.Aborted, + }, + }), + // FIXME check wallet2 is also aborted + /*wallet2.call(WalletApiOperation.TestingWaitTransactionState, { + transactionId: prepare.transactionId, + txState: { + major: TransactionMajorState.Done, + }, + })*/ + ]); + } +} + +runPeerPushTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts b/packages/taler-harness/src/integrationtests/test-peer-to-peer-pull.ts @@ -1,311 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2020 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** - * Imports. - */ -import { - AbsoluteTime, - AmountString, - Duration, - j2s, - NotificationType, - TalerCorebankApiClient, - TransactionMajorState, - TransactionMinorState, - TransactionType, - WalletNotification, -} from "@gnu-taler/taler-util"; -import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; -import { - createSimpleTestkudosEnvironmentV3, - createWalletDaemonWithClient, - withdrawViaBankV3, -} from "../harness/environments.js"; -import { - ExchangeService, - GlobalTestState, - WalletClient, -} from "../harness/harness.js"; - -/** - * Run test for basic, bank-integrated withdrawal and payment. - */ -export async function runPeerToPeerPullTest(t: GlobalTestState) { - // Set up test environment - - const { bankClient, exchange } = await createSimpleTestkudosEnvironmentV3(t); - - let allW1Notifications: WalletNotification[] = []; - let allW2Notifications: WalletNotification[] = []; - - const w1 = await createWalletDaemonWithClient(t, { - name: "w1", - persistent: true, - handleNotification(wn) { - allW1Notifications.push(wn); - }, - }); - const w2 = await createWalletDaemonWithClient(t, { - name: "w2", - persistent: true, - handleNotification(wn) { - allW2Notifications.push(wn); - }, - }); - - // Withdraw digital cash into the wallet. - const wallet1 = w1.walletClient; - const wallet2 = w2.walletClient; - - await checkNormalPeerPull(t, bankClient, exchange, wallet1, wallet2); - - console.log(`w1 notifications: ${j2s(allW1Notifications)}`); - - // Check that we don't have an excessive number of notifications. - t.assertTrue(allW1Notifications.length <= 60); - - await checkAbortedPeerPull(t, bankClient, exchange, wallet1, wallet2); -} - -async function checkNormalPeerPull( - t: GlobalTestState, - bankClient: TalerCorebankApiClient, - exchange: ExchangeService, - wallet1: WalletClient, - wallet2: WalletClient, -): Promise<void> { - const withdrawRes = await withdrawViaBankV3(t, { - walletClient: wallet2, - bankClient, - exchange, - amount: "TESTKUDOS:20", - }); - - await withdrawRes.withdrawalFinishedCond; - - const purseExpiration = AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration( - AbsoluteTime.now(), - Duration.fromSpec({ days: 2 }), - ), - ); - - await wallet1.call(WalletApiOperation.AddExchange, { - exchangeBaseUrl: exchange.baseUrl, - }); - - const checkPullCreditResp1 = await wallet1.client.call( - WalletApiOperation.CheckPeerPullCredit, - { - amount: "TESTKUDOS:5" as AmountString, - exchangeBaseUrl: exchange.baseUrl, - }, - ); - - t.assertDeepEqual(checkPullCreditResp1.amountRaw, "TESTKUDOS:5"); - - const checkPullCreditResp2 = await wallet1.client.call( - WalletApiOperation.CheckPeerPullCredit, - { - amount: "TESTKUDOS:0" as AmountString, - exchangeBaseUrl: exchange.baseUrl, - }, - ); - - t.assertDeepEqual(checkPullCreditResp2.amountRaw, "TESTKUDOS:0"); - t.assertDeepEqual(checkPullCreditResp2.amountEffective, "TESTKUDOS:0"); - t.assertDeepEqual(checkPullCreditResp2.numCoins, 0); - - const resp = await wallet1.client.call( - WalletApiOperation.InitiatePeerPullCredit, - { - exchangeBaseUrl: exchange.baseUrl, - partialContractTerms: { - summary: "Hello World", - amount: "TESTKUDOS:5" as AmountString, - purse_expiration: purseExpiration, - }, - }, - ); - - const peerPullCreditReadyCond = wallet1.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === resp.transactionId && - x.newTxState.major === TransactionMajorState.Pending && - x.newTxState.minor === TransactionMinorState.Ready, - ); - - await peerPullCreditReadyCond; - - const creditTx = await wallet1.call(WalletApiOperation.GetTransactionById, { - transactionId: resp.transactionId, - }); - - t.assertDeepEqual(creditTx.type, TransactionType.PeerPullCredit); - t.assertTrue(!!creditTx.talerUri); - - const checkResp = await wallet2.client.call( - WalletApiOperation.PreparePeerPullDebit, - { - talerUri: creditTx.talerUri, - }, - ); - - console.log(`checkResp: ${j2s(checkResp)}`); - - const peerPullCreditDoneCond = wallet1.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === resp.transactionId && - x.newTxState.major === TransactionMajorState.Done, - ); - - const peerPullDebitDoneCond = wallet2.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === checkResp.transactionId && - x.newTxState.major === TransactionMajorState.Done, - ); - - await wallet2.client.call(WalletApiOperation.ConfirmPeerPullDebit, { - transactionId: checkResp.transactionId, - }); - - await peerPullCreditDoneCond; - await peerPullDebitDoneCond; - - const txn1 = await wallet1.client.call( - WalletApiOperation.GetTransactions, - {}, - ); - - const txn2 = await wallet2.client.call( - WalletApiOperation.GetTransactions, - {}, - ); - - console.log(`txn1: ${j2s(txn1)}`); - console.log(`txn2: ${j2s(txn2)}`); -} - -async function checkAbortedPeerPull( - t: GlobalTestState, - bankClient: TalerCorebankApiClient, - exchange: ExchangeService, - wallet1: WalletClient, - wallet2: WalletClient, -): Promise<void> { - const withdrawRes = await withdrawViaBankV3(t, { - walletClient: wallet2, - bankClient, - exchange, - amount: "TESTKUDOS:20", - }); - - await withdrawRes.withdrawalFinishedCond; - - const purseExpiration = AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration( - AbsoluteTime.now(), - Duration.fromSpec({ days: 2 }), - ), - ); - - const resp = await wallet1.client.call( - WalletApiOperation.InitiatePeerPullCredit, - { - exchangeBaseUrl: exchange.baseUrl, - partialContractTerms: { - summary: "Hello World", - amount: "TESTKUDOS:5" as AmountString, - purse_expiration: purseExpiration, - }, - }, - ); - - const peerPullCreditReadyCond = wallet1.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === resp.transactionId && - x.newTxState.major === TransactionMajorState.Pending && - x.newTxState.minor === TransactionMinorState.Ready, - ); - - await peerPullCreditReadyCond; - - const creditTx = await wallet1.call(WalletApiOperation.GetTransactionById, { - transactionId: resp.transactionId, - }); - - t.assertDeepEqual(creditTx.type, TransactionType.PeerPullCredit); - t.assertTrue(!!creditTx.talerUri); - - const checkResp = await wallet2.client.call( - WalletApiOperation.PreparePeerPullDebit, - { - talerUri: creditTx.talerUri, - }, - ); - - console.log(`checkResp: ${j2s(checkResp)}`); - - const peerPullCreditAbortedCond = wallet1.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === resp.transactionId && - x.newTxState.major === TransactionMajorState.Aborted, - ); - - const peerPullDebitAbortedCond = wallet2.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.transactionId === checkResp.transactionId && - x.newTxState.major === TransactionMajorState.Aborted, - ); - - await wallet1.call(WalletApiOperation.AbortTransaction, { - transactionId: resp.transactionId, - }); - - await wallet2.client.call(WalletApiOperation.ConfirmPeerPullDebit, { - transactionId: checkResp.transactionId, - }); - - console.log(`waiting for ${resp.transactionId} to go to state aborted`); - console.log("checkpoint: before-aborted-wait"); - await peerPullCreditAbortedCond; - console.log("checkpoint: after-credit-aborted-wait"); - await peerPullDebitAbortedCond; - console.log("checkpoint: after-debit-aborted-wait"); - console.log("checkpoint: after-aborted-wait"); - - const txn1 = await wallet1.client.call( - WalletApiOperation.GetTransactions, - {}, - ); - - const txn2 = await wallet2.client.call( - WalletApiOperation.GetTransactions, - {}, - ); - - console.log(`txn1: ${j2s(txn1)}`); - console.log(`txn2: ${j2s(txn2)}`); -} - -runPeerToPeerPullTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts b/packages/taler-harness/src/integrationtests/test-peer-to-peer-push.ts @@ -1,287 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2020-2025 Taler Systems S.A. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** - * Imports. - */ -import { - AbsoluteTime, - AmountString, - Duration, - NotificationType, - TransactionMajorState, - TransactionMinorState, - TransactionType, - WalletNotification, - j2s, -} from "@gnu-taler/taler-util"; -import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; -import { - createSimpleTestkudosEnvironmentV3, - createWalletDaemonWithClient, - withdrawViaBankV3, -} from "../harness/environments.js"; -import { GlobalTestState } from "../harness/harness.js"; - -/** - * Run a test for basic peer-push payments. - */ -export async function runPeerToPeerPushTest(t: GlobalTestState) { - const { bankClient, exchange } = await createSimpleTestkudosEnvironmentV3(t); - - let allW1Notifications: WalletNotification[] = []; - let allW2Notifications: WalletNotification[] = []; - - const w1 = await createWalletDaemonWithClient(t, { - name: "w1", - handleNotification(wn) { - allW1Notifications.push(wn); - }, - }); - const w2 = await createWalletDaemonWithClient(t, { - name: "w2", - handleNotification(wn) { - allW2Notifications.push(wn); - }, - }); - - // Withdraw digital cash into the wallet. - - const withdrawRes = await withdrawViaBankV3(t, { - walletClient: w1.walletClient, - bankClient, - exchange, - amount: "TESTKUDOS:20", - }); - - await withdrawRes.withdrawalFinishedCond; - - { - const maxResp1 = await w1.walletClient.call( - WalletApiOperation.GetMaxPeerPushDebitAmount, - { - currency: "TESTKUDOS", - }, - ); - - t.assertDeepEqual(maxResp1.exchangeBaseUrl, exchange.baseUrl); - t.assertAmountEquals(maxResp1.rawAmount, "TESTKUDOS:19.1"); - t.assertAmountEquals(maxResp1.effectiveAmount, "TESTKUDOS:19.53"); - } - - const purse_expiration = AbsoluteTime.toProtocolTimestamp( - AbsoluteTime.addDuration( - AbsoluteTime.now(), - Duration.fromSpec({ days: 2 }), - ), - ); - - { - const checkRespSmall = await w1.walletClient.call( - WalletApiOperation.CheckPeerPushDebit, - { - amount: "TESTKUDOS:0" as AmountString, - }, - ); - } - - const checkResp0 = await w1.walletClient.call( - WalletApiOperation.CheckPeerPushDebit, - { - amount: "TESTKUDOS:5" as AmountString, - }, - ); - - t.assertAmountEquals(checkResp0.amountRaw, "TESTKUDOS:5"); - t.assertAmountEquals(checkResp0.amountEffective, "TESTKUDOS:5.49"); - - { - const resp = await w1.walletClient.call( - WalletApiOperation.InitiatePeerPushDebit, - { - partialContractTerms: { - summary: "Hello World 😁😇", - amount: "TESTKUDOS:5" as AmountString, - purse_expiration, - }, - }, - ); - - console.log(resp); - } - - { - const bal = await w1.walletClient.call(WalletApiOperation.GetBalances, {}); - t.assertAmountEquals(bal.balances[0].pendingOutgoing, "TESTKUDOS:5.49"); - } - - await w1.walletClient.call(WalletApiOperation.TestingWaitRefreshesFinal, {}); - - const resp = await w1.walletClient.call( - WalletApiOperation.InitiatePeerPushDebit, - { - partialContractTerms: { - summary: "Hello World 🥺", - amount: "TESTKUDOS:5" as AmountString, - purse_expiration, - }, - }, - ); - - console.log(resp); - - const peerPushReadyCond = w1.walletClient.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.newTxState.major === TransactionMajorState.Pending && - x.newTxState.minor === TransactionMinorState.Ready && - x.transactionId === resp.transactionId, - ); - - await peerPushReadyCond; - - const txDetails = await w1.walletClient.call( - WalletApiOperation.GetTransactionById, - { - transactionId: resp.transactionId, - }, - ); - t.assertDeepEqual(txDetails.type, TransactionType.PeerPushDebit); - t.assertTrue(!!txDetails.talerUri); - - const prepareResp = await w2.walletClient.call( - WalletApiOperation.PreparePeerPushCredit, - { - talerUri: txDetails.talerUri, - }, - ); - - console.log(prepareResp); - - const acceptResp = await w2.walletClient.call( - WalletApiOperation.ConfirmPeerPushCredit, - { - transactionId: prepareResp.transactionId, - }, - ); - - console.log(acceptResp); - - const txn1 = await w1.walletClient.call( - WalletApiOperation.GetTransactions, - {}, - ); - const txn2 = await w2.walletClient.call( - WalletApiOperation.GetTransactions, - {}, - ); - - console.log(`txn1: ${j2s(txn1)}`); - console.log(`txn2: ${j2s(txn2)}`); - - // We expect insufficient balance here! - const ex1 = await t.assertThrowsTalerErrorAsync( - w1.walletClient.call(WalletApiOperation.InitiatePeerPushDebit, { - partialContractTerms: { - summary: "(this will fail)", - amount: "TESTKUDOS:15" as AmountString, - purse_expiration, - }, - }) - ); - - console.log("got expected exception detail", j2s(ex1.errorDetail)); - - const initiateResp2 = await w1.walletClient.call( - WalletApiOperation.InitiatePeerPushDebit, - { - partialContractTerms: { - summary: "second tx, will expire", - amount: "TESTKUDOS:5" as AmountString, - purse_expiration, - }, - }, - ); - - const peerPushReadyCond2 = w1.walletClient.waitForNotificationCond( - (x) => - x.type === NotificationType.TransactionStateTransition && - x.newTxState.major === TransactionMajorState.Pending && - x.newTxState.minor === TransactionMinorState.Ready && - x.transactionId === initiateResp2.transactionId, - ); - - await peerPushReadyCond2; - - const txDetails3 = await w1.walletClient.call( - WalletApiOperation.GetTransactionById, - { - transactionId: initiateResp2.transactionId, - }, - ); - t.assertDeepEqual(txDetails3.type, TransactionType.PeerPushDebit); - t.assertTrue(!!txDetails3.talerUri); - - await w2.walletClient.call(WalletApiOperation.PreparePeerPushCredit, { - talerUri: txDetails3.talerUri, - }); - - const timetravelOffsetMs = Duration.toMilliseconds( - Duration.fromSpec({ days: 5 }), - ); - - console.log("stopping exchange to apply time-travel"); - - await exchange.stop(); - exchange.setTimetravel(timetravelOffsetMs); - await exchange.start(); - await exchange.pingUntilAvailable(); - - console.log("running expire"); - await exchange.runExpireOnce(); - console.log("done running expire"); - - console.log("purse should now be expired"); - - await w1.walletClient.call(WalletApiOperation.TestingSetTimetravel, { - offsetMs: timetravelOffsetMs, - }); - - await w2.walletClient.call(WalletApiOperation.TestingSetTimetravel, { - offsetMs: timetravelOffsetMs, - }); - - await w1.walletClient.call( - WalletApiOperation.TestingWaitTransactionsFinal, - {}, - ); - - await w2.walletClient.call( - WalletApiOperation.TestingWaitTransactionsFinal, - {}, - ); - - const txDetails2 = await w1.walletClient.call( - WalletApiOperation.GetTransactionById, - { - transactionId: initiateResp2.transactionId, - }, - ); - - console.log(`tx details 2: ${j2s(txDetails2)}`); -} - -runPeerToPeerPushTest.suites = ["wallet"]; diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -100,12 +100,11 @@ import { runPaymentTransientTest } from "./test-payment-transient.js"; import { runPaymentZeroTest } from "./test-payment-zero.js"; import { runPaymentTest } from "./test-payment.js"; import { runPaywallFlowTest } from "./test-paywall-flow.js"; +import { runPeerPullTest } from "./test-peer-pull.js"; +import { runPeerPushTest } from "./test-peer-push.js"; import { runPeerPullLargeTest } from "./test-peer-pull-large.js"; -import { runPeerPushAbortTest } from "./test-peer-push-abort.js"; import { runPeerPushLargeTest } from "./test-peer-push-large.js"; import { runPeerRepairTest } from "./test-peer-repair.js"; -import { runPeerToPeerPullTest } from "./test-peer-to-peer-pull.js"; -import { runPeerToPeerPushTest } from "./test-peer-to-peer-push.js"; import { runRefundAutoTest } from "./test-refund-auto.js"; import { runRefundGoneTest } from "./test-refund-gone.js"; import { runRefundIncrementalTest } from "./test-refund-incremental.js"; @@ -214,8 +213,8 @@ const allTests: TestMainFunction[] = [ runMultiExchangeTest, runWalletBalanceTest, runPaywallFlowTest, - runPeerToPeerPullTest, - runPeerToPeerPushTest, + runPeerPullTest, + runPeerPushTest, runRefundAutoTest, runRefundGoneTest, runRefundIncrementalTest, @@ -300,7 +299,6 @@ const allTests: TestMainFunction[] = [ runKycDepositAggregateImplicitAuthTest, runKycAmpTimeoutTest, runKycAmpFailureTest, - runPeerPushAbortTest, runWithdrawalCashacceptorTest, runWithdrawalConflictTest, runBankWopTest,