/* This file is part of GNU Taler (C) 2019 GNUnet e.V. 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 */ /** * Common interface of the internal wallet state. This object is passed * to the various operations (exchange management, withdrawal, refresh, reserve * management, etc.). * * Some operations can be accessed via this state object. This allows mutual * recursion between operations, without having cyclic dependencies between * the respective TypeScript files. * * (You can think of this as a "header file" for the wallet implementation.) */ /** * Imports. */ import { CancellationToken, CoinRefreshRequest, DenominationInfo, RefreshGroupId, RefreshReason, WalletNotification, } from "@gnu-taler/taler-util"; import { HttpRequestLibrary } from "@gnu-taler/taler-util/http"; import { TalerCryptoInterface } from "./crypto/cryptoImplementation.js"; import { ExchangeDetailsRecord, ExchangeRecord, RefreshReasonDetails, WalletStoresV1, } from "./db.js"; import { AsyncCondition } from "./util/promiseUtils.js"; import { DbAccess, GetReadOnlyAccess, GetReadWriteAccess, } from "./util/query.js"; import { TimerGroup } from "./util/timer.js"; import { WalletConfig } from "./wallet-api-types.js"; export const EXCHANGE_COINS_LOCK = "exchange-coins-lock"; export const EXCHANGE_RESERVES_LOCK = "exchange-reserves-lock"; export interface TrustInfo { isTrusted: boolean; isAudited: boolean; } export interface MerchantInfo { protocolVersionCurrent: number; } /** * Interface for merchant-related operations. */ export interface MerchantOperations { getMerchantInfo( ws: InternalWalletState, merchantBaseUrl: string, ): Promise; } export interface RefreshOperations { createRefreshGroup( ws: InternalWalletState, tx: GetReadWriteAccess<{ denominations: typeof WalletStoresV1.denominations; coins: typeof WalletStoresV1.coins; refreshGroups: typeof WalletStoresV1.refreshGroups; coinAvailability: typeof WalletStoresV1.coinAvailability; }>, currency: string, oldCoinPubs: CoinRefreshRequest[], reason: RefreshReason, reasonDetails?: RefreshReasonDetails, ): Promise; } /** * Interface for exchange-related operations. */ export interface ExchangeOperations { // FIXME: Should other operations maybe always use // updateExchangeFromUrl? getExchangeDetails( tx: GetReadOnlyAccess<{ exchanges: typeof WalletStoresV1.exchanges; exchangeDetails: typeof WalletStoresV1.exchangeDetails; }>, exchangeBaseUrl: string, ): Promise; getExchangeTrust( ws: InternalWalletState, exchangeInfo: ExchangeRecord, ): Promise; updateExchangeFromUrl( ws: InternalWalletState, baseUrl: string, options?: { forceNow?: boolean; cancellationToken?: CancellationToken; }, ): Promise<{ exchange: ExchangeRecord; exchangeDetails: ExchangeDetailsRecord; }>; } export interface RecoupOperations { createRecoupGroup( ws: InternalWalletState, tx: GetReadWriteAccess<{ recoupGroups: typeof WalletStoresV1.recoupGroups; denominations: typeof WalletStoresV1.denominations; refreshGroups: typeof WalletStoresV1.refreshGroups; coins: typeof WalletStoresV1.coins; }>, exchangeBaseUrl: string, coinPubs: string[], ): Promise; processRecoupGroup( ws: InternalWalletState, recoupGroupId: string, options?: { forceNow?: boolean; }, ): Promise; } export type NotificationListener = (n: WalletNotification) => void; export interface ActiveLongpollInfo { [opId: string]: { cancel: () => void; }; } /** * Internal, shard wallet state that is used by the implementation * of wallet operations. * * FIXME: This should not be exported anywhere from the taler-wallet-core package, * as it's an opaque implementation detail. */ export interface InternalWalletState { /** * Active longpoll operations. */ activeLongpoll: ActiveLongpollInfo; cryptoApi: TalerCryptoInterface; timerGroup: TimerGroup; stopped: boolean; config: Readonly; /** * Asynchronous condition to interrupt the sleep of the * retry loop. * * Used to allow processing of new work faster. */ workAvailable: AsyncCondition; listeners: NotificationListener[]; initCalled: boolean; merchantInfoCache: Record; exchangeOps: ExchangeOperations; recoupOps: RecoupOperations; merchantOps: MerchantOperations; refreshOps: RefreshOperations; getDenomInfo( ws: InternalWalletState, tx: GetReadOnlyAccess<{ denominations: typeof WalletStoresV1.denominations; }>, exchangeBaseUrl: string, denomPubHash: string, ): Promise; db: DbAccess; http: HttpRequestLibrary; notify(n: WalletNotification): void; addNotificationListener(f: (n: WalletNotification) => void): void; /** * Stop ongoing processing. */ stop(): void; /** * Run an async function after acquiring a list of locks, identified * by string tokens. */ runSequentialized(tokens: string[], f: () => Promise): Promise; runUntilDone(req?: { maxRetries?: number }): Promise; }