parent
545bf16cdf
commit
f407ab2023
@ -28,6 +28,8 @@ import {
|
||||
AmountJson,
|
||||
Amounts,
|
||||
AmountString,
|
||||
codecForMerchantOrderPrivateStatusResponse,
|
||||
codecForMerchantPostOrderResponse,
|
||||
codecForMerchantReserveCreateConfirmation,
|
||||
Configuration,
|
||||
CoreApiResponse,
|
||||
@ -39,28 +41,42 @@ import {
|
||||
hash,
|
||||
j2s,
|
||||
Logger,
|
||||
MerchantInstancesResponse,
|
||||
MerchantOrderPrivateStatusResponse,
|
||||
MerchantPostOrderRequest,
|
||||
MerchantPostOrderResponse,
|
||||
MerchantReserveCreateConfirmation,
|
||||
MerchantTemplateAddDetails,
|
||||
NotificationType,
|
||||
parsePaytoUri,
|
||||
stringToBytes,
|
||||
TalerError,
|
||||
TalerProtocolDuration,
|
||||
TransactionMajorState,
|
||||
TipCreateConfirmation,
|
||||
TipCreateRequest,
|
||||
TippingReserveStatus,
|
||||
WalletNotification,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import {
|
||||
createPlatformHttpLib,
|
||||
readSuccessResponseJsonOrThrow,
|
||||
} from "@gnu-taler/taler-util/http";
|
||||
import {
|
||||
BankApi,
|
||||
BankServiceHandle,
|
||||
HarnessExchangeBankAccount,
|
||||
OpenedPromise,
|
||||
openPromise,
|
||||
WalletApiOperation,
|
||||
WalletCoreApiClient,
|
||||
WalletCoreRequestType,
|
||||
WalletCoreResponseType,
|
||||
WalletOperations,
|
||||
} from "@gnu-taler/taler-wallet-core";
|
||||
import {
|
||||
createRemoteWallet,
|
||||
getClientFromRemoteWallet,
|
||||
makeNotificationWaiter,
|
||||
RemoteWallet,
|
||||
WalletNotificationWaiter,
|
||||
} from "@gnu-taler/taler-wallet-core/remote";
|
||||
import { deepStrictEqual } from "assert";
|
||||
import axiosImp, { AxiosError } from "axios";
|
||||
import { ChildProcess, spawn } from "child_process";
|
||||
@ -72,29 +88,6 @@ import * as readline from "readline";
|
||||
import { URL } from "url";
|
||||
import { CoinConfig } from "./denomStructures.js";
|
||||
import { LibeufinNexusApi, LibeufinSandboxApi } from "./libeufin-apis.js";
|
||||
import {
|
||||
codecForMerchantOrderPrivateStatusResponse,
|
||||
codecForMerchantPostOrderResponse,
|
||||
MerchantInstancesResponse,
|
||||
MerchantOrderPrivateStatusResponse,
|
||||
MerchantPostOrderRequest,
|
||||
MerchantPostOrderResponse,
|
||||
TipCreateConfirmation,
|
||||
TipCreateRequest,
|
||||
TippingReserveStatus,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import {
|
||||
createRemoteWallet,
|
||||
getClientFromRemoteWallet,
|
||||
makeNotificationWaiter,
|
||||
RemoteWallet,
|
||||
WalletNotificationWaiter,
|
||||
} from "@gnu-taler/taler-wallet-core/remote";
|
||||
import {
|
||||
createPlatformHttpLib,
|
||||
readSuccessResponseJsonOrErrorCode,
|
||||
readSuccessResponseJsonOrThrow,
|
||||
} from "@gnu-taler/taler-util/http";
|
||||
|
||||
const logger = new Logger("harness.ts");
|
||||
|
||||
|
@ -298,22 +298,10 @@ export async function createSimpleTestkudosEnvironmentV2(
|
||||
),
|
||||
});
|
||||
|
||||
const walletService = new WalletService(t, {
|
||||
name: "wallet",
|
||||
});
|
||||
await walletService.start();
|
||||
await walletService.pingUntilAvailable();
|
||||
|
||||
const walletClient = new WalletClient({
|
||||
unixPath: walletService.socketPath,
|
||||
onNotification(n) {
|
||||
console.log("got notification", n);
|
||||
},
|
||||
});
|
||||
await walletClient.connect();
|
||||
await walletClient.client.call(WalletApiOperation.InitWallet, {
|
||||
skipDefaults: true,
|
||||
});
|
||||
const { walletClient, walletService } = await createWalletDaemonWithClient(
|
||||
t,
|
||||
{ name: "wallet" },
|
||||
);
|
||||
|
||||
console.log("setup done!");
|
||||
|
||||
|
@ -0,0 +1,239 @@
|
||||
/*
|
||||
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 { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||
import { GlobalTestState, MerchantPrivateApi } from "../harness/harness.js";
|
||||
import {
|
||||
createSimpleTestkudosEnvironmentV2,
|
||||
withdrawViaBankV2,
|
||||
makeTestPaymentV2,
|
||||
createWalletDaemonWithClient,
|
||||
} from "../harness/helpers.js";
|
||||
import {
|
||||
ConfirmPayResultType,
|
||||
PreparePayResultType,
|
||||
j2s,
|
||||
parsePayUri,
|
||||
stringifyPayUri,
|
||||
} from "@gnu-taler/taler-util";
|
||||
|
||||
/**
|
||||
* Run test for basic, bank-integrated withdrawal and payment.
|
||||
*/
|
||||
export async function runPaymentShareTest(t: GlobalTestState) {
|
||||
// Set up test environment
|
||||
const {
|
||||
walletClient: firstWallet,
|
||||
bank,
|
||||
exchange,
|
||||
merchant,
|
||||
} = await createSimpleTestkudosEnvironmentV2(t);
|
||||
|
||||
// Withdraw digital cash into the wallet.
|
||||
await withdrawViaBankV2(t, {
|
||||
walletClient: firstWallet,
|
||||
bank,
|
||||
exchange,
|
||||
amount: "TESTKUDOS:20",
|
||||
});
|
||||
await firstWallet.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
|
||||
|
||||
const { walletClient: secondWallet } = await createWalletDaemonWithClient(t, {
|
||||
name: "wallet2",
|
||||
});
|
||||
|
||||
await withdrawViaBankV2(t, {
|
||||
walletClient: secondWallet,
|
||||
bank,
|
||||
exchange,
|
||||
amount: "TESTKUDOS:20",
|
||||
});
|
||||
await secondWallet.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
|
||||
|
||||
//create two orders to pay
|
||||
async function createOrder(amount: string) {
|
||||
const order = {
|
||||
summary: "Buy me!",
|
||||
amount,
|
||||
fulfillment_url: "taler://fulfillment-success/thx",
|
||||
};
|
||||
|
||||
const instance = "default";
|
||||
const args = { order };
|
||||
const auth = {};
|
||||
|
||||
const orderResp = await MerchantPrivateApi.createOrder(
|
||||
merchant,
|
||||
instance,
|
||||
{
|
||||
order: args.order,
|
||||
},
|
||||
auth,
|
||||
);
|
||||
|
||||
const orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(
|
||||
merchant,
|
||||
{
|
||||
orderId: orderResp.order_id,
|
||||
},
|
||||
auth,
|
||||
);
|
||||
|
||||
t.assertTrue(orderStatus.order_status === "unpaid");
|
||||
return { id: orderResp.order_id, uri: orderStatus.taler_pay_uri };
|
||||
}
|
||||
|
||||
/**
|
||||
* FIRST CASE, create in first wallet and pay in the second wallet
|
||||
* first wallet should not be able to continue
|
||||
*/
|
||||
{
|
||||
const order = await createOrder("TESTKUDOS:5");
|
||||
// Claim the order with the first wallet
|
||||
const claimFirstWallet = await firstWallet.call(
|
||||
WalletApiOperation.PreparePayForUri,
|
||||
{ talerPayUri: order.uri },
|
||||
);
|
||||
|
||||
t.assertTrue(
|
||||
claimFirstWallet.status === PreparePayResultType.PaymentPossible,
|
||||
);
|
||||
|
||||
//share order from the first wallet
|
||||
const { privatePayUri } = await firstWallet.call(
|
||||
WalletApiOperation.SharePayment,
|
||||
{
|
||||
merchantBaseUrl: merchant.makeInstanceBaseUrl(),
|
||||
orderId: order.id,
|
||||
},
|
||||
);
|
||||
|
||||
//claim from the second wallet
|
||||
const claimSecondWallet = await secondWallet.call(
|
||||
WalletApiOperation.PreparePayForUri,
|
||||
{ talerPayUri: privatePayUri },
|
||||
);
|
||||
|
||||
t.assertTrue(
|
||||
claimSecondWallet.status === PreparePayResultType.PaymentPossible,
|
||||
);
|
||||
|
||||
//pay from the second wallet
|
||||
const r2 = await secondWallet.call(WalletApiOperation.ConfirmPay, {
|
||||
proposalId: claimSecondWallet.proposalId,
|
||||
});
|
||||
|
||||
t.assertTrue(r2.type === ConfirmPayResultType.Done);
|
||||
{
|
||||
const first = await firstWallet.call(WalletApiOperation.GetBalances, {});
|
||||
const second = await secondWallet.call(
|
||||
WalletApiOperation.GetBalances,
|
||||
{},
|
||||
);
|
||||
t.assertAmountEquals(first.balances[0].available, "TESTKUDOS:19.53");
|
||||
t.assertAmountEquals(second.balances[0].available, "TESTKUDOS:14.23");
|
||||
}
|
||||
|
||||
// Claim the order with the first wallet
|
||||
const claimFirstWalletAgain = await firstWallet.call(
|
||||
WalletApiOperation.PreparePayForUri,
|
||||
{ talerPayUri: order.uri },
|
||||
);
|
||||
|
||||
t.assertTrue(
|
||||
claimFirstWalletAgain.status === PreparePayResultType.AlreadyConfirmed,
|
||||
);
|
||||
|
||||
const r1 = await firstWallet.call(WalletApiOperation.ConfirmPay, {
|
||||
proposalId: claimFirstWallet.proposalId,
|
||||
});
|
||||
|
||||
t.assertTrue(r1.type === ConfirmPayResultType.Done);
|
||||
{
|
||||
const first = await firstWallet.call(WalletApiOperation.GetBalances, {});
|
||||
const second = await secondWallet.call(
|
||||
WalletApiOperation.GetBalances,
|
||||
{},
|
||||
);
|
||||
t.assertAmountEquals(first.balances[0].available, "TESTKUDOS:19.53");
|
||||
t.assertAmountEquals(second.balances[0].available, "TESTKUDOS:14.23");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SECOND CASE, create in first wallet and share to the second wallet
|
||||
* pay with the first wallet, second wallet should not be able to continue
|
||||
*/
|
||||
{
|
||||
const order = await createOrder("TESTKUDOS:3");
|
||||
// Claim the order with the first wallet
|
||||
const claimFirstWallet = await firstWallet.call(
|
||||
WalletApiOperation.PreparePayForUri,
|
||||
{ talerPayUri: order.uri },
|
||||
);
|
||||
|
||||
t.assertTrue(
|
||||
claimFirstWallet.status === PreparePayResultType.PaymentPossible,
|
||||
);
|
||||
|
||||
//share order from the first wallet
|
||||
const { privatePayUri } = await firstWallet.call(
|
||||
WalletApiOperation.SharePayment,
|
||||
{
|
||||
merchantBaseUrl: merchant.makeInstanceBaseUrl(),
|
||||
orderId: order.id,
|
||||
},
|
||||
);
|
||||
|
||||
//claim from the second wallet
|
||||
const claimSecondWallet = await secondWallet.call(
|
||||
WalletApiOperation.PreparePayForUri,
|
||||
{ talerPayUri: privatePayUri },
|
||||
);
|
||||
|
||||
t.assertTrue(
|
||||
claimSecondWallet.status === PreparePayResultType.PaymentPossible,
|
||||
);
|
||||
|
||||
//pay from the second wallet
|
||||
const r2 = await firstWallet.call(WalletApiOperation.ConfirmPay, {
|
||||
proposalId: claimFirstWallet.proposalId,
|
||||
});
|
||||
|
||||
t.assertTrue(r2.type === ConfirmPayResultType.Done);
|
||||
|
||||
const bal1 = await firstWallet.call(WalletApiOperation.GetBalances, {});
|
||||
t.assertAmountEquals(bal1.balances[0].available, "TESTKUDOS:16.18");
|
||||
|
||||
const bal2 = await secondWallet.call(WalletApiOperation.GetBalances, {});
|
||||
t.assertAmountEquals(bal2.balances[0].available, "TESTKUDOS:14.23");
|
||||
|
||||
// Claim the order with the first wallet
|
||||
const claimSecondWalletAgain = await secondWallet.call(
|
||||
WalletApiOperation.PreparePayForUri,
|
||||
{ talerPayUri: order.uri },
|
||||
);
|
||||
|
||||
t.assertTrue(
|
||||
claimSecondWalletAgain.status === PreparePayResultType.AlreadyConfirmed,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
runPaymentShareTest.suites = ["wallet"];
|
@ -102,6 +102,7 @@ import { runWalletBalanceTest } from "./test-wallet-balance.js";
|
||||
import { runPaymentTemplateTest } from "./test-payment-template.js";
|
||||
import { runExchangeDepositTest } from "./test-exchange-deposit.js";
|
||||
import { runPeerRepairTest } from "./test-peer-repair.js";
|
||||
import { runPaymentShareTest } from "./test-payment-share.js";
|
||||
|
||||
/**
|
||||
* Test runner.
|
||||
@ -166,6 +167,7 @@ const allTests: TestMainFunction[] = [
|
||||
runPaymentIdempotencyTest,
|
||||
runPaymentMultipleTest,
|
||||
runPaymentTest,
|
||||
runPaymentShareTest,
|
||||
runPaymentTemplateTest,
|
||||
runPaymentAbortTest,
|
||||
runPaymentTransientTest,
|
||||
|
Loading…
Reference in New Issue
Block a user