summaryrefslogtreecommitdiff
path: root/packages/taler-integrationtests/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-09-08 17:40:47 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-09-08 17:40:47 +0530
commitb063382d25d1ed8572ebe2f52bf54247379300d5 (patch)
treeb60e4abf9b5285ffdf3339639ba8dae30d0bfff1 /packages/taler-integrationtests/src
parentbe77ee284a819f7932831bd85e88c47c655addb2 (diff)
downloadwallet-core-b063382d25d1ed8572ebe2f52bf54247379300d5.tar.gz
wallet-core-b063382d25d1ed8572ebe2f52bf54247379300d5.tar.bz2
wallet-core-b063382d25d1ed8572ebe2f52bf54247379300d5.zip
tipping API and integration test
Diffstat (limited to 'packages/taler-integrationtests/src')
-rw-r--r--packages/taler-integrationtests/src/harness.ts67
-rw-r--r--packages/taler-integrationtests/src/merchantApiTypes.ts60
-rw-r--r--packages/taler-integrationtests/src/test-tipping.ts106
3 files changed, 229 insertions, 4 deletions
diff --git a/packages/taler-integrationtests/src/harness.ts b/packages/taler-integrationtests/src/harness.ts
index 620b89e76..e40798b4b 100644
--- a/packages/taler-integrationtests/src/harness.ts
+++ b/packages/taler-integrationtests/src/harness.ts
@@ -72,6 +72,10 @@ import {
CoinDumpJson,
ForceExchangeUpdateRequest,
ForceRefreshRequest,
+ PrepareTipResult,
+ PrepareTipRequest,
+ codecForPrepareTipResult,
+ AcceptTipRequest,
} from "taler-wallet-core";
import { URL } from "url";
import axios, { AxiosError } from "axios";
@@ -81,6 +85,9 @@ import {
PostOrderRequest,
PostOrderResponse,
MerchantOrderPrivateStatusResponse,
+ TippingReserveStatus,
+ TipCreateConfirmation,
+ TipCreateRequest,
} from "./merchantApiTypes";
import { ApplyRefundResponse } from "taler-wallet-core";
import { PendingOperationsResponse } from "taler-wallet-core";
@@ -1216,10 +1223,46 @@ export namespace MerchantPrivateApi {
};
}
- export async function createTippingReserve(merchantService: MerchantServiceInterface,
-
+ export async function createTippingReserve(
+ merchantService: MerchantServiceInterface,
+ instance: string,
req: CreateMerchantTippingReserveRequest,
- ): Promise<CreateMerchantTippingReserveConfirmation> {}
+ ): Promise<CreateMerchantTippingReserveConfirmation> {
+ const reqUrl = new URL(
+ `private/reserves`,
+ merchantService.makeInstanceBaseUrl(instance),
+ );
+ const resp = await axios.post(reqUrl.href, req);
+ // FIXME: validate
+ return resp.data;
+ }
+
+ export async function queryTippingReserves(
+ merchantService: MerchantServiceInterface,
+ instance: string,
+ ): Promise<TippingReserveStatus> {
+ const reqUrl = new URL(
+ `private/reserves`,
+ merchantService.makeInstanceBaseUrl(instance),
+ );
+ const resp = await axios.get(reqUrl.href);
+ // FIXME: validate
+ return resp.data;
+ }
+
+ export async function giveTip(
+ merchantService: MerchantServiceInterface,
+ instance: string,
+ req: TipCreateRequest,
+ ): Promise<TipCreateConfirmation> {
+ const reqUrl = new URL(
+ `private/tips`,
+ merchantService.makeInstanceBaseUrl(instance),
+ );
+ const resp = await axios.post(reqUrl.href, req);
+ // FIXME: validate
+ return resp.data;
+ }
}
export interface CreateMerchantTippingReserveRequest {
@@ -1238,7 +1281,7 @@ export interface CreateMerchantTippingReserveConfirmation {
reserve_pub: string;
// Wire account of the exchange where to transfer the funds
- payto_url: string;
+ payto_uri: string;
}
export class MerchantService implements MerchantServiceInterface {
@@ -1594,6 +1637,22 @@ export class WalletCli {
throw new OperationFailedError(resp.error);
}
+ async prepareTip(req: PrepareTipRequest): Promise<PrepareTipResult> {
+ const resp = await this.apiRequest("prepareTip", req);
+ if (resp.type === "response") {
+ return codecForPrepareTipResult().decode(resp.result);
+ }
+ throw new OperationFailedError(resp.error);
+ }
+
+ async acceptTip(req: AcceptTipRequest): Promise<void> {
+ const resp = await this.apiRequest("acceptTip", req);
+ if (resp.type === "response") {
+ return;
+ }
+ throw new OperationFailedError(resp.error);
+ }
+
async dumpCoins(): Promise<CoinDumpJson> {
const resp = await this.apiRequest("dumpCoins", {});
if (resp.type === "response") {
diff --git a/packages/taler-integrationtests/src/merchantApiTypes.ts b/packages/taler-integrationtests/src/merchantApiTypes.ts
index 550c5e90c..e89e32642 100644
--- a/packages/taler-integrationtests/src/merchantApiTypes.ts
+++ b/packages/taler-integrationtests/src/merchantApiTypes.ts
@@ -223,3 +223,63 @@ export interface TransactionWireReport {
// Public key of the coin for which we got the exchange error.
coin_pub: CoinPublicKeyString;
}
+
+export interface TippingReserveStatus {
+ // Array of all known reserves (possibly empty!)
+ reserves: ReserveStatusEntry[];
+}
+
+export interface ReserveStatusEntry {
+ // Public key of the reserve
+ reserve_pub: string;
+
+ // Timestamp when it was established
+ creation_time: Timestamp;
+
+ // Timestamp when it expires
+ expiration_time: Timestamp;
+
+ // Initial amount as per reserve creation call
+ merchant_initial_amount: AmountString;
+
+ // Initial amount as per exchange, 0 if exchange did
+ // not confirm reserve creation yet.
+ exchange_initial_amount: AmountString;
+
+ // Amount picked up so far.
+ pickup_amount: AmountString;
+
+ // Amount approved for tips that exceeds the pickup_amount.
+ committed_amount: AmountString;
+
+ // Is this reserve active (false if it was deleted but not purged)
+ active: boolean;
+}
+
+
+export interface TipCreateConfirmation {
+ // Unique tip identifier for the tip that was created.
+ tip_id: string;
+
+ // taler://tip URI for the tip
+ taler_tip_uri: string;
+
+ // URL that will directly trigger processing
+ // the tip when the browser is redirected to it
+ tip_status_url: string;
+
+ // when does the tip expire
+ tip_expiration: Timestamp;
+}
+
+export interface TipCreateRequest {
+ // Amount that the customer should be tipped
+ amount: AmountString;
+
+ // Justification for giving the tip
+ justification: string;
+
+ // URL that the user should be directed to after tipping,
+ // will be included in the tip_token.
+ next_url: string;
+} \ No newline at end of file
diff --git a/packages/taler-integrationtests/src/test-tipping.ts b/packages/taler-integrationtests/src/test-tipping.ts
new file mode 100644
index 000000000..ddf56c0e0
--- /dev/null
+++ b/packages/taler-integrationtests/src/test-tipping.ts
@@ -0,0 +1,106 @@
+/*
+ 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 {
+ runTest,
+ GlobalTestState,
+ MerchantPrivateApi,
+ BankAccessApi,
+ BankApi,
+} from "./harness";
+import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
+
+/**
+ * Run test for basic, bank-integrated withdrawal.
+ */
+runTest(async (t: GlobalTestState) => {
+ // Set up test environment
+
+ const {
+ wallet,
+ bank,
+ exchange,
+ merchant,
+ exchangeBankAccount,
+ } = await createSimpleTestkudosEnvironment(t);
+
+ const mbu = await BankApi.createRandomBankUser(bank);
+
+ const tipReserveResp = await MerchantPrivateApi.createTippingReserve(
+ merchant,
+ "default",
+ {
+ exchange_url: exchange.baseUrl,
+ initial_balance: "TESTKUDOS:10",
+ wire_method: "x-taler-bank",
+ },
+ );
+
+ console.log("tipReserveResp:", tipReserveResp);
+
+ t.assertDeepEqual(
+ tipReserveResp.payto_uri,
+ exchangeBankAccount.accountPaytoUri,
+ );
+
+ await BankApi.adminAddIncoming(bank, {
+ amount: "TESTKUDOS:10",
+ debitAccountPayto: mbu.accountPaytoUri,
+ exchangeBankAccount,
+ reservePub: tipReserveResp.reserve_pub,
+ });
+
+ await exchange.runWirewatchOnce();
+ await merchant.stop();
+ await merchant.start();
+ await merchant.pingUntilAvailable();
+
+ const r = await MerchantPrivateApi.queryTippingReserves(merchant, "default");
+ console.log("tipping reserves:", JSON.stringify(r, undefined, 2));
+
+ t.assertTrue(r.reserves.length === 1);
+ t.assertDeepEqual(
+ r.reserves[0].exchange_initial_amount,
+ r.reserves[0].merchant_initial_amount,
+ );
+
+ const tip = await MerchantPrivateApi.giveTip(merchant, "default", {
+ amount: "TESTKUDOS:5",
+ justification: "why not?",
+ next_url: "https://example.com/after-tip",
+ });
+
+ console.log("created tip", tip);
+
+ const ptr = await wallet.prepareTip({
+ talerTipUri: tip.taler_tip_uri,
+ });
+
+ console.log(ptr);
+
+ await wallet.acceptTip({
+ walletTipId: ptr.walletTipId,
+ });
+
+ await wallet.runUntilDone();
+
+ const bal = await wallet.getBalances();
+
+ console.log(bal);
+});