nuke some console.log statements, test wallet testing functionality in integration test

This commit is contained in:
Florian Dold 2020-08-14 15:53:50 +05:30
parent e3850158c2
commit 953cd9dc41
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
22 changed files with 361 additions and 168 deletions

View File

@ -29,6 +29,7 @@ import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import * as os from "os"; import * as os from "os";
import * as http from "http"; import * as http from "http";
import { deepStrictEqual } from "assert";
import { ChildProcess, spawn } from "child_process"; import { ChildProcess, spawn } from "child_process";
import { import {
Configuration, Configuration,
@ -53,6 +54,18 @@ import {
ConfirmPayRequest, ConfirmPayRequest,
ConfirmPayResult, ConfirmPayResult,
codecForConfirmPayResult, codecForConfirmPayResult,
IntegrationTestArgs,
TestPayArgs,
BalancesResponse,
codecForBalancesResponse,
encodeCrock,
getRandomBytes,
EddsaKeyPair,
eddsaGetPublic,
createEddsaKeyPair,
TransactionsResponse,
codecForTransactionsResponse,
WithdrawTestBalanceRequest,
} from "taler-wallet-core"; } from "taler-wallet-core";
import { URL } from "url"; import { URL } from "url";
import axios from "axios"; import axios from "axios";
@ -63,14 +76,6 @@ import {
PostOrderResponse, PostOrderResponse,
MerchantOrderPrivateStatusResponse, MerchantOrderPrivateStatusResponse,
} from "./merchantApiTypes"; } from "./merchantApiTypes";
import {
EddsaKeyPair,
getRandomBytes,
encodeCrock,
eddsaGetPublic,
createEddsaKeyPair,
} from "taler-wallet-core/lib/crypto/talerCrypto";
import { WithdrawalDetails } from "taler-wallet-core/lib/types/transactions";
const exec = util.promisify(require("child_process").exec); const exec = util.promisify(require("child_process").exec);
@ -277,6 +282,10 @@ export class GlobalTestState {
} }
} }
assertDeepEqual(actual: any, expected: any): asserts actual is any {
deepStrictEqual(actual, expected);
}
assertAmountEquals( assertAmountEquals(
amtExpected: string | AmountJson, amtExpected: string | AmountJson,
amtActual: string | AmountJson, amtActual: string | AmountJson,
@ -521,6 +530,10 @@ export class BankService {
config.setString("bank", "suggested_exchange_payto", exchangePayto); config.setString("bank", "suggested_exchange_payto", exchangePayto);
} }
get baseUrl(): string {
return `http://localhost:${this.bankConfig.httpPort}/`;
}
async createExchangeAccount( async createExchangeAccount(
accountName: string, accountName: string,
password: string, password: string,
@ -890,11 +903,10 @@ export interface MerchantConfig {
database: string; database: string;
} }
export interface PrivateOrderStatusQuery { export interface PrivateOrderStatusQuery {
instance?: string, instance?: string;
orderId: string, orderId: string;
sessionId?: string, sessionId?: string;
} }
export class MerchantService { export class MerchantService {
@ -993,7 +1005,9 @@ export class MerchantService {
}); });
} }
async queryPrivateOrderStatus(query: PrivateOrderStatusQuery): Promise<MerchantOrderPrivateStatusResponse> { async queryPrivateOrderStatus(
query: PrivateOrderStatusQuery,
): Promise<MerchantOrderPrivateStatusResponse> {
const reqUrl = new URL( const reqUrl = new URL(
`private/orders/${query.orderId}`, `private/orders/${query.orderId}`,
this.makeInstanceBaseUrl(query.instance), this.makeInstanceBaseUrl(query.instance),
@ -1215,6 +1229,46 @@ export class WalletCli {
throw new OperationFailedError(resp.error); throw new OperationFailedError(resp.error);
} }
async getBalances(): Promise<BalancesResponse> {
const resp = await this.apiRequest("getBalances", {});
if (resp.type === "response") {
return codecForBalancesResponse().decode(resp.result);
}
throw new OperationFailedError(resp.error);
}
async getTransactions(): Promise<TransactionsResponse> {
const resp = await this.apiRequest("getTransactions", {});
if (resp.type === "response") {
return codecForTransactionsResponse().decode(resp.result);
}
throw new OperationFailedError(resp.error);
}
async runIntegrationtest(args: IntegrationTestArgs): Promise<void> {
const resp = await this.apiRequest("runIntegrationtest", args);
if (resp.type === "response") {
return;
}
throw new OperationFailedError(resp.error);
}
async testPay(args: TestPayArgs): Promise<void> {
const resp = await this.apiRequest("testPay", args);
if (resp.type === "response") {
return;
}
throw new OperationFailedError(resp.error);
}
async withdrawTestBalance(args: WithdrawTestBalanceRequest): Promise<void> {
const resp = await this.apiRequest("withdrawTestBalance", args);
if (resp.type === "response") {
return;
}
throw new OperationFailedError(resp.error);
}
async getWithdrawalDetailsForUri( async getWithdrawalDetailsForUri(
req: GetWithdrawalDetailsForUriRequest, req: GetWithdrawalDetailsForUriRequest,
): Promise<WithdrawUriInfoResponse> { ): Promise<WithdrawUriInfoResponse> {
@ -1222,6 +1276,6 @@ export class WalletCli {
if (resp.type === "response") { if (resp.type === "response") {
return codecForWithdrawUriInfoResponse().decode(resp.result); return codecForWithdrawUriInfoResponse().decode(resp.result);
} }
throw new OperationFailedError(resp.error); throw new OperationFailedError(resp.error);
} }
} }

View File

@ -0,0 +1,90 @@
/*
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/>
*/
/**
* Integration test for the wallet testing functionality used by the exchange
* test cases.
*/
/**
* Imports.
*/
import { runTest, GlobalTestState } from "./harness";
import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
/**
* Run test for basic, bank-integrated withdrawal.
*/
runTest(async (t: GlobalTestState) => {
const {
wallet,
bank,
exchange,
merchant,
} = await createSimpleTestkudosEnvironment(t);
await wallet.runIntegrationtest({
amountToSpend: "TESTKUDOS:5",
amountToWithdraw: "TESTKUDOS:10",
bankBaseUrl: bank.baseUrl,
exchangeBaseUrl: exchange.baseUrl,
merchantApiKey: "sandbox",
merchantBaseUrl: merchant.makeInstanceBaseUrl(),
});
let txns = await wallet.getTransactions();
console.log(JSON.stringify(txns, undefined, 2));
let txTypes = txns.transactions.map((x) => x.type);
t.assertDeepEqual(txTypes, [
"withdrawal",
"payment",
"withdrawal",
"payment",
"refund",
"payment",
]);
wallet.deleteDatabase();
await wallet.withdrawTestBalance({
amount: "TESTKUDOS:10",
bankBaseUrl: bank.baseUrl,
exchangeBaseUrl: exchange.baseUrl,
});
await wallet.runUntilDone();
await wallet.testPay({
amount: "TESTKUDOS:5",
merchantApiKey: "sandbox",
merchantBaseUrl: merchant.makeInstanceBaseUrl(),
summary: "foo",
});
await wallet.runUntilDone();
txns = await wallet.getTransactions();
console.log(JSON.stringify(txns, undefined, 2));
txTypes = txns.transactions.map((x) => x.type);
t.assertDeepEqual(txTypes, [
"withdrawal",
"payment",
]);
await t.shutdown();
});

View File

@ -203,21 +203,21 @@ export class CryptoApi {
handleWorkerError(ws: WorkerState, e: any): void { handleWorkerError(ws: WorkerState, e: any): void {
if (ws.currentWorkItem) { if (ws.currentWorkItem) {
console.error( logger.error(
`error in worker during ${ws.currentWorkItem.operation}`, `error in worker during ${ws.currentWorkItem.operation}`,
e, e,
); );
} else { } else {
console.error("error in worker", e); logger.error("error in worker", e);
} }
console.error(e.message); logger.error(e.message);
try { try {
if (ws.w) { if (ws.w) {
ws.w.terminate(); ws.w.terminate();
ws.w = null; ws.w = null;
} }
} catch (e) { } catch (e) {
console.error(e); logger.error(e);
} }
if (ws.currentWorkItem !== null) { if (ws.currentWorkItem !== null) {
ws.currentWorkItem.reject(e); ws.currentWorkItem.reject(e);

View File

@ -105,7 +105,7 @@ export async function getDefaultNodeWallet(
} }
const myVersionChange = (): Promise<void> => { const myVersionChange = (): Promise<void> => {
console.error("version change requested, should not happen"); logger.error("version change requested, should not happen");
throw Error(); throw Error();
}; };
@ -119,7 +119,7 @@ export async function getDefaultNodeWallet(
require("worker_threads"); require("worker_threads");
workerFactory = new NodeThreadCryptoWorkerFactory(); workerFactory = new NodeThreadCryptoWorkerFactory();
} catch (e) { } catch (e) {
console.log( logger.warn(
"worker threads not available, falling back to synchronous workers", "worker threads not available, falling back to synchronous workers",
); );
workerFactory = new SynchronousCryptoWorkerFactory(); workerFactory = new SynchronousCryptoWorkerFactory();

View File

@ -26,6 +26,9 @@ export { strings } from "./strings";
// @ts-ignore: no type decl for this library // @ts-ignore: no type decl for this library
import * as jedLib from "jed"; import * as jedLib from "jed";
import { Logger } from "../util/logging";
const logger = new Logger("i18n/index.ts");
export let jed: any = undefined; export let jed: any = undefined;
@ -38,7 +41,7 @@ export function setupI18n(lang: string): any {
if (!strings[lang]) { if (!strings[lang]) {
lang = "en-US"; lang = "en-US";
console.log(`language ${lang} not found, defaulting to english`); logger.warn(`language ${lang} not found, defaulting to english`);
} }
jed = new jedLib.Jed(strings[lang]); jed = new jedLib.Jed(strings[lang]);
} }

View File

@ -19,59 +19,48 @@
*/ */
export { Wallet } from "./wallet"; export { Wallet } from "./wallet";
// Errors
export { TalerErrorCode } from "./TalerErrorCode";
export * from "./operations/errors";
// Utils for using the wallet under node
export { NodeHttpLib } from "./headless/NodeHttpLib";
export { export {
getDefaultNodeWallet, getDefaultNodeWallet,
DefaultNodeWalletArgs, DefaultNodeWalletArgs,
} from "./headless/helpers"; } from "./headless/helpers";
export { Amounts, AmountJson } from "./util/amounts";
export { Logger } from "./util/logging";
export * from "./crypto/talerCrypto";
export {
OperationFailedAndReportedError,
OperationFailedError,
makeErrorDetails,
} from "./operations/errors";
export * from "./types/walletTypes";
export * from "./types/talerTypes";
export * from "./util/taleruri";
export * from "./util/time";
export * from "./util/codec";
export { NodeHttpLib } from "./headless/NodeHttpLib";
export * from "./util/payto";
export * from "./util/testvectors";
export * from "./operations/versions"; export * from "./operations/versions";
export type { CryptoWorker } from "./crypto/workers/cryptoWorker";
export { CryptoWorkerFactory, CryptoApi } from "./crypto/workers/cryptoApi";
export * from "./util/http";
export { TalerErrorCode } from "./TalerErrorCode";
export * from "./util/query";
export { CryptoImplementation } from "./crypto/workers/cryptoImplementation";
export * from "./db"; export * from "./db";
export * from "./util/promiseUtils"; // Internationalization
export * from "./i18n"; export * from "./i18n";
// Crypto and crypto workers
export * from "./crypto/workers/nodeThreadWorker"; export * from "./crypto/workers/nodeThreadWorker";
export { CryptoImplementation } from "./crypto/workers/cryptoImplementation";
export type { CryptoWorker } from "./crypto/workers/cryptoWorker";
export { CryptoWorkerFactory, CryptoApi } from "./crypto/workers/cryptoApi";
export * from "./crypto/talerCrypto";
export * from "./types/notifications"; // Util functionality
export { Amounts, AmountJson } from "./util/amounts";
export { Logger } from "./util/logging";
export { Configuration } from "./util/talerconfig"; export { Configuration } from "./util/talerconfig";
export { URL } from "./util/url";
export * from "./util/codec";
export * from "./util/promiseUtils";
export * from "./util/query";
export * from "./util/http";
export * from "./util/payto";
export * from "./util/testvectors";
export * from "./util/taleruri";
export * from "./util/time";
export { URL } from "./util/url"; // Types
export * from "./types/talerTypes";
export * from "./types/walletTypes";
export * from "./types/notifications";
export * from "./types/transactions"

View File

@ -175,7 +175,7 @@ async function updateExchangeWithKeys(
async (tx) => { async (tx) => {
const r = await tx.get(Stores.exchanges, baseUrl); const r = await tx.get(Stores.exchanges, baseUrl);
if (!r) { if (!r) {
console.warn(`exchange ${baseUrl} no longer present`); logger.warn(`exchange ${baseUrl} no longer present`);
return; return;
} }
if (r.details) { if (r.details) {
@ -222,10 +222,10 @@ async function updateExchangeWithKeys(
if (oldDenom.isRevoked) { if (oldDenom.isRevoked) {
// We already marked the denomination as revoked, // We already marked the denomination as revoked,
// this implies we revoked all coins // this implies we revoked all coins
console.log("denom already revoked"); logger.trace("denom already revoked");
continue; continue;
} }
console.log("revoking denom", recoupInfo.h_denom_pub); logger.trace("revoking denom", recoupInfo.h_denom_pub);
oldDenom.isRevoked = true; oldDenom.isRevoked = true;
await tx.put(Stores.denominations, oldDenom); await tx.put(Stores.denominations, oldDenom);
const affectedCoins = await tx const affectedCoins = await tx
@ -236,7 +236,7 @@ async function updateExchangeWithKeys(
} }
} }
if (newlyRevokedCoinPubs.length != 0) { if (newlyRevokedCoinPubs.length != 0) {
console.log("recouping coins", newlyRevokedCoinPubs); logger.trace("recouping coins", newlyRevokedCoinPubs);
await createRecoupGroup(ws, tx, newlyRevokedCoinPubs); await createRecoupGroup(ws, tx, newlyRevokedCoinPubs);
} }
}, },
@ -246,7 +246,7 @@ async function updateExchangeWithKeys(
// Asynchronously start recoup. This doesn't need to finish // Asynchronously start recoup. This doesn't need to finish
// for the exchange update to be considered finished. // for the exchange update to be considered finished.
processRecoupGroup(ws, recoupGroupId).catch((e) => { processRecoupGroup(ws, recoupGroupId).catch((e) => {
console.log("error while recouping coins:", e); logger.error("error while recouping coins:", e);
}); });
} }

View File

@ -353,7 +353,7 @@ async function getCoinsForPayment(
throw Error("db inconsistent"); throw Error("db inconsistent");
} }
if (denom.value.currency !== currency) { if (denom.value.currency !== currency) {
console.warn( logger.warn(
`same pubkey for different currencies at exchange ${exchange.baseUrl}`, `same pubkey for different currencies at exchange ${exchange.baseUrl}`,
); );
continue; continue;
@ -539,7 +539,7 @@ async function incrementPurchasePayRetry(
proposalId: string, proposalId: string,
err: OperationErrorDetails | undefined, err: OperationErrorDetails | undefined,
): Promise<void> { ): Promise<void> {
console.log("incrementing purchase pay retry with error", err); logger.warn("incrementing purchase pay retry with error", err);
await ws.db.runWithWriteTransaction([Stores.purchases], async (tx) => { await ws.db.runWithWriteTransaction([Stores.purchases], async (tx) => {
const pr = await tx.get(Stores.purchases, proposalId); const pr = await tx.get(Stores.purchases, proposalId);
if (!pr) { if (!pr) {
@ -693,7 +693,7 @@ async function processDownloadProposalImpl(
fulfillmentUrl, fulfillmentUrl,
); );
if (differentPurchase) { if (differentPurchase) {
console.log("repurchase detected"); logger.warn("repurchase detected");
p.proposalStatus = ProposalStatus.REPURCHASE; p.proposalStatus = ProposalStatus.REPURCHASE;
p.repurchaseProposalId = differentPurchase.proposalId; p.repurchaseProposalId = differentPurchase.proposalId;
await tx.put(Stores.proposals, p); await tx.put(Stores.proposals, p);
@ -814,7 +814,7 @@ export async function submitPay(
merchantPub, merchantPub,
); );
if (!valid) { if (!valid) {
console.error("merchant payment signature invalid"); logger.error("merchant payment signature invalid");
// FIXME: properly display error // FIXME: properly display error
throw Error("merchant payment signature invalid"); throw Error("merchant payment signature invalid");
} }
@ -826,7 +826,7 @@ export async function submitPay(
if (isFirst) { if (isFirst) {
const ar = purchase.contractData.autoRefund; const ar = purchase.contractData.autoRefund;
if (ar) { if (ar) {
console.log("auto_refund present"); logger.info("auto_refund present");
purchase.refundStatusRequested = true; purchase.refundStatusRequested = true;
purchase.refundStatusRetryInfo = initRetryInfo(); purchase.refundStatusRetryInfo = initRetryInfo();
purchase.lastRefundStatusError = undefined; purchase.lastRefundStatusError = undefined;
@ -899,7 +899,7 @@ export async function preparePayForUri(
if (!existingProposalId) { if (!existingProposalId) {
throw Error("invalid proposal state"); throw Error("invalid proposal state");
} }
console.log("using existing purchase for same product"); logger.trace("using existing purchase for same product");
proposal = await ws.db.get(Stores.proposals, existingProposalId); proposal = await ws.db.get(Stores.proposals, existingProposalId);
if (!proposal) { if (!proposal) {
throw Error("existing proposal is in wrong state"); throw Error("existing proposal is in wrong state");
@ -907,7 +907,7 @@ export async function preparePayForUri(
} }
const d = proposal.download; const d = proposal.download;
if (!d) { if (!d) {
console.error("bad proposal", proposal); logger.error("bad proposal", proposal);
throw Error("proposal is in invalid state"); throw Error("proposal is in invalid state");
} }
const contractData = d.contractData; const contractData = d.contractData;

View File

@ -51,6 +51,9 @@ import { getTimestampNow } from "../util/time";
import { guardOperationException } from "./errors"; import { guardOperationException } from "./errors";
import { readSuccessResponseJsonOrThrow } from "../util/http"; import { readSuccessResponseJsonOrThrow } from "../util/http";
import { URL } from "../util/url"; import { URL } from "../util/url";
import { Logger } from "../util/logging";
const logger = new Logger("operations/recoup.ts");
async function incrementRecoupRetry( async function incrementRecoupRetry(
ws: InternalWalletState, ws: InternalWalletState,
@ -207,7 +210,7 @@ async function recoupWithdrawCoin(
}); });
forceQueryReserve(ws, reserve.reservePub).catch((e) => { forceQueryReserve(ws, reserve.reservePub).catch((e) => {
console.log("re-querying reserve after recoup failed:", e); logger.error("re-querying reserve after recoup failed:", e);
}); });
} }
@ -224,7 +227,7 @@ async function recoupRefreshCoin(
const recoupRequest = await ws.cryptoApi.createRecoupRequest(coin); const recoupRequest = await ws.cryptoApi.createRecoupRequest(coin);
const reqUrl = new URL(`/coins/${coin.coinPub}/recoup`, coin.exchangeBaseUrl); const reqUrl = new URL(`/coins/${coin.coinPub}/recoup`, coin.exchangeBaseUrl);
console.log("making recoup request"); logger.trace("making recoup request");
const resp = await ws.http.postJson(reqUrl.href, recoupRequest); const resp = await ws.http.postJson(reqUrl.href, recoupRequest);
const recoupConfirmation = await readSuccessResponseJsonOrThrow( const recoupConfirmation = await readSuccessResponseJsonOrThrow(
@ -270,7 +273,7 @@ async function recoupRefreshCoin(
oldCoin.currentAmount, oldCoin.currentAmount,
recoupGroup.oldAmountPerCoin[coinIdx], recoupGroup.oldAmountPerCoin[coinIdx],
).amount; ).amount;
console.log( logger.trace(
"recoup: setting old coin amount to", "recoup: setting old coin amount to",
Amounts.stringify(oldCoin.currentAmount), Amounts.stringify(oldCoin.currentAmount),
); );
@ -317,14 +320,12 @@ async function processRecoupGroupImpl(
if (forceNow) { if (forceNow) {
await resetRecoupGroupRetry(ws, recoupGroupId); await resetRecoupGroupRetry(ws, recoupGroupId);
} }
console.log("in processRecoupGroupImpl");
const recoupGroup = await ws.db.get(Stores.recoupGroups, recoupGroupId); const recoupGroup = await ws.db.get(Stores.recoupGroups, recoupGroupId);
if (!recoupGroup) { if (!recoupGroup) {
return; return;
} }
console.log(recoupGroup);
if (recoupGroup.timestampFinished) { if (recoupGroup.timestampFinished) {
console.log("recoup group finished"); logger.trace("recoup group finished");
return; return;
} }
const ps = recoupGroup.coinPubs.map((x, i) => const ps = recoupGroup.coinPubs.map((x, i) =>

View File

@ -188,7 +188,7 @@ async function refreshCreateSession(
} }
const r = Amounts.sub(c.currentAmount, refreshSession.amountRefreshInput); const r = Amounts.sub(c.currentAmount, refreshSession.amountRefreshInput);
if (r.saturated) { if (r.saturated) {
console.log("can't refresh coin, no amount left"); logger.warn("can't refresh coin, no amount left");
return; return;
} }
c.currentAmount = r.amount; c.currentAmount = r.amount;
@ -387,7 +387,7 @@ async function refreshReveal(
async (tx) => { async (tx) => {
const rg = await tx.get(Stores.refreshGroups, refreshGroupId); const rg = await tx.get(Stores.refreshGroups, refreshGroupId);
if (!rg) { if (!rg) {
console.log("no refresh session found"); logger.warn("no refresh session found");
return; return;
} }
const rs = rg.refreshSessionPerCoin[coinIndex]; const rs = rg.refreshSessionPerCoin[coinIndex];
@ -395,7 +395,7 @@ async function refreshReveal(
return; return;
} }
if (rs.finishedTimestamp) { if (rs.finishedTimestamp) {
console.log("refresh session already finished"); logger.warn("refresh session already finished");
return; return;
} }
rs.finishedTimestamp = getTimestampNow(); rs.finishedTimestamp = getTimestampNow();
@ -417,7 +417,7 @@ async function refreshReveal(
await tx.put(Stores.refreshGroups, rg); await tx.put(Stores.refreshGroups, rg);
}, },
); );
console.log("refresh finished (end of reveal)"); logger.trace("refresh finished (end of reveal)");
ws.notify({ ws.notify({
type: NotificationType.RefreshRevealed, type: NotificationType.RefreshRevealed,
}); });

View File

@ -50,7 +50,7 @@ import {
AmountString, AmountString,
} from "../types/talerTypes"; } from "../types/talerTypes";
import { guardOperationException } from "./errors"; import { guardOperationException } from "./errors";
import { getTimestampNow } from "../util/time"; import { getTimestampNow, Timestamp } from "../util/time";
import { Logger } from "../util/logging"; import { Logger } from "../util/logging";
import { readSuccessResponseJsonOrThrow } from "../util/http"; import { readSuccessResponseJsonOrThrow } from "../util/http";
import { TransactionHandle } from "../util/query"; import { TransactionHandle } from "../util/query";
@ -142,6 +142,7 @@ async function applySuccessfulRefund(
p.refunds[refundKey] = { p.refunds[refundKey] = {
type: RefundState.Applied, type: RefundState.Applied,
obtainedTime: getTimestampNow(),
executionTime: r.execution_time, executionTime: r.execution_time,
refundAmount: Amounts.parseOrThrow(r.refund_amount), refundAmount: Amounts.parseOrThrow(r.refund_amount),
refundFee: denom.feeRefund, refundFee: denom.feeRefund,
@ -191,6 +192,7 @@ async function storePendingRefund(
p.refunds[refundKey] = { p.refunds[refundKey] = {
type: RefundState.Pending, type: RefundState.Pending,
obtainedTime: getTimestampNow(),
executionTime: r.execution_time, executionTime: r.execution_time,
refundAmount: Amounts.parseOrThrow(r.refund_amount), refundAmount: Amounts.parseOrThrow(r.refund_amount),
refundFee: denom.feeRefund, refundFee: denom.feeRefund,

View File

@ -178,7 +178,7 @@ export async function createReserve(
const exchangeInfo = await updateExchangeFromUrl(ws, req.exchange); const exchangeInfo = await updateExchangeFromUrl(ws, req.exchange);
const exchangeDetails = exchangeInfo.details; const exchangeDetails = exchangeInfo.details;
if (!exchangeDetails) { if (!exchangeDetails) {
console.log(exchangeDetails); logger.trace(exchangeDetails);
throw Error("exchange not updated"); throw Error("exchange not updated");
} }
const { isAudited, isTrusted } = await getExchangeTrust(ws, exchangeInfo); const { isAudited, isTrusted } = await getExchangeTrust(ws, exchangeInfo);
@ -576,7 +576,7 @@ async function processReserveImpl(
): Promise<void> { ): Promise<void> {
const reserve = await ws.db.get(Stores.reserves, reservePub); const reserve = await ws.db.get(Stores.reserves, reservePub);
if (!reserve) { if (!reserve) {
console.log("not processing reserve: reserve does not exist"); logger.trace("not processing reserve: reserve does not exist");
return; return;
} }
if (!forceNow) { if (!forceNow) {

View File

@ -269,11 +269,11 @@ async function makePayment(
"taler://fulfillment-success/thx", "taler://fulfillment-success/thx",
); );
console.log("created order with orderId", orderResp.orderId); logger.trace("created order with orderId", orderResp.orderId);
let paymentStatus = await checkPayment(http, merchant, orderResp.orderId); let paymentStatus = await checkPayment(http, merchant, orderResp.orderId);
console.log("payment status", paymentStatus); logger.trace("payment status", paymentStatus);
const talerPayUri = paymentStatus.taler_pay_uri; const talerPayUri = paymentStatus.taler_pay_uri;
if (!talerPayUri) { if (!talerPayUri) {
@ -282,7 +282,7 @@ async function makePayment(
const preparePayResult = await wallet.preparePayForUri(talerPayUri); const preparePayResult = await wallet.preparePayForUri(talerPayUri);
console.log("prepare pay result", preparePayResult); logger.trace("prepare pay result", preparePayResult);
if (preparePayResult.status != "payment-possible") { if (preparePayResult.status != "payment-possible") {
throw Error("payment not possible"); throw Error("payment not possible");
@ -293,11 +293,11 @@ async function makePayment(
undefined, undefined,
); );
console.log("confirmPayResult", confirmPayResult); logger.trace("confirmPayResult", confirmPayResult);
paymentStatus = await checkPayment(http, merchant, orderResp.orderId); paymentStatus = await checkPayment(http, merchant, orderResp.orderId);
console.log("payment status after wallet payment:", paymentStatus); logger.trace("payment status after wallet payment:", paymentStatus);
if (paymentStatus.order_status !== "paid") { if (paymentStatus.order_status !== "paid") {
throw Error("payment did not succeed"); throw Error("payment did not succeed");
@ -318,26 +318,18 @@ export async function runIntegrationTest(
const parsedSpendAmount = Amounts.parseOrThrow(args.amountToSpend); const parsedSpendAmount = Amounts.parseOrThrow(args.amountToSpend);
const currency = parsedSpendAmount.currency; 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"); logger.info("withdrawing test balance");
await wallet.withdrawTestBalance( await wallet.withdrawTestBalance({
args.amountToWithdraw, amount: args.amountToWithdraw,
args.bankBaseUrl, bankBaseUrl: args.bankBaseUrl,
args.exchangeBaseUrl, exchangeBaseUrl: args.exchangeBaseUrl,
); });
await wallet.runUntilDone();
logger.info("done withdrawing test balance"); logger.info("done withdrawing test balance");
const balance = await myWallet.getBalances(); const balance = await wallet.getBalances();
console.log(JSON.stringify(balance, null, 2)); logger.trace(JSON.stringify(balance, null, 2));
const myMerchant: MerchantBackendInfo = { const myMerchant: MerchantBackendInfo = {
baseUrl: args.merchantBaseUrl, baseUrl: args.merchantBaseUrl,
@ -353,26 +345,26 @@ export async function runIntegrationTest(
); );
// Wait until the refresh is done // Wait until the refresh is done
await myWallet.runUntilDone(); await wallet.runUntilDone();
console.log("withdrawing test balance for refund"); logger.trace("withdrawing test balance for refund");
const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`); const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`);
const spendAmountTwo = Amounts.parseOrThrow(`${currency}:7`); const spendAmountTwo = Amounts.parseOrThrow(`${currency}:7`);
const refundAmount = Amounts.parseOrThrow(`${currency}:6`); const refundAmount = Amounts.parseOrThrow(`${currency}:6`);
const spendAmountThree = Amounts.parseOrThrow(`${currency}:3`); const spendAmountThree = Amounts.parseOrThrow(`${currency}:3`);
await myWallet.withdrawTestBalance( await wallet.withdrawTestBalance({
Amounts.stringify(withdrawAmountTwo), amount: Amounts.stringify(withdrawAmountTwo),
args.bankBaseUrl, bankBaseUrl: args.bankBaseUrl,
args.exchangeBaseUrl, exchangeBaseUrl: args.exchangeBaseUrl,
); });
// Wait until the withdraw is done // Wait until the withdraw is done
await myWallet.runUntilDone(); await wallet.runUntilDone();
const { orderId: refundOrderId } = await makePayment( const { orderId: refundOrderId } = await makePayment(
http, http,
myWallet, wallet,
myMerchant, myMerchant,
Amounts.stringify(spendAmountTwo), Amounts.stringify(spendAmountTwo),
"order that will be refunded", "order that will be refunded",
@ -386,22 +378,30 @@ export async function runIntegrationTest(
Amounts.stringify(refundAmount), Amounts.stringify(refundAmount),
); );
console.log("refund URI", refundUri); logger.trace("refund URI", refundUri);
await myWallet.applyRefund(refundUri); await wallet.applyRefund(refundUri);
logger.trace("integration test: applied refund");
// Wait until the refund is done // Wait until the refund is done
await myWallet.runUntilDone(); await wallet.runUntilDone();
logger.trace("integration test: making payment after refund");
await makePayment( await makePayment(
http, http,
myWallet, wallet,
myMerchant, myMerchant,
Amounts.stringify(spendAmountThree), Amounts.stringify(spendAmountThree),
"payment after refund", "payment after refund",
); );
await myWallet.runUntilDone(); logger.trace("integration test: make payment done");
await wallet.runUntilDone();
logger.trace("integration test: all done!");
} }
export async function testPay( export async function testPay(
@ -409,8 +409,8 @@ export async function testPay(
wallet: Wallet, wallet: Wallet,
args: TestPayArgs, args: TestPayArgs,
) { ) {
console.log("creating order"); logger.trace("creating order");
const merchant = { apikey: args.apikey, baseUrl: args.merchant }; const merchant = { apikey: args.merchantApiKey, baseUrl: args.merchantBaseUrl };
const orderResp = await createOrder( const orderResp = await createOrder(
http, http,
merchant, merchant,
@ -418,7 +418,7 @@ export async function testPay(
args.summary, args.summary,
"taler://fulfillment-success/thank+you", "taler://fulfillment-success/thank+you",
); );
console.log("created new order with order ID", orderResp.orderId); logger.trace("created new order with order ID", orderResp.orderId);
const checkPayResp = await checkPayment(http, merchant, orderResp.orderId); const checkPayResp = await checkPayment(http, merchant, orderResp.orderId);
const talerPayUri = checkPayResp.taler_pay_uri; const talerPayUri = checkPayResp.taler_pay_uri;
if (!talerPayUri) { if (!talerPayUri) {
@ -426,7 +426,7 @@ export async function testPay(
process.exit(1); process.exit(1);
return; return;
} }
console.log("taler pay URI:", talerPayUri); logger.trace("taler pay URI:", talerPayUri);
const result = await wallet.preparePayForUri(talerPayUri); const result = await wallet.preparePayForUri(talerPayUri);
if (result.status !== PreparePayResultType.PaymentPossible) { if (result.status !== PreparePayResultType.PaymentPossible) {
throw Error(`unexpected prepare pay status: ${result.status}`); throw Error(`unexpected prepare pay status: ${result.status}`);

View File

@ -45,6 +45,9 @@ import { NotificationType } from "../types/notifications";
import { getTimestampNow } from "../util/time"; import { getTimestampNow } from "../util/time";
import { readSuccessResponseJsonOrThrow } from "../util/http"; import { readSuccessResponseJsonOrThrow } from "../util/http";
import { URL } from "../util/url"; import { URL } from "../util/url";
import { Logger } from "../util/logging";
const logger = new Logger("operations/tip.ts");
export async function getTipStatus( export async function getTipStatus(
ws: InternalWalletState, ws: InternalWalletState,
@ -57,13 +60,13 @@ export async function getTipStatus(
const tipStatusUrl = new URL("tip-pickup", res.merchantBaseUrl); const tipStatusUrl = new URL("tip-pickup", res.merchantBaseUrl);
tipStatusUrl.searchParams.set("tip_id", res.merchantTipId); tipStatusUrl.searchParams.set("tip_id", res.merchantTipId);
console.log("checking tip status from", tipStatusUrl.href); logger.trace("checking tip status from", tipStatusUrl.href);
const merchantResp = await ws.http.get(tipStatusUrl.href); const merchantResp = await ws.http.get(tipStatusUrl.href);
const tipPickupStatus = await readSuccessResponseJsonOrThrow( const tipPickupStatus = await readSuccessResponseJsonOrThrow(
merchantResp, merchantResp,
codecForTipPickupGetResponse(), codecForTipPickupGetResponse(),
); );
console.log("status", tipPickupStatus); logger.trace(`status ${tipPickupStatus}`);
const amount = Amounts.parseOrThrow(tipPickupStatus.amount); const amount = Amounts.parseOrThrow(tipPickupStatus.amount);
@ -191,7 +194,7 @@ async function processTipImpl(
} }
if (tipRecord.pickedUp) { if (tipRecord.pickedUp) {
console.log("tip already picked up"); logger.warn("tip already picked up");
return; return;
} }
@ -230,7 +233,7 @@ async function processTipImpl(
throw Error("invariant violated"); throw Error("invariant violated");
} }
console.log("got planchets for tip!"); logger.trace("got planchets for tip!");
// Planchets in the form that the merchant expects // Planchets in the form that the merchant expects
const planchetsDetail: TipPlanchetDetail[] = tipRecord.planchets.map((p) => ({ const planchetsDetail: TipPlanchetDetail[] = tipRecord.planchets.map((p) => ({
@ -248,9 +251,9 @@ async function processTipImpl(
if (merchantResp.status !== 200) { if (merchantResp.status !== 200) {
throw Error(`unexpected status ${merchantResp.status} for tip-pickup`); throw Error(`unexpected status ${merchantResp.status} for tip-pickup`);
} }
console.log("got merchant resp:", merchantResp); logger.trace("got merchant resp:", merchantResp);
} catch (e) { } catch (e) {
console.log("tipping failed", e); logger.warn("tipping failed", e);
throw e; throw e;
} }
@ -331,7 +334,7 @@ export async function acceptTip(
): Promise<void> { ): Promise<void> {
const tipRecord = await ws.db.get(Stores.tips, tipId); const tipRecord = await ws.db.get(Stores.tips, tipId);
if (!tipRecord) { if (!tipRecord) {
console.log("tip not found"); logger.error("tip not found");
return; return;
} }

View File

@ -25,7 +25,7 @@ import {
RefundState, RefundState,
} from "../types/dbTypes"; } from "../types/dbTypes";
import { Amounts, AmountJson } from "../util/amounts"; import { Amounts, AmountJson } from "../util/amounts";
import { timestampCmp } from "../util/time"; import { timestampCmp, Timestamp } from "../util/time";
import { import {
TransactionsRequest, TransactionsRequest,
TransactionsResponse, TransactionsResponse,
@ -297,12 +297,13 @@ export async function getTransactions(
if (!r0) { if (!r0) {
throw Error("invariant violated"); throw Error("invariant violated");
} }
let ts: Timestamp;
transactions.push({ transactions.push({
type: TransactionType.Refund, type: TransactionType.Refund,
info, info,
refundedTransactionId: paymentTransactionId, refundedTransactionId: paymentTransactionId,
transactionId: refundTransactionId, transactionId: refundTransactionId,
timestamp: r0.executionTime, timestamp: r0.obtainedTime,
amountEffective: Amounts.stringify(amountEffective), amountEffective: Amounts.stringify(amountEffective),
amountRaw: Amounts.stringify(amountRaw), amountRaw: Amounts.stringify(amountRaw),
pending: false, pending: false,

View File

@ -1164,7 +1164,14 @@ export type WalletRefundItem =
| WalletRefundAppliedItem; | WalletRefundAppliedItem;
export interface WalletRefundItemCommon { export interface WalletRefundItemCommon {
// Execution time as claimed by the merchant
executionTime: Timestamp; executionTime: Timestamp;
/**
* Time when the wallet became aware of the refund.
*/
obtainedTime: Timestamp;
refundAmount: AmountJson; refundAmount: AmountJson;
refundFee: AmountJson; refundFee: AmountJson;

View File

@ -31,6 +31,8 @@ import {
buildCodecForObject, buildCodecForObject,
codecOptional, codecOptional,
codecForString, codecForString,
codecForList,
codecForAny,
} from "../util/codec"; } from "../util/codec";
export interface TransactionsRequest { export interface TransactionsRequest {
@ -309,3 +311,9 @@ export const codecForTransactionsRequest = (): Codec<TransactionsRequest> =>
.property("currency", codecOptional(codecForString())) .property("currency", codecOptional(codecForString()))
.property("search", codecOptional(codecForString())) .property("search", codecOptional(codecForString()))
.build("TransactionsRequest"); .build("TransactionsRequest");
// FIXME: do full validation here!
export const codecForTransactionsResponse = (): Codec<TransactionsResponse> =>
buildCodecForObject<TransactionsResponse>()
.property("transactions", codecForList(codecForAny()))
.build("TransactionsResponse");

View File

@ -653,16 +653,16 @@ export interface GetExchangeTosResult {
} }
export interface TestPayArgs { export interface TestPayArgs {
merchant: string; merchantBaseUrl: string;
apikey: string; merchantApiKey: string;
amount: string; amount: string;
summary: string; summary: string;
} }
export const codecForTestPayArgs = (): Codec<TestPayArgs> => export const codecForTestPayArgs = (): Codec<TestPayArgs> =>
buildCodecForObject<TestPayArgs>() buildCodecForObject<TestPayArgs>()
.property("merchant", codecForString()) .property("merchantBaseUrl", codecForString())
.property("apikey", codecForString()) .property("merchantApiKey", codecForString())
.property("amount", codecForString()) .property("amount", codecForString())
.property("summary", codecForString()) .property("summary", codecForString())
.build("TestPayArgs"); .build("TestPayArgs");
@ -829,3 +829,22 @@ export interface CoreApiResponseError {
id: string; id: string;
error: OperationErrorDetails; error: OperationErrorDetails;
} }
export interface WithdrawTestBalanceRequest {
amount: string;
bankBaseUrl: string;
exchangeBaseUrl: string;
}
export const withdrawTestBalanceDefaults = {
amount: "TESTKUDOS:10",
bankBaseUrl: "https://bank.test.taler.net/",
exchangeBaseUrl: "https://exchange.test.taler.net/",
};
export const codecForWithdrawTestBalance = (): Codec<WithdrawTestBalanceRequest> =>
buildCodecForObject<WithdrawTestBalanceRequest>()
.property("amount", codecForString())
.property("bankBaseUrl", codecForString())
.property("exchangeBaseUrl", codecForString())
.build("WithdrawTestBalanceRequest");

View File

@ -23,6 +23,9 @@
*/ */
import { getTimestampNow, timestampDifference } from "../util/time"; import { getTimestampNow, timestampDifference } from "../util/time";
import { URL } from "./url"; import { URL } from "./url";
import { Logger } from "./logging";
const logger = new Logger("RequestThrottler.ts");
/** /**
* Maximum request per second, per origin. * Maximum request per second, per origin.
@ -77,15 +80,15 @@ class OriginState {
applyThrottle(): boolean { applyThrottle(): boolean {
this.refill(); this.refill();
if (this.tokensSecond < 1) { if (this.tokensSecond < 1) {
console.log("request throttled (per second limit exceeded)"); logger.warn("request throttled (per second limit exceeded)");
return true; return true;
} }
if (this.tokensMinute < 1) { if (this.tokensMinute < 1) {
console.log("request throttled (per minute limit exceeded)"); logger.warn("request throttled (per minute limit exceeded)");
return true; return true;
} }
if (this.tokensHour < 1) { if (this.tokensHour < 1) {
console.log("request throttled (per hour limit exceeded)"); logger.warn("request throttled (per hour limit exceeded)");
return true; return true;
} }
this.tokensSecond--; this.tokensSecond--;

View File

@ -35,6 +35,10 @@ import {
Event, Event,
IDBCursor, IDBCursor,
} from "idb-bridge"; } from "idb-bridge";
import { Logger } from "./logging";
const logger = new Logger("query.ts");
/** /**
* Exception that should be thrown by client code to abort a transaction. * Exception that should be thrown by client code to abort a transaction.
@ -72,9 +76,9 @@ function requestToPromise(req: IDBRequest): Promise<any> {
resolve(req.result); resolve(req.result);
}; };
req.onerror = () => { req.onerror = () => {
console.log("error in DB request", req.error); console.error("error in DB request", req.error);
reject(req.error); reject(req.error);
console.log("Request failed:", stack); console.error("Request failed:", stack);
}; };
}); });
} }
@ -341,14 +345,14 @@ function runWithTransaction<T>(
resolve(funResult); resolve(funResult);
}; };
tx.onerror = () => { tx.onerror = () => {
console.error("error in transaction"); logger.error("error in transaction");
console.error(stack); logger.error(`${stack}`);
}; };
tx.onabort = () => { tx.onabort = () => {
if (tx.error) { if (tx.error) {
console.error("Transaction aborted with error:", tx.error); logger.error("Transaction aborted with error:", tx.error);
} else { } else {
console.log("Trasaction aborted (no error)"); logger.error("Trasaction aborted (no error)");
} }
reject(TransactionAbort); reject(TransactionAbort);
}; };
@ -361,7 +365,7 @@ function runWithTransaction<T>(
}) })
.catch((e) => { .catch((e) => {
if (e == TransactionAbort) { if (e == TransactionAbort) {
console.info("aborting transaction"); logger.trace("aborting transaction");
} else { } else {
console.error("Transaction failed:", e); console.error("Transaction failed:", e);
console.error(stack); console.error(stack);
@ -427,12 +431,12 @@ export function openDatabase(
return new Promise<IDBDatabase>((resolve, reject) => { return new Promise<IDBDatabase>((resolve, reject) => {
const req = idbFactory.open(databaseName, databaseVersion); const req = idbFactory.open(databaseName, databaseVersion);
req.onerror = (e) => { req.onerror = (e) => {
console.log("taler database error", e); logger.error("taler database error", e);
reject(new Error("database error")); reject(new Error("database error"));
}; };
req.onsuccess = (e) => { req.onsuccess = (e) => {
req.result.onversionchange = (evt: IDBVersionChangeEvent) => { req.result.onversionchange = (evt: IDBVersionChangeEvent) => {
console.log( logger.info(
`handling live db version change from ${evt.oldVersion} to ${evt.newVersion}`, `handling live db version change from ${evt.oldVersion} to ${evt.newVersion}`,
); );
req.result.close(); req.result.close();
@ -491,7 +495,7 @@ export class Database {
importDatabase(dump: any): Promise<void> { importDatabase(dump: any): Promise<void> {
const db = this.db; const db = this.db;
console.log("importing db", dump); logger.info("importing db", dump);
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite"); const tx = db.transaction(Array.from(db.objectStoreNames), "readwrite");
if (dump.stores) { if (dump.stores) {
@ -501,7 +505,7 @@ export class Database {
for (const key in dumpStore) { for (const key in dumpStore) {
objects.push(dumpStore[key]); objects.push(dumpStore[key]);
} }
console.log(`importing ${objects.length} records into ${storeName}`); logger.info(`importing ${objects.length} records into ${storeName}`);
const store = tx.objectStore(storeName); const store = tx.objectStore(storeName);
for (const obj of objects) { for (const obj of objects) {
store.put(obj); store.put(obj);

View File

@ -86,6 +86,10 @@ import {
CoreApiResponse, CoreApiResponse,
codecForPreparePayRequest, codecForPreparePayRequest,
codecForIntegrationTestArgs, codecForIntegrationTestArgs,
WithdrawTestBalanceRequest,
withdrawTestBalanceDefaults,
codecForWithdrawTestBalance,
codecForTestPayArgs,
} from "./types/walletTypes"; } from "./types/walletTypes";
import { Logger } from "./util/logging"; import { Logger } from "./util/logging";
@ -313,7 +317,7 @@ export class Wallet {
} }
}); });
this.runRetryLoop().catch((e) => { this.runRetryLoop().catch((e) => {
console.log("exception in wallet retry loop"); logger.error("exception in wallet retry loop");
reject(e); reject(e);
}); });
}); });
@ -377,7 +381,7 @@ export class Wallet {
numPending, numPending,
}); });
await Promise.race([timeout, this.latch.wait()]); await Promise.race([timeout, this.latch.wait()]);
console.log("timeout done"); logger.trace("timeout done");
} else { } else {
// FIXME: maybe be a bit smarter about executing these // FIXME: maybe be a bit smarter about executing these
// operations in parallel? // operations in parallel?
@ -899,11 +903,9 @@ export class Wallet {
} }
async withdrawTestBalance( async withdrawTestBalance(
amount = "TESTKUDOS:10", req: WithdrawTestBalanceRequest,
bankBaseUrl = "https://bank.test.taler.net/",
exchangeBaseUrl = "https://exchange.test.taler.net/",
): Promise<void> { ): Promise<void> {
await withdrawTestBalance(this.ws, amount, bankBaseUrl, exchangeBaseUrl); await withdrawTestBalance(this.ws, req.amount, req.bankBaseUrl, req.exchangeBaseUrl);
} }
async runIntegrationtest(args: IntegrationTestArgs): Promise<void> { async runIntegrationtest(args: IntegrationTestArgs): Promise<void> {
@ -924,7 +926,16 @@ export class Wallet {
): Promise<Record<string, any>> { ): Promise<Record<string, any>> {
switch (operation) { switch (operation) {
case "withdrawTestkudos": { case "withdrawTestkudos": {
await this.withdrawTestBalance(); await this.withdrawTestBalance({
amount: "TESTKUDOS:10",
bankBaseUrl: "https://bank.test.taler.net/",
exchangeBaseUrl: "https://exchange.test.taler.net/",
});
return {};
}
case "withdrawTestBalance": {
const req = codecForWithdrawTestBalance().decode(payload);
await this.withdrawTestBalance(req);
return {}; return {};
} }
case "runIntegrationtest": { case "runIntegrationtest": {
@ -933,8 +944,8 @@ export class Wallet {
return {} return {}
} }
case "testPay": { case "testPay": {
const req = codecForIntegrationTestArgs().decode(payload); const req = codecForTestPayArgs().decode(payload);
await this.runIntegrationtest(req); await this.testPay(req);
return {} return {}
} }
case "getTransactions": { case "getTransactions": {

View File

@ -22,7 +22,9 @@
* Imports. * Imports.
*/ */
import { CryptoImplementation } from "taler-wallet-core"; import { CryptoImplementation, Logger } from "taler-wallet-core";
const logger = new Logger("browserWorkerEntry.ts");
const worker: Worker = (self as any) as Worker; const worker: Worker = (self as any) as Worker;
@ -42,7 +44,7 @@ async function handleRequest(
const result = (impl as any)[operation](...args); const result = (impl as any)[operation](...args);
worker.postMessage({ result, id }); worker.postMessage({ result, id });
} catch (e) { } catch (e) {
console.log("error during operation", e); logger.error("error during operation", e);
return; return;
} }
} }
@ -64,10 +66,6 @@ worker.onmessage = (msg: MessageEvent) => {
return; return;
} }
if (CryptoImplementation.enableTracing) {
console.log("onmessage with", operation);
}
handleRequest(operation, id, args).catch((e) => { handleRequest(operation, id, args).catch((e) => {
console.error("error in browsere worker", e); console.error("error in browsere worker", e);
}); });