gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 03/03: re-implement integration test functionalty th


From: gnunet
Subject: [taler-wallet-core] 03/03: re-implement integration test functionalty that will be used by the exchange for testing
Date: Fri, 14 Aug 2020 09:36:50 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

commit e3850158c249d890399fdb9e083ec7e654a8380f
Author: Florian Dold <florian.dold@gmail.com>
AuthorDate: Fri Aug 14 13:06:42 2020 +0530

    re-implement integration test functionalty that will be used by the 
exchange for testing
---
 packages/taler-wallet-android/src/index.ts         |   3 +-
 packages/taler-wallet-cli/package.json             |   1 +
 packages/taler-wallet-cli/src/index.ts             |   8 +-
 packages/taler-wallet-core/src/index.ts            |   4 +-
 .../taler-wallet-core/src/operations/testing.ts    | 281 +++++++++++++++++-
 .../taler-wallet-core/src/types/walletTypes.ts     | 187 +++++++++++-
 packages/taler-wallet-core/src/wallet.ts           | 194 ++++++++++++-
 .../taler-wallet-core/src/walletCoreApiHandler.ts  | 318 ---------------------
 .../taler-wallet-webextension/src/wxBackend.ts     |   9 +-
 pnpm-lock.yaml                                     |   2 +
 10 files changed, 665 insertions(+), 342 deletions(-)

diff --git a/packages/taler-wallet-android/src/index.ts 
b/packages/taler-wallet-android/src/index.ts
index 4430848c..07d15d58 100644
--- a/packages/taler-wallet-android/src/index.ts
+++ b/packages/taler-wallet-android/src/index.ts
@@ -38,7 +38,6 @@ import {
   WalletNotification,
   WALLET_EXCHANGE_PROTOCOL_VERSION,
   WALLET_MERCHANT_PROTOCOL_VERSION,
-  handleCoreApiRequest,
 } from "taler-wallet-core";
 
 import fs from "fs";
@@ -229,7 +228,7 @@ class AndroidWalletMessageHandler {
       }
       default: {
         const wallet = await this.wp.promise;
-        return await handleCoreApiRequest(wallet, operation, id, args);
+        return await wallet.handleCoreApiRequest(operation, id, args);
       }
     }
   }
diff --git a/packages/taler-wallet-cli/package.json 
b/packages/taler-wallet-cli/package.json
index 1870aa29..72a737d4 100644
--- a/packages/taler-wallet-cli/package.json
+++ b/packages/taler-wallet-cli/package.json
@@ -43,6 +43,7 @@
     "typescript": "^3.9.7"
   },
   "dependencies": {
+    "axios": "^0.19.2",
     "source-map-support": "^0.5.19",
     "taler-wallet-core": "workspace:*",
     "tslib": "^2.0.0"
diff --git a/packages/taler-wallet-cli/src/index.ts 
b/packages/taler-wallet-cli/src/index.ts
index a32ed226..94f01ba8 100644
--- a/packages/taler-wallet-cli/src/index.ts
+++ b/packages/taler-wallet-cli/src/index.ts
@@ -26,7 +26,6 @@ import {
   NodeHttpLib,
   PreparePayResultType,
   setDangerousTimetravel,
-  handleCoreApiRequest,
   classifyTalerUri,
   TalerUriType,
   decodeCrock,
@@ -34,10 +33,10 @@ import {
   codecForList,
   codecForString,
   printTestVectors,
+  NodeThreadCryptoWorkerFactory,
+  CryptoApi,
 } from "taler-wallet-core";
 import * as clk from "./clk";
-import { NodeThreadCryptoWorkerFactory } from 
"taler-wallet-core/lib/crypto/workers/nodeThreadWorker";
-import { CryptoApi } from "taler-wallet-core/lib/crypto/workers/cryptoApi";
 
 // This module also serves as the entry point for the crypto
 // thread worker, and thus must expose these two handlers.
@@ -210,8 +209,7 @@ walletCli
         console.error("Invalid JSON");
         process.exit(1);
       }
-      const resp = await handleCoreApiRequest(
-        wallet,
+      const resp = await wallet.handleCoreApiRequest(
         args.api.operation,
         "reqid-1",
         requestJson,
diff --git a/packages/taler-wallet-core/src/index.ts 
b/packages/taler-wallet-core/src/index.ts
index 784c9d63..1d5dc493 100644
--- a/packages/taler-wallet-core/src/index.ts
+++ b/packages/taler-wallet-core/src/index.ts
@@ -37,8 +37,6 @@ export * from "./types/walletTypes";
 
 export * from "./types/talerTypes";
 
-export * from "./walletCoreApiHandler";
-
 export * from "./util/taleruri";
 
 export * from "./util/time";
@@ -54,7 +52,7 @@ export * from "./util/testvectors";
 export * from "./operations/versions";
 
 export type { CryptoWorker } from "./crypto/workers/cryptoWorker";
-export type { CryptoWorkerFactory } from "./crypto/workers/cryptoApi";
+export { CryptoWorkerFactory, CryptoApi } from "./crypto/workers/cryptoApi";
 
 export * from "./util/http";
 
diff --git a/packages/taler-wallet-core/src/operations/testing.ts 
b/packages/taler-wallet-core/src/operations/testing.ts
index 3ccfafc9..629cd92f 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -21,10 +21,19 @@ import {
   checkSuccessResponseOrThrow,
 } from "../util/http";
 import { codecForAny } from "../util/codec";
-import { AmountString } from "../types/talerTypes";
+import {
+  AmountString,
+  CheckPaymentResponse,
+  codecForCheckPaymentResponse,
+} from "../types/talerTypes";
 import { InternalWalletState } from "./state";
 import { createTalerWithdrawReserve } from "./reserves";
 import { URL } from "../util/url";
+import { Wallet } from "../wallet";
+import { Amounts } from "../util/amounts";
+import { NodeHttpLib } from "../headless/NodeHttpLib";
+import { getDefaultNodeWallet } from "../headless/helpers";
+import { TestPayArgs, PreparePayResultType, IntegrationTestArgs } from 
"../types/walletTypes";
 
 const logger = new Logger("operations/testing.ts");
 
@@ -38,6 +47,11 @@ interface BankWithdrawalResponse {
   withdrawal_id: string;
 }
 
+interface MerchantBackendInfo {
+  baseUrl: string;
+  apikey: string;
+}
+
 /**
  * Generate a random alphanumeric ID.  Does *not* use cryptographically
  * secure randomness.
@@ -154,3 +168,268 @@ async function registerRandomBankUser(
   await checkSuccessResponseOrThrow(resp);
   return bankUser;
 }
+
+async function refund(
+  http: HttpRequestLibrary,
+  merchantBackend: MerchantBackendInfo,
+  orderId: string,
+  reason: string,
+  refundAmount: string,
+): Promise<string> {
+  const reqUrl = new URL(
+    `private/orders/${orderId}/refund`,
+    merchantBackend.baseUrl,
+  );
+  const refundReq = {
+    order_id: orderId,
+    reason,
+    refund: refundAmount,
+  };
+  const resp = await http.postJson(reqUrl.href, refundReq, {
+    headers: {
+      Authorization: `ApiKey ${merchantBackend.apikey}`,
+    },
+  });
+  const r = await readSuccessResponseJsonOrThrow(resp, codecForAny());
+  const refundUri = r.taler_refund_uri;
+  if (!refundUri) {
+    throw Error("no refund URI in response");
+  }
+  return refundUri;
+}
+
+async function createOrder(
+  http: HttpRequestLibrary,
+  merchantBackend: MerchantBackendInfo,
+  amount: string,
+  summary: string,
+  fulfillmentUrl: string,
+): Promise<{ orderId: string }> {
+  const t = Math.floor(new Date().getTime() / 1000) + 15 * 60;
+  const reqUrl = new URL("private/orders", merchantBackend.baseUrl).href;
+  const orderReq = {
+    order: {
+      amount,
+      summary,
+      fulfillment_url: fulfillmentUrl,
+      refund_deadline: { t_ms: t * 1000 },
+      wire_transfer_deadline: { t_ms: t * 1000 },
+    },
+  };
+  const resp = await http.postJson(reqUrl, orderReq, {
+    headers: {
+      Authorization: `ApiKey ${merchantBackend.apikey}`,
+    },
+  });
+  const r = await readSuccessResponseJsonOrThrow(resp, codecForAny());
+  const orderId = r.order_id;
+  if (!orderId) {
+    throw Error("no order id in response");
+  }
+  return { orderId };
+}
+
+async function checkPayment(
+  http: HttpRequestLibrary,
+  merchantBackend: MerchantBackendInfo,
+  orderId: string,
+): Promise<CheckPaymentResponse> {
+  const reqUrl = new URL(`/private/orders/${orderId}`, 
merchantBackend.baseUrl);
+  reqUrl.searchParams.set("order_id", orderId);
+  const resp = await http.get(reqUrl.href, {
+    headers: {
+      Authorization: `ApiKey ${merchantBackend.apikey}`,
+    },
+  });
+  return readSuccessResponseJsonOrThrow(resp, codecForCheckPaymentResponse());
+}
+
+interface BankUser {
+  username: string;
+  password: string;
+}
+
+interface BankWithdrawalResponse {
+  taler_withdraw_uri: string;
+  withdrawal_id: string;
+}
+
+async function makePayment(
+  http: HttpRequestLibrary,
+  wallet: Wallet,
+  merchant: MerchantBackendInfo,
+  amount: string,
+  summary: string,
+): Promise<{ orderId: string }> {
+  const orderResp = await createOrder(
+    http,
+    merchant,
+    amount,
+    summary,
+    "taler://fulfillment-success/thx",
+  );
+
+  console.log("created order with orderId", orderResp.orderId);
+
+  let paymentStatus = await checkPayment(http, merchant, orderResp.orderId);
+
+  console.log("payment status", paymentStatus);
+
+  const talerPayUri = paymentStatus.taler_pay_uri;
+  if (!talerPayUri) {
+    throw Error("no taler://pay/ URI in payment response");
+  }
+
+  const preparePayResult = await wallet.preparePayForUri(talerPayUri);
+
+  console.log("prepare pay result", preparePayResult);
+
+  if (preparePayResult.status != "payment-possible") {
+    throw Error("payment not possible");
+  }
+
+  const confirmPayResult = await wallet.confirmPay(
+    preparePayResult.proposalId,
+    undefined,
+  );
+
+  console.log("confirmPayResult", confirmPayResult);
+
+  paymentStatus = await checkPayment(http, merchant, orderResp.orderId);
+
+  console.log("payment status after wallet payment:", paymentStatus);
+
+  if (paymentStatus.order_status !== "paid") {
+    throw Error("payment did not succeed");
+  }
+
+  return {
+    orderId: orderResp.orderId,
+  };
+}
+
+export async function runIntegrationTest(
+  http: HttpRequestLibrary,
+  wallet: Wallet,
+  args: IntegrationTestArgs,
+): Promise<void> {
+  logger.info("running test with arguments", args);
+
+  const parsedSpendAmount = Amounts.parseOrThrow(args.amountToSpend);
+  const currency = parsedSpendAmount.currency;
+
+  const myHttpLib = new NodeHttpLib();
+  myHttpLib.setThrottling(false);
+
+  const myWallet = await getDefaultNodeWallet({ httpLib: myHttpLib });
+
+  myWallet.runRetryLoop().catch((e) => {
+    console.error("exception during retry loop:", e);
+  });
+
+  logger.info("withdrawing test balance");
+  await wallet.withdrawTestBalance(
+    args.amountToWithdraw,
+    args.bankBaseUrl,
+    args.exchangeBaseUrl,
+  );
+  logger.info("done withdrawing test balance");
+
+  const balance = await myWallet.getBalances();
+
+  console.log(JSON.stringify(balance, null, 2));
+
+  const myMerchant: MerchantBackendInfo = {
+    baseUrl: args.merchantBaseUrl,
+    apikey: args.merchantApiKey,
+  };
+
+  await makePayment(
+    http,
+    wallet,
+    myMerchant,
+    args.amountToSpend,
+    "hello world",
+  );
+
+  // Wait until the refresh is done
+  await myWallet.runUntilDone();
+
+  console.log("withdrawing test balance for refund");
+  const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`);
+  const spendAmountTwo = Amounts.parseOrThrow(`${currency}:7`);
+  const refundAmount = Amounts.parseOrThrow(`${currency}:6`);
+  const spendAmountThree = Amounts.parseOrThrow(`${currency}:3`);
+
+  await myWallet.withdrawTestBalance(
+    Amounts.stringify(withdrawAmountTwo),
+    args.bankBaseUrl,
+    args.exchangeBaseUrl,
+  );
+
+  // Wait until the withdraw is done
+  await myWallet.runUntilDone();
+
+  const { orderId: refundOrderId } = await makePayment(
+    http,
+    myWallet,
+    myMerchant,
+    Amounts.stringify(spendAmountTwo),
+    "order that will be refunded",
+  );
+
+  const refundUri = await refund(
+    http,
+    myMerchant,
+    refundOrderId,
+    "test refund",
+    Amounts.stringify(refundAmount),
+  );
+
+  console.log("refund URI", refundUri);
+
+  await myWallet.applyRefund(refundUri);
+
+  // Wait until the refund is done
+  await myWallet.runUntilDone();
+
+  await makePayment(
+    http,
+    myWallet,
+    myMerchant,
+    Amounts.stringify(spendAmountThree),
+    "payment after refund",
+  );
+
+  await myWallet.runUntilDone();
+}
+
+export async function testPay(
+  http: HttpRequestLibrary,
+  wallet: Wallet,
+  args: TestPayArgs,
+) {
+  console.log("creating order");
+  const merchant = { apikey: args.apikey, baseUrl: args.merchant };
+  const orderResp = await createOrder(
+    http,
+    merchant,
+    args.amount,
+    args.summary,
+    "taler://fulfillment-success/thank+you",
+  );
+  console.log("created new order with order ID", orderResp.orderId);
+  const checkPayResp = await checkPayment(http, merchant, orderResp.orderId);
+  const talerPayUri = checkPayResp.taler_pay_uri;
+  if (!talerPayUri) {
+    console.error("fatal: no taler pay URI received from backend");
+    process.exit(1);
+    return;
+  }
+  console.log("taler pay URI:", talerPayUri);
+  const result = await wallet.preparePayForUri(talerPayUri);
+  if (result.status !== PreparePayResultType.PaymentPossible) {
+    throw Error(`unexpected prepare pay status: ${result.status}`);
+  }
+  await wallet.confirmPay(result.proposalId, undefined);
+}
diff --git a/packages/taler-wallet-core/src/types/walletTypes.ts 
b/packages/taler-wallet-core/src/types/walletTypes.ts
index 8521af3f..e64187e7 100644
--- a/packages/taler-wallet-core/src/types/walletTypes.ts
+++ b/packages/taler-wallet-core/src/types/walletTypes.ts
@@ -229,9 +229,7 @@ export const codecForConfirmPayResultPending = (): Codec<
     .property("type", codecForConstString(ConfirmPayResultType.Pending))
     .build("ConfirmPayResultPending");
 
-export const codecForConfirmPayResultDone = (): Codec<
-  ConfirmPayResultDone
-> =>
+export const codecForConfirmPayResultDone = (): Codec<ConfirmPayResultDone> =>
   buildCodecForObject<ConfirmPayResultDone>()
     .property("type", codecForConstString(ConfirmPayResultType.Done))
     .property("nextUrl", codecForString())
@@ -240,7 +238,10 @@ export const codecForConfirmPayResultDone = (): Codec<
 export const codecForConfirmPayResult = (): Codec<ConfirmPayResult> =>
   buildCodecForUnion<ConfirmPayResult>()
     .discriminateOn("type")
-    .alternative(ConfirmPayResultType.Pending, 
codecForConfirmPayResultPending())
+    .alternative(
+      ConfirmPayResultType.Pending,
+      codecForConfirmPayResultPending(),
+    )
     .alternative(ConfirmPayResultType.Done, codecForConfirmPayResultDone())
     .build("ConfirmPayResult");
 
@@ -650,3 +651,181 @@ export interface GetExchangeTosResult {
    */
   acceptedEtag: string | undefined;
 }
+
+export interface TestPayArgs {
+  merchant: string;
+  apikey: string;
+  amount: string;
+  summary: string;
+}
+
+export const codecForTestPayArgs = (): Codec<TestPayArgs> =>
+  buildCodecForObject<TestPayArgs>()
+    .property("merchant", codecForString())
+    .property("apikey", codecForString())
+    .property("amount", codecForString())
+    .property("summary", codecForString())
+    .build("TestPayArgs");
+
+export interface IntegrationTestArgs {
+  exchangeBaseUrl: string;
+  bankBaseUrl: string;
+  merchantBaseUrl: string;
+  merchantApiKey: string;
+  amountToWithdraw: string;
+  amountToSpend: string;
+}
+
+export const codecForIntegrationTestArgs = (): Codec<IntegrationTestArgs> =>
+  buildCodecForObject<IntegrationTestArgs>()
+    .property("exchangeBaseUrl", codecForString())
+    .property("bankBaseUrl", codecForString())
+    .property("merchantBaseUrl", codecForString())
+    .property("merchantApiKey", codecForString())
+    .property("amountToSpend", codecForAmountString())
+    .property("amountToWithdraw", codecForAmountString())
+    .build("IntegrationTestArgs");
+
+export interface AddExchangeRequest {
+  exchangeBaseUrl: string;
+}
+
+export const codecForAddExchangeRequest = (): Codec<AddExchangeRequest> =>
+  buildCodecForObject<AddExchangeRequest>()
+    .property("exchangeBaseUrl", codecForString())
+    .build("AddExchangeRequest");
+
+export interface GetExchangeTosRequest {
+  exchangeBaseUrl: string;
+}
+
+export const codecForGetExchangeTosRequest = (): Codec<GetExchangeTosRequest> 
=>
+  buildCodecForObject<GetExchangeTosRequest>()
+    .property("exchangeBaseUrl", codecForString())
+    .build("GetExchangeTosRequest");
+
+export interface AcceptManualWithdrawalRequest {
+  exchangeBaseUrl: string;
+  amount: string;
+}
+
+export const codecForAcceptManualWithdrawalRequet = (): Codec<
+  AcceptManualWithdrawalRequest
+> =>
+  buildCodecForObject<AcceptManualWithdrawalRequest>()
+    .property("exchangeBaseUrl", codecForString())
+    .property("amount", codecForString())
+    .build("AcceptManualWithdrawalRequest");
+
+export interface GetWithdrawalDetailsForAmountRequest {
+  exchangeBaseUrl: string;
+  amount: string;
+}
+
+export interface AcceptBankIntegratedWithdrawalRequest {
+  talerWithdrawUri: string;
+  exchangeBaseUrl: string;
+}
+
+export const codecForAcceptBankIntegratedWithdrawalRequest = (): Codec<
+  AcceptBankIntegratedWithdrawalRequest
+> =>
+  buildCodecForObject<AcceptBankIntegratedWithdrawalRequest>()
+    .property("exchangeBaseUrl", codecForString())
+    .property("talerWithdrawUri", codecForString())
+    .build("AcceptBankIntegratedWithdrawalRequest");
+
+export const codecForGetWithdrawalDetailsForAmountRequest = (): Codec<
+  GetWithdrawalDetailsForAmountRequest
+> =>
+  buildCodecForObject<GetWithdrawalDetailsForAmountRequest>()
+    .property("exchangeBaseUrl", codecForString())
+    .property("amount", codecForString())
+    .build("GetWithdrawalDetailsForAmountRequest");
+
+export interface AcceptExchangeTosRequest {
+  exchangeBaseUrl: string;
+  etag: string;
+}
+
+export const codecForAcceptExchangeTosRequest = (): Codec<
+  AcceptExchangeTosRequest
+> =>
+  buildCodecForObject<AcceptExchangeTosRequest>()
+    .property("exchangeBaseUrl", codecForString())
+    .property("etag", codecForString())
+    .build("AcceptExchangeTosRequest");
+
+export interface ApplyRefundRequest {
+  talerRefundUri: string;
+}
+
+export const codecForApplyRefundRequest = (): Codec<ApplyRefundRequest> =>
+  buildCodecForObject<ApplyRefundRequest>()
+    .property("talerRefundUri", codecForString())
+    .build("ApplyRefundRequest");
+
+export interface GetWithdrawalDetailsForUriRequest {
+  talerWithdrawUri: string;
+}
+
+export const codecForGetWithdrawalDetailsForUri = (): Codec<
+  GetWithdrawalDetailsForUriRequest
+> =>
+  buildCodecForObject<GetWithdrawalDetailsForUriRequest>()
+    .property("talerWithdrawUri", codecForString())
+    .build("GetWithdrawalDetailsForUriRequest");
+
+export interface AbortProposalRequest {
+  proposalId: string;
+}
+
+export const codecForAbortProposalRequest = (): Codec<AbortProposalRequest> =>
+  buildCodecForObject<AbortProposalRequest>()
+    .property("proposalId", codecForString())
+    .build("AbortProposalRequest");
+
+export interface PreparePayRequest {
+  talerPayUri: string;
+}
+
+export const codecForPreparePayRequest = (): Codec<PreparePayRequest> =>
+  buildCodecForObject<PreparePayRequest>()
+    .property("talerPayUri", codecForString())
+    .build("PreparePay");
+
+export interface ConfirmPayRequest {
+  proposalId: string;
+  sessionId?: string;
+}
+
+export const codecForConfirmPayRequest = (): Codec<ConfirmPayRequest> =>
+  buildCodecForObject<ConfirmPayRequest>()
+    .property("proposalId", codecForString())
+    .property("sessionId", codecOptional(codecForString()))
+    .build("ConfirmPay");
+
+export type CoreApiResponse = CoreApiResponseSuccess | CoreApiResponseError;
+
+export type CoreApiEnvelope = CoreApiResponse | CoreApiNotification;
+
+export interface CoreApiNotification {
+  type: "notification";
+  payload: unknown;
+}
+
+export interface CoreApiResponseSuccess {
+  // To distinguish the message from notifications
+  type: "response";
+  operation: string;
+  id: string;
+  result: unknown;
+}
+
+export interface CoreApiResponseError {
+  // To distinguish the message from notifications
+  type: "error";
+  operation: string;
+  id: string;
+  error: OperationErrorDetails;
+}
diff --git a/packages/taler-wallet-core/src/wallet.ts 
b/packages/taler-wallet-core/src/wallet.ts
index 4a409f58..0b3e2ed6 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -70,6 +70,22 @@ import {
   GetExchangeTosResult,
   AcceptManualWithdrawalResult,
   BalancesResponse,
+  TestPayArgs,
+  PreparePayResultType,
+  IntegrationTestArgs,
+  codecForAddExchangeRequest,
+  codecForGetWithdrawalDetailsForUri,
+  codecForAcceptManualWithdrawalRequet,
+  codecForGetWithdrawalDetailsForAmountRequest,
+  codecForAcceptExchangeTosRequest,
+  codecForApplyRefundRequest,
+  codecForAcceptBankIntegratedWithdrawalRequest,
+  codecForGetExchangeTosRequest,
+  codecForAbortProposalRequest,
+  codecForConfirmPayRequest,
+  CoreApiResponse,
+  codecForPreparePayRequest,
+  codecForIntegrationTestArgs,
 } from "./types/walletTypes";
 import { Logger } from "./util/logging";
 
@@ -107,13 +123,23 @@ import { WalletNotification, NotificationType } from 
"./types/notifications";
 import { processPurchaseQueryRefund, applyRefund } from "./operations/refund";
 import { durationMin, Duration } from "./util/time";
 import { processRecoupGroup } from "./operations/recoup";
-import { OperationFailedAndReportedError } from "./operations/errors";
+import {
+  OperationFailedAndReportedError,
+  OperationFailedError,
+  makeErrorDetails,
+} from "./operations/errors";
 import {
   TransactionsRequest,
   TransactionsResponse,
+  codecForTransactionsRequest,
 } from "./types/transactions";
 import { getTransactions } from "./operations/transactions";
-import { withdrawTestBalance } from "./operations/testing";
+import {
+  withdrawTestBalance,
+  runIntegrationTest,
+  testPay,
+} from "./operations/testing";
+import { TalerErrorCode } from ".";
 
 const builtinCurrencies: CurrencyRecord[] = [
   {
@@ -879,4 +905,168 @@ export class Wallet {
   ): Promise<void> {
     await withdrawTestBalance(this.ws, amount, bankBaseUrl, exchangeBaseUrl);
   }
+
+  async runIntegrationtest(args: IntegrationTestArgs): Promise<void> {
+    return runIntegrationTest(this.ws.http, this, args);
+  }
+
+  async testPay(args: TestPayArgs) {
+    return testPay(this.ws.http, this, args);
+  }
+
+  /**
+   * Implementation of the "wallet-core" API.
+   */
+
+  private async dispatchRequestInternal(
+    operation: string,
+    payload: unknown,
+  ): Promise<Record<string, any>> {
+    switch (operation) {
+      case "withdrawTestkudos": {
+        await this.withdrawTestBalance();
+        return {};
+      }
+      case "runIntegrationtest": {
+        const req = codecForIntegrationTestArgs().decode(payload);
+        await this.runIntegrationtest(req);
+        return {}
+      }
+      case "testPay": {
+        const req = codecForIntegrationTestArgs().decode(payload);
+        await this.runIntegrationtest(req);
+        return {}
+      }
+      case "getTransactions": {
+        const req = codecForTransactionsRequest().decode(payload);
+        return await this.getTransactions(req);
+      }
+      case "addExchange": {
+        const req = codecForAddExchangeRequest().decode(payload);
+        await this.updateExchangeFromUrl(req.exchangeBaseUrl);
+        return {};
+      }
+      case "listExchanges": {
+        return await this.getExchanges();
+      }
+      case "getWithdrawalDetailsForUri": {
+        const req = codecForGetWithdrawalDetailsForUri().decode(payload);
+        return await this.getWithdrawalDetailsForUri(req.talerWithdrawUri);
+      }
+      case "acceptManualWithdrawal": {
+        const req = codecForAcceptManualWithdrawalRequet().decode(payload);
+        const res = await this.acceptManualWithdrawal(
+          req.exchangeBaseUrl,
+          Amounts.parseOrThrow(req.amount),
+        );
+        return res;
+      }
+      case "getWithdrawalDetailsForAmount": {
+        const req = codecForGetWithdrawalDetailsForAmountRequest().decode(
+          payload,
+        );
+        return await this.getWithdrawalDetailsForAmount(
+          req.exchangeBaseUrl,
+          Amounts.parseOrThrow(req.amount),
+        );
+      }
+      case "getBalances": {
+        return await this.getBalances();
+      }
+      case "getPendingOperations": {
+        return await this.getPendingOperations();
+      }
+      case "setExchangeTosAccepted": {
+        const req = codecForAcceptExchangeTosRequest().decode(payload);
+        await this.acceptExchangeTermsOfService(
+          req.exchangeBaseUrl,
+          req.etag,
+        );
+        return {};
+      }
+      case "applyRefund": {
+        const req = codecForApplyRefundRequest().decode(payload);
+        return await this.applyRefund(req.talerRefundUri);
+      }
+      case "acceptBankIntegratedWithdrawal": {
+        const req = codecForAcceptBankIntegratedWithdrawalRequest().decode(
+          payload,
+        );
+        return await this.acceptWithdrawal(
+          req.talerWithdrawUri,
+          req.exchangeBaseUrl,
+        );
+      }
+      case "getExchangeTos": {
+        const req = codecForGetExchangeTosRequest().decode(payload);
+        return this.getExchangeTos(req.exchangeBaseUrl);
+      }
+      case "abortProposal": {
+        const req = codecForAbortProposalRequest().decode(payload);
+        await this.refuseProposal(req.proposalId);
+        return {};
+      }
+      case "retryPendingNow": {
+        await this.runPending(true);
+        return {};
+      }
+      case "preparePay": {
+        const req = codecForPreparePayRequest().decode(payload);
+        return await this.preparePayForUri(req.talerPayUri);
+      }
+      case "confirmPay": {
+        const req = codecForConfirmPayRequest().decode(payload);
+        return await this.confirmPay(req.proposalId, req.sessionId);
+      }
+    }
+    throw OperationFailedError.fromCode(
+      TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN,
+      "unknown operation",
+      {
+        operation,
+      },
+    );
+  }
+
+  /**
+   * Handle a request to the wallet-core API.
+   */
+  async handleCoreApiRequest(
+    operation: string,
+    id: string,
+    payload: unknown,
+  ): Promise<CoreApiResponse> {
+    try {
+      const result = await this.dispatchRequestInternal(operation, payload);
+      return {
+        type: "response",
+        operation,
+        id,
+        result,
+      };
+    } catch (e) {
+      if (
+        e instanceof OperationFailedError ||
+        e instanceof OperationFailedAndReportedError
+      ) {
+        return {
+          type: "error",
+          operation,
+          id,
+          error: e.operationError,
+        };
+      } else {
+        return {
+          type: "error",
+          operation,
+          id,
+          error: makeErrorDetails(
+            TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
+            `unexpected exception: ${e}`,
+            {},
+          ),
+        };
+      }
+    }
+  }
 }
diff --git a/packages/taler-wallet-core/src/walletCoreApiHandler.ts 
b/packages/taler-wallet-core/src/walletCoreApiHandler.ts
deleted file mode 100644
index 5bc9005a..00000000
--- a/packages/taler-wallet-core/src/walletCoreApiHandler.ts
+++ /dev/null
@@ -1,318 +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/>
- */
-
-import { Wallet } from "./wallet";
-import {
-  OperationFailedError,
-  OperationFailedAndReportedError,
-  makeErrorDetails,
-} from "./operations/errors";
-import { TalerErrorCode } from "./TalerErrorCode";
-import { codecForTransactionsRequest } from "./types/transactions";
-import {
-  buildCodecForObject,
-  codecForString,
-  Codec,
-  codecOptional,
-} from "./util/codec";
-import { Amounts } from "./util/amounts";
-import { OperationErrorDetails } from "./types/walletTypes";
-
-export interface AddExchangeRequest {
-  exchangeBaseUrl: string;
-}
-
-export const codecForAddExchangeRequest = (): Codec<AddExchangeRequest> =>
-  buildCodecForObject<AddExchangeRequest>()
-    .property("exchangeBaseUrl", codecForString())
-    .build("AddExchangeRequest");
-
-export interface GetExchangeTosRequest {
-  exchangeBaseUrl: string;
-}
-
-export const codecForGetExchangeTosRequest = (): Codec<GetExchangeTosRequest> 
=>
-  buildCodecForObject<GetExchangeTosRequest>()
-    .property("exchangeBaseUrl", codecForString())
-    .build("GetExchangeTosRequest");
-
-export interface AcceptManualWithdrawalRequest {
-  exchangeBaseUrl: string;
-  amount: string;
-}
-
-export const codecForAcceptManualWithdrawalRequet = (): Codec<
-  AcceptManualWithdrawalRequest
-> =>
-  buildCodecForObject<AcceptManualWithdrawalRequest>()
-    .property("exchangeBaseUrl", codecForString())
-    .property("amount", codecForString())
-    .build("AcceptManualWithdrawalRequest");
-
-export interface GetWithdrawalDetailsForAmountRequest {
-  exchangeBaseUrl: string;
-  amount: string;
-}
-
-export interface AcceptBankIntegratedWithdrawalRequest {
-  talerWithdrawUri: string;
-  exchangeBaseUrl: string;
-}
-
-export const codecForAcceptBankIntegratedWithdrawalRequest = (): Codec<
-  AcceptBankIntegratedWithdrawalRequest
-> =>
-  buildCodecForObject<AcceptBankIntegratedWithdrawalRequest>()
-    .property("exchangeBaseUrl", codecForString())
-    .property("talerWithdrawUri", codecForString())
-    .build("AcceptBankIntegratedWithdrawalRequest");
-
-export const codecForGetWithdrawalDetailsForAmountRequest = (): Codec<
-  GetWithdrawalDetailsForAmountRequest
-> =>
-  buildCodecForObject<GetWithdrawalDetailsForAmountRequest>()
-    .property("exchangeBaseUrl", codecForString())
-    .property("amount", codecForString())
-    .build("GetWithdrawalDetailsForAmountRequest");
-
-export interface AcceptExchangeTosRequest {
-  exchangeBaseUrl: string;
-  etag: string;
-}
-
-export const codecForAcceptExchangeTosRequest = (): 
Codec<AcceptExchangeTosRequest> =>
-  buildCodecForObject<AcceptExchangeTosRequest>()
-    .property("exchangeBaseUrl", codecForString())
-    .property("etag", codecForString())
-    .build("AcceptExchangeTosRequest");
-
-export interface ApplyRefundRequest {
-  talerRefundUri: string;
-}
-
-export const codecForApplyRefundRequest = (): Codec<ApplyRefundRequest> =>
-  buildCodecForObject<ApplyRefundRequest>()
-    .property("talerRefundUri", codecForString())
-    .build("ApplyRefundRequest");
-
-export interface GetWithdrawalDetailsForUriRequest {
-  talerWithdrawUri: string;
-}
-
-export const codecForGetWithdrawalDetailsForUri = (): Codec<
-  GetWithdrawalDetailsForUriRequest
-> =>
-  buildCodecForObject<GetWithdrawalDetailsForUriRequest>()
-    .property("talerWithdrawUri", codecForString())
-    .build("GetWithdrawalDetailsForUriRequest");
-
-export interface AbortProposalRequest {
-  proposalId: string;
-}
-
-export const codecForAbortProposalRequest = (): Codec<AbortProposalRequest> =>
-  buildCodecForObject<AbortProposalRequest>()
-    .property("proposalId", codecForString())
-    .build("AbortProposalRequest");
-
-export interface PreparePayRequest {
-  talerPayUri: string;
-}
-
-const codecForPreparePayRequest = (): Codec<PreparePayRequest> =>
-  buildCodecForObject<PreparePayRequest>()
-    .property("talerPayUri", codecForString())
-    .build("PreparePay");
-
-export interface ConfirmPayRequest {
-  proposalId: string;
-  sessionId?: string;
-}
-
-export const codecForConfirmPayRequest = (): Codec<ConfirmPayRequest> =>
-  buildCodecForObject<ConfirmPayRequest>()
-    .property("proposalId", codecForString())
-    .property("sessionId", codecOptional(codecForString()))
-    .build("ConfirmPay");
-
-/**
- * Implementation of the "wallet-core" API.
- */
-
-async function dispatchRequestInternal(
-  wallet: Wallet,
-  operation: string,
-  payload: unknown,
-): Promise<Record<string, any>> {
-  switch (operation) {
-    case "withdrawTestkudos":
-      await wallet.withdrawTestBalance();
-      return {};
-    case "getTransactions": {
-      const req = codecForTransactionsRequest().decode(payload);
-      return await wallet.getTransactions(req);
-    }
-    case "addExchange": {
-      const req = codecForAddExchangeRequest().decode(payload);
-      await wallet.updateExchangeFromUrl(req.exchangeBaseUrl);
-      return {};
-    }
-    case "listExchanges": {
-      return await wallet.getExchanges();
-    }
-    case "getWithdrawalDetailsForUri": {
-      const req = codecForGetWithdrawalDetailsForUri().decode(payload);
-      return await wallet.getWithdrawalDetailsForUri(req.talerWithdrawUri);
-    }
-    case "acceptManualWithdrawal": {
-      const req = codecForAcceptManualWithdrawalRequet().decode(payload);
-      const res = await wallet.acceptManualWithdrawal(
-        req.exchangeBaseUrl,
-        Amounts.parseOrThrow(req.amount),
-      );
-      return res;
-    }
-    case "getWithdrawalDetailsForAmount": {
-      const req = codecForGetWithdrawalDetailsForAmountRequest().decode(
-        payload,
-      );
-      return await wallet.getWithdrawalDetailsForAmount(
-        req.exchangeBaseUrl,
-        Amounts.parseOrThrow(req.amount),
-      );
-    }
-    case "getBalances": {
-      return await wallet.getBalances();
-    }
-    case "getPendingOperations": {
-      return await wallet.getPendingOperations();
-    }
-    case "setExchangeTosAccepted": {
-      const req = codecForAcceptExchangeTosRequest().decode(payload);
-      await wallet.acceptExchangeTermsOfService(req.exchangeBaseUrl, req.etag);
-      return {};
-    }
-    case "applyRefund": {
-      const req = codecForApplyRefundRequest().decode(payload);
-      return await wallet.applyRefund(req.talerRefundUri);
-    }
-    case "acceptBankIntegratedWithdrawal": {
-      const req = codecForAcceptBankIntegratedWithdrawalRequest().decode(
-        payload,
-      );
-      return await wallet.acceptWithdrawal(
-        req.talerWithdrawUri,
-        req.exchangeBaseUrl,
-      );
-    }
-    case "getExchangeTos": {
-      const req = codecForGetExchangeTosRequest().decode(payload);
-      return wallet.getExchangeTos(req.exchangeBaseUrl);
-    }
-    case "abortProposal": {
-      const req = codecForAbortProposalRequest().decode(payload);
-      await wallet.refuseProposal(req.proposalId);
-      return {};
-    }
-    case "retryPendingNow": {
-      await wallet.runPending(true);
-      return {};
-    }
-    case "preparePay": {
-      const req = codecForPreparePayRequest().decode(payload);
-      return await wallet.preparePayForUri(req.talerPayUri);
-    }
-    case "confirmPay": {
-      const req = codecForConfirmPayRequest().decode(payload);
-      return await wallet.confirmPay(req.proposalId, req.sessionId);
-    }
-  }
-  throw OperationFailedError.fromCode(
-    TalerErrorCode.WALLET_CORE_API_OPERATION_UNKNOWN,
-    "unknown operation",
-    {
-      operation,
-    },
-  );
-}
-
-export type CoreApiResponse = CoreApiResponseSuccess | CoreApiResponseError;
-
-export type CoreApiEnvelope = CoreApiResponse | CoreApiNotification;
-
-export interface CoreApiNotification {
-  type: "notification";
-  payload: unknown;
-}
-
-export interface CoreApiResponseSuccess {
-  // To distinguish the message from notifications
-  type: "response";
-  operation: string;
-  id: string;
-  result: unknown;
-}
-
-export interface CoreApiResponseError {
-  // To distinguish the message from notifications
-  type: "error";
-  operation: string;
-  id: string;
-  error: OperationErrorDetails;
-}
-
-/**
- * Handle a request to the wallet-core API.
- */
-export async function handleCoreApiRequest(
-  w: Wallet,
-  operation: string,
-  id: string,
-  payload: unknown,
-): Promise<CoreApiResponse> {
-  try {
-    const result = await dispatchRequestInternal(w, operation, payload);
-    return {
-      type: "response",
-      operation,
-      id,
-      result,
-    };
-  } catch (e) {
-    if (
-      e instanceof OperationFailedError ||
-      e instanceof OperationFailedAndReportedError
-    ) {
-      return {
-        type: "error",
-        operation,
-        id,
-        error: e.operationError,
-      };
-    } else {
-      return {
-        type: "error",
-        operation,
-        id,
-        error: makeErrorDetails(
-          TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
-          `unexpected exception: ${e}`,
-          {},
-        ),
-      };
-    }
-  }
-}
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts 
b/packages/taler-wallet-webextension/src/wxBackend.ts
index 86008dd9..60d0b6d4 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -24,7 +24,6 @@
  * Imports.
  */
 import { isFirefox, getPermissionsApi } from "./compat";
-import * as wxApi from "./wxApi";
 import MessageSender = chrome.runtime.MessageSender;
 import { extendedPermissions } from "./permissions";
 
@@ -32,16 +31,12 @@ import {
   Wallet,
   OpenedPromise,
   openPromise,
-  deleteTalerDatabase,
-  WALLET_DB_MINOR_VERSION,
-  WalletDiagnostics,
   openTalerDatabase,
   Database,
   classifyTalerUri,
   TalerUriType,
   makeErrorDetails,
   TalerErrorCode,
-  handleCoreApiRequest,
 } from "taler-wallet-core";
 import { BrowserHttpLib } from "./browserHttpLib";
 import { BrowserCryptoWorkerFactory } from "./browserCryptoWorkerFactory";
@@ -82,7 +77,7 @@ async function dispatch(
     return;
   }
 
-  const r = await handleCoreApiRequest(w, req.operation, req.id, req.payload);
+  const r = await w.handleCoreApiRequest(req.operation, req.id, req.payload);
   try {
     sendResponse(r);
   } catch (e) {
@@ -251,7 +246,7 @@ function headerListener(
             );
           case TalerUriType.TalerRefund:
             return makeSyncWalletRedirect(
-              "/static/refund.html",
+              "refund.html",
               details.tabId,
               details.url,
               {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 78011a19..9bdba271 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -83,6 +83,7 @@ importers:
       typescript: ^3.9.7
   packages/taler-wallet-cli:
     dependencies:
+      axios: 0.19.2
       source-map-support: 0.5.19
       taler-wallet-core: 'link:../taler-wallet-core'
       tslib: 2.0.1
@@ -105,6 +106,7 @@ importers:
       '@rollup/plugin-node-resolve': ^8.4.0
       '@rollup/plugin-replace': ^2.3.3
       '@types/node': ^14.0.27
+      axios: ^0.19.2
       prettier: ^2.0.5
       rimraf: ^3.0.2
       rollup: ^2.23.0

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]