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-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 ++++---- 11 files changed, 74 insertions(+), 386 deletions(-) delete mode 100644 packages/taler-wallet-core/src/util/timer.ts (limited to 'packages/taler-wallet-core') 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 { -- cgit v1.2.3