aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-harness
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2024-04-22 19:37:51 +0200
committerFlorian Dold <florian@dold.me>2024-04-22 19:37:58 +0200
commit5f7926db8bfc2013fb427264cb46def2e9574868 (patch)
treebc619218f741dbcf2247673341a0cabf466a6870 /packages/taler-harness
parentf817371e336564d71639a3f8f7ac956cbbd53df5 (diff)
downloadwallet-core-5f7926db8bfc2013fb427264cb46def2e9574868.tar.xz
wallet-core: support multi-batch p2p payments
Diffstat (limited to 'packages/taler-harness')
-rw-r--r--packages/taler-harness/src/integrationtests/test-peer-pull-large.ts194
-rw-r--r--packages/taler-harness/src/integrationtests/test-peer-push-large.ts177
-rw-r--r--packages/taler-harness/src/integrationtests/test-wallet-blocked-pay-merchant.ts26
-rw-r--r--packages/taler-harness/src/integrationtests/testrunner.ts4
4 files changed, 388 insertions, 13 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
new file mode 100644
index 000000000..6de3c2e33
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-peer-pull-large.ts
@@ -0,0 +1,194 @@
+/*
+ This file is part of GNU Taler
+ (C) 2024 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,
+ TransactionMajorState,
+ TransactionMinorState,
+ TransactionType,
+ WalletNotification,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { CoinConfig } from "../harness/denomStructures.js";
+import {
+ BankServiceHandle,
+ ExchangeService,
+ GlobalTestState,
+ WalletClient,
+} from "../harness/harness.js";
+import {
+ createSimpleTestkudosEnvironmentV2,
+ createWalletDaemonWithClient,
+ withdrawViaBankV2,
+} from "../harness/helpers.js";
+
+const coinCommon = {
+ cipher: "RSA" as const,
+ durationLegal: "3 years",
+ durationSpend: "2 years",
+ durationWithdraw: "7 days",
+ feeDeposit: "TESTKUDOS:0",
+ feeRefresh: "TESTKUDOS:0",
+ feeRefund: "TESTKUDOS:0",
+ feeWithdraw: "TESTKUDOS:0",
+ rsaKeySize: 1024,
+};
+
+const coinConfigList: CoinConfig[] = [
+ {
+ ...coinCommon,
+ name: "n1",
+ value: "TESTKUDOS:1",
+ },
+];
+
+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);
+ },
+ });
+
+ // 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> {
+ const withdrawRes = await withdrawViaBankV2(t, {
+ walletClient: wallet2,
+ bank,
+ exchange,
+ amount: "TESTKUDOS:500",
+ });
+
+ 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:200" 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)}`);
+}
+
+runPeerPullLargeTest.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
new file mode 100644
index 000000000..b7fbe9f6e
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-peer-push-large.ts
@@ -0,0 +1,177 @@
+/*
+ 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,
+ NotificationType,
+ TransactionMajorState,
+ TransactionMinorState,
+ TransactionType,
+ WalletNotification,
+ j2s,
+} from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { GlobalTestState } from "../harness/harness.js";
+import {
+ createSimpleTestkudosEnvironmentV2,
+ createWalletDaemonWithClient,
+ withdrawViaBankV2,
+} from "../harness/helpers.js";
+import { CoinConfig } from "../harness/denomStructures.js";
+
+const coinCommon = {
+ cipher: "RSA" as const,
+ durationLegal: "3 years",
+ durationSpend: "2 years",
+ durationWithdraw: "7 days",
+ feeDeposit: "TESTKUDOS:0",
+ feeRefresh: "TESTKUDOS:0",
+ feeRefund: "TESTKUDOS:0",
+ feeWithdraw: "TESTKUDOS:0",
+ rsaKeySize: 1024,
+};
+
+const coinConfigList: CoinConfig[] = [
+ {
+ ...coinCommon,
+ name: "n1",
+ value: "TESTKUDOS:1",
+ },
+];
+
+/**
+ * Run a test for a multi-batch peer push payment.
+ */
+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);
+ },
+ });
+
+ // Withdraw digital cash into the wallet.
+
+ const withdrawRes = await withdrawViaBankV2(t, {
+ walletClient: w1.walletClient,
+ bank,
+ 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(
+ WalletApiOperation.CheckPeerPushDebit,
+ {
+ amount: "TESTKUDOS:200" as AmountString,
+ },
+ );
+
+ t.assertAmountEquals(checkResp0.amountEffective, "TESTKUDOS:200");
+
+ const resp = await w1.walletClient.call(
+ WalletApiOperation.InitiatePeerPushDebit,
+ {
+ partialContractTerms: {
+ summary: "Hello World 🥺",
+ amount: "TESTKUDOS:200" 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 checkResp = await w2.walletClient.call(
+ WalletApiOperation.PreparePeerPushCredit,
+ {
+ talerUri: txDetails.talerUri,
+ },
+ );
+
+ console.log(checkResp);
+
+ const acceptResp = await w2.walletClient.call(
+ WalletApiOperation.ConfirmPeerPushCredit,
+ {
+ transactionId: checkResp.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)}`);
+}
+
+runPeerPushLargeTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-wallet-blocked-pay-merchant.ts b/packages/taler-harness/src/integrationtests/test-wallet-blocked-pay-merchant.ts
index 15167d133..004de87c8 100644
--- a/packages/taler-harness/src/integrationtests/test-wallet-blocked-pay-merchant.ts
+++ b/packages/taler-harness/src/integrationtests/test-wallet-blocked-pay-merchant.ts
@@ -44,25 +44,25 @@ const coinCommon = {
rsaKeySize: 1024,
};
+const coinConfigList: CoinConfig[] = [
+ {
+ ...coinCommon,
+ name: "n1",
+ value: "TESTKUDOS:1",
+ },
+ {
+ ...coinCommon,
+ name: "n5",
+ value: "TESTKUDOS:5",
+ },
+];
+
/**
* Run test for paying a merchant with balance locked behind a pending refresh.
*/
export async function runWalletBlockedPayMerchantTest(t: GlobalTestState) {
// Set up test environment
- const coinConfigList: CoinConfig[] = [
- {
- ...coinCommon,
- name: "n1",
- value: "TESTKUDOS:1",
- },
- {
- ...coinCommon,
- name: "n5",
- value: "TESTKUDOS:5",
- },
- ];
-
const { bank, exchange, merchant } = await createSimpleTestkudosEnvironmentV2(
t,
coinConfigList,
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts
index 54c211c6b..2f6304773 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -72,6 +72,8 @@ 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 { runPeerPullLargeTest } from "./test-peer-pull-large.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";
@@ -224,6 +226,8 @@ const allTests: TestMainFunction[] = [
runWalletBlockedPayPeerPullTest,
runWalletExchangeUpdateTest,
runWalletRefreshErrorsTest,
+ runPeerPullLargeTest,
+ runPeerPushLargeTest,
];
export interface TestRunSpec {