From 194eeea6aaf4ab401825aa07073b3e0a4f9d3c1b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 19 Feb 2024 20:07:37 +0100 Subject: restructure --- packages/taler-harness/src/bench2.ts | 10 +- packages/taler-harness/src/index.ts | 3 +- .../src/integrationtests/test-exchange-deposit.ts | 14 +- .../src/integrationtests/test-exchange-purse.ts | 12 +- .../src/integrationtests/test-wallet-dbless.ts | 10 +- packages/taler-util/src/index.ts | 1 + packages/taler-util/src/timer.ts | 213 +++++++++++++++++++++ packages/taler-util/src/wallet-types.ts | 106 ++++++++++ packages/taler-wallet-core/package.json | 3 + packages/taler-wallet-core/src/backup/index.ts | 127 +----------- .../src/crypto/workers/crypto-dispatcher.ts | 4 +- packages/taler-wallet-core/src/db.ts | 7 +- packages/taler-wallet-core/src/dbless.ts | 4 +- packages/taler-wallet-core/src/host-impl.node.ts | 3 +- packages/taler-wallet-core/src/host-impl.qtart.ts | 3 +- packages/taler-wallet-core/src/index.ts | 12 +- .../taler-wallet-core/src/internal-wallet-state.ts | 4 +- packages/taler-wallet-core/src/util/timer.ts | 213 --------------------- packages/taler-wallet-core/src/wallet.ts | 80 ++++---- packages/taler-wallet-embedded/src/wallet-qjs.ts | 2 +- .../src/hooks/useProviderStatus.ts | 3 +- .../src/wallet/AddBackupProvider/index.ts | 8 +- .../src/wallet/AddBackupProvider/state.ts | 7 +- .../src/wallet/Backup.stories.tsx | 15 +- .../src/wallet/BackupPage.tsx | 24 ++- .../src/wallet/ExchangeSelection/state.ts | 6 +- .../src/wallet/ProviderDetail.stories.tsx | 3 +- .../src/wallet/ProviderDetailPage.tsx | 12 +- .../taler-wallet-webextension/src/wxBackend.ts | 2 +- 29 files changed, 462 insertions(+), 449 deletions(-) create mode 100644 packages/taler-util/src/timer.ts delete mode 100644 packages/taler-wallet-core/src/util/timer.ts diff --git a/packages/taler-harness/src/bench2.ts b/packages/taler-harness/src/bench2.ts index 35c12b2d4..c85bd6a5d 100644 --- a/packages/taler-harness/src/bench2.ts +++ b/packages/taler-harness/src/bench2.ts @@ -26,18 +26,20 @@ import { Logger, } from "@gnu-taler/taler-util"; import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; +import { + CryptoDispatcher, + SynchronousCryptoWorkerFactoryPlain, + Wallet, +} from "@gnu-taler/taler-wallet-core"; import { checkReserve, createTestingReserve, - CryptoDispatcher, depositCoin, downloadExchangeInfo, findDenomOrThrow, refreshCoin, - SynchronousCryptoWorkerFactoryPlain, - Wallet, withdrawCoin, -} from "@gnu-taler/taler-wallet-core"; +} from "@gnu-taler/taler-wallet-core/dbless"; /** * Entry point for the benchmark. diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts index 0fdf3a15b..9ca297cb2 100644 --- a/packages/taler-harness/src/index.ts +++ b/packages/taler-harness/src/index.ts @@ -46,8 +46,6 @@ import { CryptoDispatcher, SynchronousCryptoWorkerFactoryPlain, WalletApiOperation, - downloadExchangeInfo, - topupReserveWithDemobank, } from "@gnu-taler/taler-wallet-core"; import { deepStrictEqual } from "assert"; import fs from "fs"; @@ -70,6 +68,7 @@ import { } from "./harness/helpers.js"; import { getTestInfo, runTests } from "./integrationtests/testrunner.js"; import { lintExchangeDeployment } from "./lint.js"; +import { downloadExchangeInfo, topupReserveWithDemobank } from "@gnu-taler/taler-wallet-core/dbless"; const logger = new Logger("taler-harness:index.ts"); diff --git a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts index 8e1726aba..ca8b9e375 100644 --- a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts +++ b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts @@ -26,20 +26,20 @@ import { } from "@gnu-taler/taler-util"; import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; import { - checkReserve, CryptoDispatcher, + SynchronousCryptoWorkerFactoryPlain, + Wallet, +} from "@gnu-taler/taler-wallet-core"; +import { + checkReserve, depositCoin, downloadExchangeInfo, findDenomOrThrow, - SynchronousCryptoWorkerFactoryPlain, topupReserveWithDemobank, - Wallet, withdrawCoin, -} from "@gnu-taler/taler-wallet-core"; +} from "@gnu-taler/taler-wallet-core/dbless"; import { GlobalTestState } from "../harness/harness.js"; -import { - createSimpleTestkudosEnvironmentV2, -} from "../harness/helpers.js"; +import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js"; /** * Run test for basic, bank-integrated withdrawal and payment. diff --git a/packages/taler-harness/src/integrationtests/test-exchange-purse.ts b/packages/taler-harness/src/integrationtests/test-exchange-purse.ts index c3815e1de..8ff740732 100644 --- a/packages/taler-harness/src/integrationtests/test-exchange-purse.ts +++ b/packages/taler-harness/src/integrationtests/test-exchange-purse.ts @@ -32,17 +32,19 @@ import { TalerPreciseTimestamp, } from "@gnu-taler/taler-util"; import { - checkReserve, CryptoDispatcher, - downloadExchangeInfo, EncryptContractRequest, - findDenomOrThrow, SpendCoinDetails, SynchronousCryptoWorkerFactoryPlain, - topupReserveWithDemobank, Wallet, - withdrawCoin, } from "@gnu-taler/taler-wallet-core"; +import { + checkReserve, + downloadExchangeInfo, + findDenomOrThrow, + topupReserveWithDemobank, + withdrawCoin, +} from "@gnu-taler/taler-wallet-core/dbless"; import { GlobalTestState, harnessHttpLib } from "../harness/harness.js"; import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js"; diff --git a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts index 32534f2c8..1c4c16e0f 100644 --- a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts +++ b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts @@ -25,17 +25,19 @@ import { TalerError, } from "@gnu-taler/taler-util"; import { - checkReserve, CryptoDispatcher, + SynchronousCryptoWorkerFactoryPlain, + Wallet, +} from "@gnu-taler/taler-wallet-core"; +import { + checkReserve, depositCoin, downloadExchangeInfo, findDenomOrThrow, refreshCoin, - SynchronousCryptoWorkerFactoryPlain, topupReserveWithDemobank, - Wallet, withdrawCoin, -} from "@gnu-taler/taler-wallet-core"; +} from "@gnu-taler/taler-wallet-core/dbless"; import { GlobalTestState, harnessHttpLib } from "../harness/harness.js"; import { createSimpleTestkudosEnvironmentV2 } from "../harness/helpers.js"; diff --git a/packages/taler-util/src/index.ts b/packages/taler-util/src/index.ts index edc9c4ff2..ec5b85d29 100644 --- a/packages/taler-util/src/index.ts +++ b/packages/taler-util/src/index.ts @@ -50,6 +50,7 @@ export * from "./taler-crypto.js"; export * from "./taler-types.js"; export * from "./taleruri.js"; export * from "./time.js"; +export * from "./timer.js"; export * from "./transaction-test-data.js"; export * from "./transactions-types.js"; export * from "./url.js"; diff --git a/packages/taler-util/src/timer.ts b/packages/taler-util/src/timer.ts new file mode 100644 index 000000000..8db024512 --- /dev/null +++ b/packages/taler-util/src/timer.ts @@ -0,0 +1,213 @@ +/* + This file is part of GNU Taler + (C) 2017-2019 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 + */ + +/** + * Cross-platform timers. + * + * NodeJS and the browser use slightly different timer API, + * this abstracts over these differences. + */ + +/** + * Imports. + */ +import { Logger, Duration } from "@gnu-taler/taler-util"; + +const logger = new Logger("timer.ts"); + +/** + * Cancelable timer. + */ +export interface TimerHandle { + clear(): void; + + /** + * Make sure the event loop exits when the timer is the + * only event left. Has no effect in the browser. + */ + unref(): void; +} + +class IntervalHandle { + constructor(public h: any) {} + + clear(): void { + clearInterval(this.h); + } + + /** + * Make sure the event loop exits when the timer is the + * only event left. Has no effect in the browser. + */ + unref(): void { + if (typeof this.h === "object" && "unref" in this.h) { + this.h.unref(); + } + } +} + +class TimeoutHandle { + constructor(public h: any) {} + + clear(): void { + clearTimeout(this.h); + } + + /** + * Make sure the event loop exits when the timer is the + * only event left. Has no effect in the browser. + */ + unref(): void { + if (typeof this.h === "object" && "unref" in this.h) { + this.h.unref(); + } + } +} + +/** + * Get a performance counter in nanoseconds. + */ +export const performanceNow: () => bigint = (() => { + // @ts-ignore + if (typeof process !== "undefined" && process.hrtime) { + return () => { + return process.hrtime.bigint(); + }; + } + + // @ts-ignore + if (typeof performance !== "undefined") { + // @ts-ignore + return () => BigInt(Math.floor(performance.now() * 1000)) * BigInt(1000); + } + + return () => BigInt(new Date().getTime()) * BigInt(1000) * BigInt(1000); +})(); + +const nullTimerHandle = { + clear() { + // do nothing + return; + }, + unref() { + // do nothing + return; + }, +}; + +/** + * Group of timers that can be destroyed at once. + */ +export interface TimerAPI { + after(delayMs: number, callback: () => void): TimerHandle; + every(delayMs: number, callback: () => void): TimerHandle; +} + +export class SetTimeoutTimerAPI implements TimerAPI { + /** + * Call a function every time the delay given in milliseconds passes. + */ + every(delayMs: number, callback: () => void): TimerHandle { + return new IntervalHandle(setInterval(callback, delayMs)); + } + + /** + * Call a function after the delay given in milliseconds passes. + */ + after(delayMs: number, callback: () => void): TimerHandle { + return new TimeoutHandle(setTimeout(callback, delayMs)); + } +} + +export const timer = new SetTimeoutTimerAPI(); + +/** + * Implementation of [[TimerGroup]] using setTimeout + */ +export class TimerGroup { + private stopped = false; + + private readonly timerMap: { [index: number]: TimerHandle } = {}; + + private idGen = 1; + + constructor(public readonly timerApi: TimerAPI) {} + + stopCurrentAndFutureTimers(): void { + this.stopped = true; + for (const x in this.timerMap) { + if (!this.timerMap.hasOwnProperty(x)) { + continue; + } + this.timerMap[x].clear(); + delete this.timerMap[x]; + } + } + + resolveAfter(delayMs: Duration): Promise { + return new Promise((resolve, reject) => { + if (delayMs.d_ms !== "forever") { + this.after(delayMs.d_ms, () => { + resolve(); + }); + } + }); + } + + after(delayMs: number, callback: () => void): TimerHandle { + if (this.stopped) { + logger.warn("dropping timer since timer group is stopped"); + return nullTimerHandle; + } + const h = this.timerApi.after(delayMs, callback); + const myId = this.idGen++; + this.timerMap[myId] = h; + + const tm = this.timerMap; + + return { + clear() { + h.clear(); + delete tm[myId]; + }, + unref() { + h.unref(); + }, + }; + } + + every(delayMs: number, callback: () => void): TimerHandle { + if (this.stopped) { + logger.warn("dropping timer since timer group is stopped"); + return nullTimerHandle; + } + const h = this.timerApi.every(delayMs, callback); + const myId = this.idGen++; + this.timerMap[myId] = h; + + const tm = this.timerMap; + + return { + clear() { + h.clear(); + delete tm[myId]; + }, + unref() { + h.unref(); + }, + }; + } +} diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 4e3e8ac30..5293fcd55 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -3074,3 +3074,109 @@ export interface RetryLoopOpts { */ stopWhenDone?: boolean; } + +/** + * Information about one provider. + * + * We don't store the account key here, + * as that's derived from the wallet root key. + */ +export interface ProviderInfo { + active: boolean; + syncProviderBaseUrl: string; + name: string; + terms?: BackupProviderTerms; + /** + * Last communication issue with the provider. + */ + lastError?: TalerErrorDetail; + lastSuccessfulBackupTimestamp?: TalerPreciseTimestamp; + lastAttemptedBackupTimestamp?: TalerPreciseTimestamp; + paymentProposalIds: string[]; + backupProblem?: BackupProblem; + paymentStatus: ProviderPaymentStatus; +} + +export interface BackupProviderTerms { + supportedProtocolVersion: string; + annualFee: AmountString; + storageLimitInMegabytes: number; +} + +export type BackupProblem = + | BackupUnreadableProblem + | BackupConflictingDeviceProblem; + +export interface BackupUnreadableProblem { + type: "backup-unreadable"; +} + +export interface BackupConflictingDeviceProblem { + type: "backup-conflicting-device"; + otherDeviceId: string; + myDeviceId: string; + backupTimestamp: AbsoluteTime; +} + +export type ProviderPaymentStatus = + | ProviderPaymentTermsChanged + | ProviderPaymentPaid + | ProviderPaymentInsufficientBalance + | ProviderPaymentUnpaid + | ProviderPaymentPending; + +export enum ProviderPaymentType { + Unpaid = "unpaid", + Pending = "pending", + InsufficientBalance = "insufficient-balance", + Paid = "paid", + TermsChanged = "terms-changed", +} + +export interface ProviderPaymentUnpaid { + type: ProviderPaymentType.Unpaid; +} + +export interface ProviderPaymentInsufficientBalance { + type: ProviderPaymentType.InsufficientBalance; + amount: AmountString; +} + +export interface ProviderPaymentPending { + type: ProviderPaymentType.Pending; + talerUri?: string; +} + +export interface ProviderPaymentPaid { + type: ProviderPaymentType.Paid; + paidUntil: AbsoluteTime; +} + +export interface ProviderPaymentTermsChanged { + type: ProviderPaymentType.TermsChanged; + paidUntil: AbsoluteTime; + oldTerms: BackupProviderTerms; + newTerms: BackupProviderTerms; +} + +// FIXME: Does not really belong here, move to sync API +export interface SyncTermsOfServiceResponse { + // maximum backup size supported + storage_limit_in_megabytes: number; + + // Fee for an account, per year. + annual_fee: AmountString; + + // protocol version supported by the server, + // for now always "0.0". + version: string; +} + +// FIXME: Does not really belong here, move to sync API +export const codecForSyncTermsOfServiceResponse = + (): Codec => + buildCodecForObject() + .property("storage_limit_in_megabytes", codecForNumber()) + .property("annual_fee", codecForAmountString()) + .property("version", codecForString()) + .build("SyncTermsOfServiceResponse"); diff --git a/packages/taler-wallet-core/package.json b/packages/taler-wallet-core/package.json index 7427609e5..48c3600ee 100644 --- a/packages/taler-wallet-core/package.json +++ b/packages/taler-wallet-core/package.json @@ -39,6 +39,9 @@ }, "./remote": { "default": "./lib/remote.js" + }, + "./dbless": { + "default": "./lib/dbless.js" } }, "imports": { diff --git a/packages/taler-wallet-core/src/backup/index.ts b/packages/taler-wallet-core/src/backup/index.ts index 13bf95026..919e92c5a 100644 --- a/packages/taler-wallet-core/src/backup/index.ts +++ b/packages/taler-wallet-core/src/backup/index.ts @@ -26,7 +26,6 @@ */ import { AbsoluteTime, - AmountString, AttentionType, BackupRecovery, Codec, @@ -34,11 +33,12 @@ import { HttpStatusCode, Logger, PreparePayResult, + ProviderInfo, + ProviderPaymentStatus, RecoveryLoadRequest, RecoveryMergeStrategy, TalerError, TalerErrorCode, - TalerErrorDetail, TalerPreciseTimestamp, URL, buildCodecForObject, @@ -46,12 +46,11 @@ import { bytesToString, canonicalJson, canonicalizeBaseUrl, - codecForAmountString, codecForBoolean, codecForConstString, codecForList, - codecForNumber, codecForString, + codecForSyncTermsOfServiceResponse, codecOptional, decodeCrock, durationFromSpec, @@ -71,11 +70,16 @@ import { readTalerErrorResponse, } from "@gnu-taler/taler-util/http"; import { gunzipSync, gzipSync } from "fflate"; +import { addAttentionRequest, removeAttentionRequest } from "../attention.js"; +import { + TaskIdentifiers, + TaskRunResult, + TaskRunResultType, +} from "../common.js"; import { BackupProviderRecord, BackupProviderState, BackupProviderStateTag, - BackupProviderTerms, ConfigRecord, ConfigRecordKey, WalletBackupConfState, @@ -84,17 +88,8 @@ import { timestampPreciseToDb, } from "../db.js"; import { InternalWalletState } from "../internal-wallet-state.js"; -import { - checkDbInvariant, - checkLogicInvariant, -} from "../util/invariants.js"; -import { addAttentionRequest, removeAttentionRequest } from "../attention.js"; -import { - TaskIdentifiers, - TaskRunResult, - TaskRunResultType, -} from "../common.js"; import { preparePayForUri } from "../pay-merchant.js"; +import { checkDbInvariant, checkLogicInvariant } from "../util/invariants.js"; const logger = new Logger("operations/backup.ts"); @@ -496,26 +491,6 @@ export async function runBackupCycle( } } -export interface SyncTermsOfServiceResponse { - // maximum backup size supported - storage_limit_in_megabytes: number; - - // Fee for an account, per year. - annual_fee: AmountString; - - // protocol version supported by the server, - // for now always "0.0". - version: string; -} - -export const codecForSyncTermsOfServiceResponse = - (): Codec => - buildCodecForObject() - .property("storage_limit_in_megabytes", codecForNumber()) - .property("annual_fee", codecForAmountString()) - .property("version", codecForString()) - .build("SyncTermsOfServiceResponse"); - export interface AddBackupProviderRequest { backupProviderBaseUrl: string; @@ -664,94 +639,12 @@ export async function restoreFromRecoverySecret(): Promise { return; } -/** - * Information about one provider. - * - * We don't store the account key here, - * as that's derived from the wallet root key. - */ -export interface ProviderInfo { - active: boolean; - syncProviderBaseUrl: string; - name: string; - terms?: BackupProviderTerms; - /** - * Last communication issue with the provider. - */ - lastError?: TalerErrorDetail; - lastSuccessfulBackupTimestamp?: TalerPreciseTimestamp; - lastAttemptedBackupTimestamp?: TalerPreciseTimestamp; - paymentProposalIds: string[]; - backupProblem?: BackupProblem; - paymentStatus: ProviderPaymentStatus; -} - -export type BackupProblem = - | BackupUnreadableProblem - | BackupConflictingDeviceProblem; - -export interface BackupUnreadableProblem { - type: "backup-unreadable"; -} - -export interface BackupUnreadableProblem { - type: "backup-unreadable"; -} - -export interface BackupConflictingDeviceProblem { - type: "backup-conflicting-device"; - otherDeviceId: string; - myDeviceId: string; - backupTimestamp: AbsoluteTime; -} - -export type ProviderPaymentStatus = - | ProviderPaymentTermsChanged - | ProviderPaymentPaid - | ProviderPaymentInsufficientBalance - | ProviderPaymentUnpaid - | ProviderPaymentPending; - export interface BackupInfo { walletRootPub: string; deviceId: string; providers: ProviderInfo[]; } -export enum ProviderPaymentType { - Unpaid = "unpaid", - Pending = "pending", - InsufficientBalance = "insufficient-balance", - Paid = "paid", - TermsChanged = "terms-changed", -} - -export interface ProviderPaymentUnpaid { - type: ProviderPaymentType.Unpaid; -} - -export interface ProviderPaymentInsufficientBalance { - type: ProviderPaymentType.InsufficientBalance; - amount: AmountString; -} - -export interface ProviderPaymentPending { - type: ProviderPaymentType.Pending; - talerUri?: string; -} - -export interface ProviderPaymentPaid { - type: ProviderPaymentType.Paid; - paidUntil: AbsoluteTime; -} - -export interface ProviderPaymentTermsChanged { - type: ProviderPaymentType.TermsChanged; - paidUntil: AbsoluteTime; - oldTerms: BackupProviderTerms; - newTerms: BackupProviderTerms; -} - async function getProviderPaymentInfo( ws: InternalWalletState, provider: BackupProviderRecord, diff --git a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts index 83897f331..f86163723 100644 --- a/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts +++ b/packages/taler-wallet-core/src/crypto/workers/crypto-dispatcher.ts @@ -27,10 +27,12 @@ import { j2s, Logger, openPromise, + performanceNow, TalerError, TalerErrorCode, + timer, + TimerHandle, } from "@gnu-taler/taler-util"; -import { performanceNow, timer, TimerHandle } from "../../util/timer.js"; import { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js"; import { CryptoWorker } from "./cryptoWorkerInterface.js"; diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts index 12801194f..33f962339 100644 --- a/packages/taler-wallet-core/src/db.ts +++ b/packages/taler-wallet-core/src/db.ts @@ -34,6 +34,7 @@ import { AmountString, Amounts, AttentionInfo, + BackupProviderTerms, Codec, CoinEnvelope, CoinPublicKeyString, @@ -1625,12 +1626,6 @@ export type BackupProviderState = tag: BackupProviderStateTag.Retrying; }; -export interface BackupProviderTerms { - supportedProtocolVersion: string; - annualFee: AmountString; - storageLimitInMegabytes: number; -} - export interface BackupProviderRecord { /** * Base URL of the provider. diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts index e538a6e76..1d2ebe9db 100644 --- a/packages/taler-wallet-core/src/dbless.ts +++ b/packages/taler-wallet-core/src/dbless.ts @@ -56,11 +56,13 @@ import { } from "@gnu-taler/taler-util/http"; import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; import { DenominationRecord } from "./db.js"; -import { ExchangeInfo } from "./exchanges.js"; +import { ExchangeInfo, downloadExchangeInfo } from "./exchanges.js"; import { assembleRefreshRevealRequest } from "./refresh.js"; import { isWithdrawableDenom } from "./util/denominations.js"; import { getBankStatusUrl, getBankWithdrawalInfo } from "./withdraw.js"; +export { downloadExchangeInfo }; + const logger = new Logger("dbless.ts"); export interface ReserveKeypair { diff --git a/packages/taler-wallet-core/src/host-impl.node.ts b/packages/taler-wallet-core/src/host-impl.node.ts index a2c37b32b..a0c739f45 100644 --- a/packages/taler-wallet-core/src/host-impl.node.ts +++ b/packages/taler-wallet-core/src/host-impl.node.ts @@ -32,13 +32,12 @@ import { shimIndexedDB, } from "@gnu-taler/idb-bridge"; import { createNodeSqlite3Impl } from "@gnu-taler/idb-bridge/node-sqlite3-bindings"; -import { Logger } from "@gnu-taler/taler-util"; +import { Logger, SetTimeoutTimerAPI } from "@gnu-taler/taler-util"; import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; import * as fs from "fs"; import { NodeThreadCryptoWorkerFactory } from "./crypto/workers/nodeThreadWorker.js"; import { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js"; import { DefaultNodeWalletArgs, makeTempfileId } from "./host-common.js"; -import { SetTimeoutTimerAPI } from "./util/timer.js"; import { Wallet } from "./wallet.js"; const logger = new Logger("host-impl.node.ts"); diff --git a/packages/taler-wallet-core/src/host-impl.qtart.ts b/packages/taler-wallet-core/src/host-impl.qtart.ts index 0fc346b44..329e491bf 100644 --- a/packages/taler-wallet-core/src/host-impl.qtart.ts +++ b/packages/taler-wallet-core/src/host-impl.qtart.ts @@ -36,12 +36,11 @@ import { createSqliteBackend, shimIndexedDB, } from "@gnu-taler/idb-bridge"; -import { Logger } from "@gnu-taler/taler-util"; +import { Logger, SetTimeoutTimerAPI } from "@gnu-taler/taler-util"; import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; import { qjsOs, qjsStd } from "@gnu-taler/taler-util/qtart"; import { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js"; import { DefaultNodeWalletArgs, makeTempfileId } from "./host-common.js"; -import { SetTimeoutTimerAPI } from "./util/timer.js"; import { Wallet } from "./wallet.js"; const logger = new Logger("host-impl.qtart.ts"); diff --git a/packages/taler-wallet-core/src/index.ts b/packages/taler-wallet-core/src/index.ts index 0e1feb58f..d0de16ccd 100644 --- a/packages/taler-wallet-core/src/index.ts +++ b/packages/taler-wallet-core/src/index.ts @@ -26,9 +26,19 @@ export { } from "./crypto/workers/crypto-dispatcher.js"; export type { CryptoWorker } from "./crypto/workers/cryptoWorkerInterface.js"; export { SynchronousCryptoWorkerFactoryPlain } from "./crypto/workers/synchronousWorkerFactoryPlain.js"; -export * from "./dbless.js"; export * from "./host-common.js"; export * from "./host.js"; export * from "./versions.js"; export * from "./wallet-api-types.js"; export * from "./wallet.js"; + +export { createPairTimeline } from "./util/denominations.js"; + +// FIXME: Should these really be exported?! +export { + WalletStoresV1, + deleteTalerDatabase, + exportDb, + importDb, +} from "./db.js"; +export { DbAccess } from "./query.js"; diff --git a/packages/taler-wallet-core/src/internal-wallet-state.ts b/packages/taler-wallet-core/src/internal-wallet-state.ts index 255019d23..d55b12269 100644 --- a/packages/taler-wallet-core/src/internal-wallet-state.ts +++ b/packages/taler-wallet-core/src/internal-wallet-state.ts @@ -32,6 +32,7 @@ import { IDBFactory } from "@gnu-taler/idb-bridge"; import { DenominationInfo, + TimerGroup, TransactionState, WalletNotification, } from "@gnu-taler/taler-util"; @@ -43,9 +44,8 @@ import { WalletDbReadWriteTransaction, WalletStoresV1, } from "./db.js"; -import { TaskScheduler } from "./shepherd.js"; import { DbAccess } from "./query.js"; -import { TimerGroup } from "./util/timer.js"; +import { TaskScheduler } from "./shepherd.js"; import { WalletConfig } from "./wallet-api-types.js"; export const EXCHANGE_COINS_LOCK = "exchange-coins-lock"; diff --git a/packages/taler-wallet-core/src/util/timer.ts b/packages/taler-wallet-core/src/util/timer.ts deleted file mode 100644 index 8db024512..000000000 --- a/packages/taler-wallet-core/src/util/timer.ts +++ /dev/null @@ -1,213 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2017-2019 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 - */ - -/** - * Cross-platform timers. - * - * NodeJS and the browser use slightly different timer API, - * this abstracts over these differences. - */ - -/** - * Imports. - */ -import { Logger, Duration } from "@gnu-taler/taler-util"; - -const logger = new Logger("timer.ts"); - -/** - * Cancelable timer. - */ -export interface TimerHandle { - clear(): void; - - /** - * Make sure the event loop exits when the timer is the - * only event left. Has no effect in the browser. - */ - unref(): void; -} - -class IntervalHandle { - constructor(public h: any) {} - - clear(): void { - clearInterval(this.h); - } - - /** - * Make sure the event loop exits when the timer is the - * only event left. Has no effect in the browser. - */ - unref(): void { - if (typeof this.h === "object" && "unref" in this.h) { - this.h.unref(); - } - } -} - -class TimeoutHandle { - constructor(public h: any) {} - - clear(): void { - clearTimeout(this.h); - } - - /** - * Make sure the event loop exits when the timer is the - * only event left. Has no effect in the browser. - */ - unref(): void { - if (typeof this.h === "object" && "unref" in this.h) { - this.h.unref(); - } - } -} - -/** - * Get a performance counter in nanoseconds. - */ -export const performanceNow: () => bigint = (() => { - // @ts-ignore - if (typeof process !== "undefined" && process.hrtime) { - return () => { - return process.hrtime.bigint(); - }; - } - - // @ts-ignore - if (typeof performance !== "undefined") { - // @ts-ignore - return () => BigInt(Math.floor(performance.now() * 1000)) * BigInt(1000); - } - - return () => BigInt(new Date().getTime()) * BigInt(1000) * BigInt(1000); -})(); - -const nullTimerHandle = { - clear() { - // do nothing - return; - }, - unref() { - // do nothing - return; - }, -}; - -/** - * Group of timers that can be destroyed at once. - */ -export interface TimerAPI { - after(delayMs: number, callback: () => void): TimerHandle; - every(delayMs: number, callback: () => void): TimerHandle; -} - -export class SetTimeoutTimerAPI implements TimerAPI { - /** - * Call a function every time the delay given in milliseconds passes. - */ - every(delayMs: number, callback: () => void): TimerHandle { - return new IntervalHandle(setInterval(callback, delayMs)); - } - - /** - * Call a function after the delay given in milliseconds passes. - */ - after(delayMs: number, callback: () => void): TimerHandle { - return new TimeoutHandle(setTimeout(callback, delayMs)); - } -} - -export const timer = new SetTimeoutTimerAPI(); - -/** - * Implementation of [[TimerGroup]] using setTimeout - */ -export class TimerGroup { - private stopped = false; - - private readonly timerMap: { [index: number]: TimerHandle } = {}; - - private idGen = 1; - - constructor(public readonly timerApi: TimerAPI) {} - - stopCurrentAndFutureTimers(): void { - this.stopped = true; - for (const x in this.timerMap) { - if (!this.timerMap.hasOwnProperty(x)) { - continue; - } - this.timerMap[x].clear(); - delete this.timerMap[x]; - } - } - - resolveAfter(delayMs: Duration): Promise { - return new Promise((resolve, reject) => { - if (delayMs.d_ms !== "forever") { - this.after(delayMs.d_ms, () => { - resolve(); - }); - } - }); - } - - after(delayMs: number, callback: () => void): TimerHandle { - if (this.stopped) { - logger.warn("dropping timer since timer group is stopped"); - return nullTimerHandle; - } - const h = this.timerApi.after(delayMs, callback); - const myId = this.idGen++; - this.timerMap[myId] = h; - - const tm = this.timerMap; - - return { - clear() { - h.clear(); - delete tm[myId]; - }, - unref() { - h.unref(); - }, - }; - } - - every(delayMs: number, callback: () => void): TimerHandle { - if (this.stopped) { - logger.warn("dropping timer since timer group is stopped"); - return nullTimerHandle; - } - const h = this.timerApi.every(delayMs, callback); - const myId = this.idGen++; - this.timerMap[myId] = h; - - const tm = this.timerMap; - - return { - clear() { - h.clear(); - delete tm[myId]; - }, - unref() { - h.unref(); - }, - }; - } -} diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 8b24fdc11..63b7ca4f2 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -51,6 +51,8 @@ import { TalerErrorCode, TalerUriAction, TestingWaitTransactionRequest, + TimerAPI, + TimerGroup, TransactionState, TransactionType, ValidateIbanResponse, @@ -132,32 +134,6 @@ import { validateIban, } from "@gnu-taler/taler-util"; import type { HttpRequestLibrary } from "@gnu-taler/taler-util/http"; -import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; -import { - CryptoDispatcher, - CryptoWorkerFactory, -} from "./crypto/workers/crypto-dispatcher.js"; -import { - CoinSourceType, - ConfigRecordKey, - DenominationRecord, - WalletDbReadOnlyTransaction, - WalletDbReadWriteTransaction, - WalletStoresV1, - clearDatabase, - exportDb, - importDb, - openStoredBackupsDatabase, - openTalerDatabase, -} from "./db.js"; -import { DevExperimentHttpLib, applyDevExperiment } from "./dev-experiments.js"; -import { - CancelFn, - InternalWalletState, - MerchantInfo, - NotificationListener, - RecoupOperations, -} from "./internal-wallet-state.js"; import { getUserAttentions, getUserAttentionsUnreadCount, @@ -176,12 +152,31 @@ import { setWalletDeviceId, } from "./backup/index.js"; import { getBalanceDetail, getBalances } from "./balance.js"; +import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; +import { + CryptoDispatcher, + CryptoWorkerFactory, +} from "./crypto/workers/crypto-dispatcher.js"; +import { + CoinSourceType, + ConfigRecordKey, + DenominationRecord, + WalletDbReadOnlyTransaction, + WalletDbReadWriteTransaction, + WalletStoresV1, + clearDatabase, + exportDb, + importDb, + openStoredBackupsDatabase, + openTalerDatabase, +} from "./db.js"; import { computeDepositTransactionStatus, createDepositGroup, generateDepositGroupTxId, prepareDepositGroup, } from "./deposits.js"; +import { DevExperimentHttpLib, applyDevExperiment } from "./dev-experiments.js"; import { acceptExchangeTermsOfService, addPresetExchangeEntry, @@ -193,6 +188,13 @@ import { listExchanges, lookupExchangeByUri, } from "./exchanges.js"; +import { + CancelFn, + InternalWalletState, + MerchantInfo, + NotificationListener, + RecoupOperations, +} from "./internal-wallet-state.js"; import { computePayMerchantTransactionState, computeRefundTransactionState, @@ -224,12 +226,11 @@ import { computePeerPushDebitTransactionState, initiatePeerPushDebit, } from "./pay-peer-push-debit.js"; +import { DbAccess } from "./query.js"; import { createRecoupGroup } from "./recoup.js"; -import { - computeRefreshTransactionState, - forceRefresh, -} from "./refresh.js"; +import { computeRefreshTransactionState, forceRefresh } from "./refresh.js"; import { computeRewardTransactionStatus } from "./reward.js"; +import { TaskScheduler } from "./shepherd.js"; import { runIntegrationTest, runIntegrationTest2, @@ -252,14 +253,6 @@ import { retryTransaction, suspendTransaction, } from "./transactions.js"; -import { - acceptWithdrawalFromUri, - computeWithdrawalTransactionStatus, - createManualWithdrawal, - getExchangeWithdrawalInfo, - getWithdrawalDetailsForUri, -} from "./withdraw.js"; -import { TaskScheduler } from "./shepherd.js"; import { assertUnreachable } from "./util/assertUnreachable.js"; import { convertDepositAmount, @@ -269,8 +262,6 @@ import { getMaxPeerPushAmount, } from "./util/instructedAmountConversion.js"; import { checkDbInvariant } from "./util/invariants.js"; -import { DbAccess } from "./query.js"; -import { TimerAPI, TimerGroup } from "./util/timer.js"; import { WALLET_BANK_CONVERSION_API_PROTOCOL_VERSION, WALLET_BANK_INTEGRATION_PROTOCOL_VERSION, @@ -286,6 +277,13 @@ import { WalletCoreApiClient, WalletCoreResponseType, } from "./wallet-api-types.js"; +import { + acceptWithdrawalFromUri, + computeWithdrawalTransactionStatus, + createManualWithdrawal, + getExchangeWithdrawalInfo, + getWithdrawalDetailsForUri, +} from "./withdraw.js"; const logger = new Logger("wallet.ts"); @@ -608,7 +606,7 @@ async function handlePrepareWithdrawExchange( /** * Response returned from the pending operations API. - * + * * @deprecated this is a placeholder for the response type of a deprecated wallet-core request. */ export interface PendingOperationsResponse { diff --git a/packages/taler-wallet-embedded/src/wallet-qjs.ts b/packages/taler-wallet-embedded/src/wallet-qjs.ts index 0fbcd7583..029cf2120 100644 --- a/packages/taler-wallet-embedded/src/wallet-qjs.ts +++ b/packages/taler-wallet-embedded/src/wallet-qjs.ts @@ -40,6 +40,7 @@ import { getErrorDetailFromException, j2s, openPromise, + performanceNow, setGlobalLogLevelFromString, } from "@gnu-taler/taler-util"; import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; @@ -49,7 +50,6 @@ import { Wallet, WalletApiOperation, createNativeWalletHost2, - performanceNow, } from "@gnu-taler/taler-wallet-core"; setGlobalLogLevelFromString("trace"); diff --git a/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts b/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts index ca2054931..e2ba5b285 100644 --- a/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts +++ b/packages/taler-wallet-webextension/src/hooks/useProviderStatus.ts @@ -14,7 +14,8 @@ GNU Taler; see the file COPYING. If not, see */ -import { ProviderInfo, WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { ProviderInfo } from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useEffect, useState } from "preact/hooks"; import { useBackendContext } from "../context/backend.js"; diff --git a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts index e0b79e060..daa6b425d 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts +++ b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/index.ts @@ -14,8 +14,10 @@ GNU Taler; see the file COPYING. If not, see */ -import { TalerErrorDetail } from "@gnu-taler/taler-util"; -import { SyncTermsOfServiceResponse } from "@gnu-taler/taler-wallet-core"; +import { + SyncTermsOfServiceResponse, + TalerErrorDetail, +} from "@gnu-taler/taler-util"; import { ErrorAlertView } from "../../components/CurrentAlerts.js"; import { Loading } from "../../components/Loading.js"; import { ErrorAlert } from "../../context/alert.js"; @@ -24,7 +26,7 @@ import { TextFieldHandler, ToggleHandler, } from "../../mui/handlers.js"; -import { compose, StateViewMap } from "../../utils/index.js"; +import { StateViewMap, compose } from "../../utils/index.js"; import { useComponentState } from "./state.js"; import { ConfirmProviderView, SelectProviderView } from "./views.js"; diff --git a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts index cf35abac7..e6d46a626 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/AddBackupProvider/state.ts @@ -14,11 +14,12 @@ GNU Taler; see the file COPYING. If not, see */ -import { canonicalizeBaseUrl, Codec } from "@gnu-taler/taler-util"; import { + canonicalizeBaseUrl, + Codec, codecForSyncTermsOfServiceResponse, - WalletApiOperation, -} from "@gnu-taler/taler-wallet-core"; +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useEffect, useState } from "preact/hooks"; import { useAlertContext } from "../../context/alert.js"; import { useBackendContext } from "../../context/backend.js"; diff --git a/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx index ae160a30c..cc7c9af67 100644 --- a/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Backup.stories.tsx @@ -19,19 +19,18 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core"; -import { addDays } from "date-fns"; -import { - BackupView as TestedComponent, - ShowRecoveryInfo, -} from "./BackupPage.js"; -import * as tests from "@gnu-taler/web-util/testing"; import { AbsoluteTime, AmountString, + ProviderPaymentType, TalerPreciseTimestamp, - TalerProtocolTimestamp, } from "@gnu-taler/taler-util"; +import * as tests from "@gnu-taler/web-util/testing"; +import { addDays } from "date-fns"; +import { + ShowRecoveryInfo, + BackupView as TestedComponent, +} from "./BackupPage.js"; export default { title: "backup", diff --git a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx index b460d9f88..0a39b2777 100644 --- a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx @@ -16,15 +16,13 @@ import { AbsoluteTime, - stringifyRestoreUri -} from "@gnu-taler/taler-util"; -import { ProviderInfo, ProviderPaymentPaid, ProviderPaymentStatus, ProviderPaymentType, - WalletApiOperation, -} from "@gnu-taler/taler-wallet-core"; + stringifyRestoreUri, +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { differenceInMonths, @@ -324,12 +322,12 @@ function daysUntil(d: AbsoluteTime): string { duration?.years ? "years" : duration?.months - ? "months" - : duration?.days - ? "days" - : duration.hours - ? "hours" - : "minutes", + ? "months" + : duration?.days + ? "days" + : duration.hours + ? "hours" + : "minutes", ], }); return `${str}`; @@ -352,6 +350,6 @@ function getStatusPaidOrder( return a.paidUntil.t_ms === "never" ? -1 : b.paidUntil.t_ms === "never" - ? 1 - : a.paidUntil.t_ms - b.paidUntil.t_ms; + ? 1 + : a.paidUntil.t_ms - b.paidUntil.t_ms; } diff --git a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts index b1cbbc2b2..db88dc94e 100644 --- a/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts +++ b/packages/taler-wallet-webextension/src/wallet/ExchangeSelection/state.ts @@ -16,13 +16,13 @@ import { DenomOperationMap, FeeDescription } from "@gnu-taler/taler-util"; import { - createPairTimeline, WalletApiOperation, + createPairTimeline, } from "@gnu-taler/taler-wallet-core"; +import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { useState } from "preact/hooks"; import { alertFromError, useAlertContext } from "../../context/alert.js"; import { useBackendContext } from "../../context/backend.js"; -import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js"; import { Props, State } from "./index.js"; @@ -151,7 +151,7 @@ export function useComponentState({ }; } - //this may be expensive, useMemo + // this may be expensive, useMemo const coinOperationTimeline: DenomOperationMap = { deposit: createPairTimeline( selected.denomFees.deposit, diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx index f81a86b9d..d4ee09b89 100644 --- a/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetail.stories.tsx @@ -22,10 +22,9 @@ import { AbsoluteTime, AmountString, + ProviderPaymentType, TalerPreciseTimestamp, - TalerProtocolTimestamp, } from "@gnu-taler/taler-util"; -import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core"; import * as tests from "@gnu-taler/web-util/testing"; import { ProviderView as TestedComponent } from "./ProviderDetailPage.js"; diff --git a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx index 19ae39106..5bd90c69b 100644 --- a/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/ProviderDetailPage.tsx @@ -15,22 +15,22 @@ */ import * as utils from "@gnu-taler/taler-util"; -import { AbsoluteTime } from "@gnu-taler/taler-util"; import { + AbsoluteTime, ProviderInfo, ProviderPaymentStatus, ProviderPaymentType, - WalletApiOperation, -} from "@gnu-taler/taler-wallet-core"; -import { Fragment, h, VNode } from "preact"; +} from "@gnu-taler/taler-util"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; +import { useTranslationContext } from "@gnu-taler/web-util/browser"; +import { Fragment, VNode, h } from "preact"; import { ErrorAlertView } from "../components/CurrentAlerts.js"; import { ErrorMessage } from "../components/ErrorMessage.js"; import { Loading } from "../components/Loading.js"; -import { PaymentStatus, SmallLightText } from "../components/styled/index.js"; import { Time } from "../components/Time.js"; +import { PaymentStatus, SmallLightText } from "../components/styled/index.js"; import { alertFromError } from "../context/alert.js"; import { useBackendContext } from "../context/backend.js"; -import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; import { Button } from "../mui/Button.js"; diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index fb07b72a5..70db60eca 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -27,6 +27,7 @@ import { LogLevel, Logger, OpenedPromise, + SetTimeoutTimerAPI, TalerErrorCode, getErrorDetailFromException, makeErrorDetail, @@ -37,7 +38,6 @@ import { import { HttpRequestLibrary } from "@gnu-taler/taler-util/http"; import { DbAccess, - SetTimeoutTimerAPI, SynchronousCryptoWorkerFactoryPlain, Wallet, WalletOperations, -- cgit v1.2.3