parent
545bf16cdf
commit
f407ab2023
@ -28,6 +28,8 @@ import {
|
|||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
AmountString,
|
AmountString,
|
||||||
|
codecForMerchantOrderPrivateStatusResponse,
|
||||||
|
codecForMerchantPostOrderResponse,
|
||||||
codecForMerchantReserveCreateConfirmation,
|
codecForMerchantReserveCreateConfirmation,
|
||||||
Configuration,
|
Configuration,
|
||||||
CoreApiResponse,
|
CoreApiResponse,
|
||||||
@ -39,28 +41,42 @@ import {
|
|||||||
hash,
|
hash,
|
||||||
j2s,
|
j2s,
|
||||||
Logger,
|
Logger,
|
||||||
|
MerchantInstancesResponse,
|
||||||
|
MerchantOrderPrivateStatusResponse,
|
||||||
|
MerchantPostOrderRequest,
|
||||||
|
MerchantPostOrderResponse,
|
||||||
MerchantReserveCreateConfirmation,
|
MerchantReserveCreateConfirmation,
|
||||||
MerchantTemplateAddDetails,
|
MerchantTemplateAddDetails,
|
||||||
NotificationType,
|
|
||||||
parsePaytoUri,
|
parsePaytoUri,
|
||||||
stringToBytes,
|
stringToBytes,
|
||||||
TalerError,
|
TalerError,
|
||||||
TalerProtocolDuration,
|
TalerProtocolDuration,
|
||||||
TransactionMajorState,
|
TipCreateConfirmation,
|
||||||
|
TipCreateRequest,
|
||||||
|
TippingReserveStatus,
|
||||||
WalletNotification,
|
WalletNotification,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import {
|
||||||
|
createPlatformHttpLib,
|
||||||
|
readSuccessResponseJsonOrThrow,
|
||||||
|
} from "@gnu-taler/taler-util/http";
|
||||||
import {
|
import {
|
||||||
BankApi,
|
BankApi,
|
||||||
BankServiceHandle,
|
BankServiceHandle,
|
||||||
HarnessExchangeBankAccount,
|
HarnessExchangeBankAccount,
|
||||||
OpenedPromise,
|
|
||||||
openPromise,
|
openPromise,
|
||||||
WalletApiOperation,
|
|
||||||
WalletCoreApiClient,
|
WalletCoreApiClient,
|
||||||
WalletCoreRequestType,
|
WalletCoreRequestType,
|
||||||
WalletCoreResponseType,
|
WalletCoreResponseType,
|
||||||
WalletOperations,
|
WalletOperations,
|
||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
|
import {
|
||||||
|
createRemoteWallet,
|
||||||
|
getClientFromRemoteWallet,
|
||||||
|
makeNotificationWaiter,
|
||||||
|
RemoteWallet,
|
||||||
|
WalletNotificationWaiter,
|
||||||
|
} from "@gnu-taler/taler-wallet-core/remote";
|
||||||
import { deepStrictEqual } from "assert";
|
import { deepStrictEqual } from "assert";
|
||||||
import axiosImp, { AxiosError } from "axios";
|
import axiosImp, { AxiosError } from "axios";
|
||||||
import { ChildProcess, spawn } from "child_process";
|
import { ChildProcess, spawn } from "child_process";
|
||||||
@ -72,29 +88,6 @@ import * as readline from "readline";
|
|||||||
import { URL } from "url";
|
import { URL } from "url";
|
||||||
import { CoinConfig } from "./denomStructures.js";
|
import { CoinConfig } from "./denomStructures.js";
|
||||||
import { LibeufinNexusApi, LibeufinSandboxApi } from "./libeufin-apis.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");
|
const logger = new Logger("harness.ts");
|
||||||
|
|
||||||
|
@ -298,22 +298,10 @@ export async function createSimpleTestkudosEnvironmentV2(
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const walletService = new WalletService(t, {
|
const { walletClient, walletService } = await createWalletDaemonWithClient(
|
||||||
name: "wallet",
|
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,
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("setup done!");
|
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 { runPaymentTemplateTest } from "./test-payment-template.js";
|
||||||
import { runExchangeDepositTest } from "./test-exchange-deposit.js";
|
import { runExchangeDepositTest } from "./test-exchange-deposit.js";
|
||||||
import { runPeerRepairTest } from "./test-peer-repair.js";
|
import { runPeerRepairTest } from "./test-peer-repair.js";
|
||||||
|
import { runPaymentShareTest } from "./test-payment-share.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test runner.
|
* Test runner.
|
||||||
@ -166,6 +167,7 @@ const allTests: TestMainFunction[] = [
|
|||||||
runPaymentIdempotencyTest,
|
runPaymentIdempotencyTest,
|
||||||
runPaymentMultipleTest,
|
runPaymentMultipleTest,
|
||||||
runPaymentTest,
|
runPaymentTest,
|
||||||
|
runPaymentShareTest,
|
||||||
runPaymentTemplateTest,
|
runPaymentTemplateTest,
|
||||||
runPaymentAbortTest,
|
runPaymentAbortTest,
|
||||||
runPaymentTransientTest,
|
runPaymentTransientTest,
|
||||||
|
Loading…
Reference in New Issue
Block a user