From 3f34981e5d2536fda9afc8616bb5647702d74898 Mon Sep 17 00:00:00 2001 From: Peter Sanderson Date: Tue, 3 Dec 2024 13:49:18 +0100 Subject: [PATCH] chore: unify types for setTimeout return type to address the NodeJS types leak issue --- packages/blockchain-link/src/workers/baseWebsocket.ts | 3 ++- .../src/workers/electrum/client/batching.ts | 4 +++- .../src/workers/electrum/client/caching.ts | 3 ++- .../src/workers/electrum/client/electrum.ts | 4 +++- packages/blockchain-link/src/workers/ripple/index.ts | 3 ++- packages/blockchain-link/src/workers/solana/index.ts | 5 +++-- packages/coinjoin/src/client/CoinjoinPrison.ts | 6 ++---- packages/coinjoin/src/client/Status.ts | 3 ++- .../components/VirtualizedList/VirtualizedList.tsx | 3 ++- packages/connect-popup/src/index.tsx | 3 ++- packages/connect-popup/src/log.tsx | 3 ++- packages/connect-web/src/popup/index.ts | 7 ++++--- packages/connect/src/backend/BackendManager.ts | 4 +++- packages/react-utils/src/hooks/useDebounce.ts | 4 ++-- .../suite-desktop-core/e2e/support/networkAnalyzer.ts | 4 +++- packages/suite-desktop-core/src/app.ts | 3 ++- packages/suite-desktop-core/src/hang-detect.ts | 3 ++- packages/suite-desktop-core/src/libs/logger.ts | 3 ++- .../src/libs/processes/BaseProcess.ts | 6 ++++-- .../labeling/MetadataLabeling/MetadataLabeling.tsx | 4 ++-- .../SuiteLayout/DeviceSelector/DeviceSelector.tsx | 6 +++--- packages/transport/src/sessions/background.ts | 5 +++-- packages/transport/src/transports/udp.ts | 4 +++- packages/type-utils/src/index.ts | 1 + packages/type-utils/src/timeout.ts | 11 +++++++++++ packages/type-utils/src/utils.ts | 3 +-- packages/utils/src/createDeferredManager.ts | 4 +++- packages/utils/src/scheduleAction.ts | 6 ++++-- packages/utils/src/throttler.ts | 4 +++- .../token-definitions/src/tokenDefinitionsThunks.ts | 4 ++-- .../wallet-core/src/blockchain/blockchainActions.ts | 4 ++-- .../wallet-core/src/blockchain/blockchainThunks.ts | 4 ++-- .../wallet-core/src/fiat-rates/fiatRatesThunks.ts | 3 ++- suite-common/wallet-core/src/stake/stakeThunks.ts | 4 ++-- suite-common/wallet-types/src/backend.ts | 4 ++-- .../app/src/hooks/useCoinEnablingInitialCheck.tsx | 3 ++- .../discovery/src/useIsDiscoveryDurationTooLong.tsx | 3 ++- suite-native/graph/src/components/Graph.tsx | 3 ++- .../HomeScreen/components/BiometricsBottomSheet.tsx | 3 ++- .../components/EnableViewOnlyBottomSheet.tsx | 3 ++- 40 files changed, 103 insertions(+), 57 deletions(-) create mode 100644 packages/type-utils/src/timeout.ts diff --git a/packages/blockchain-link/src/workers/baseWebsocket.ts b/packages/blockchain-link/src/workers/baseWebsocket.ts index 0132080c76e..d33f0ced179 100644 --- a/packages/blockchain-link/src/workers/baseWebsocket.ts +++ b/packages/blockchain-link/src/workers/baseWebsocket.ts @@ -2,6 +2,7 @@ import WebSocket from 'ws'; import { createDeferred, createDeferredManager, TypedEmitter } from '@trezor/utils'; import { CustomError } from '@trezor/blockchain-link-types/src/constants/errors'; +import { TimerId } from '@trezor/type-utils'; interface Subscription { id: string; @@ -38,7 +39,7 @@ export abstract class BaseWebsocket extends TypedEmitter = this; private ws?: WebSocket; - private pingTimeout?: ReturnType; + private pingTimeout?: TimerId; private connectPromise?: Promise; protected abstract ping(): Promise; diff --git a/packages/blockchain-link/src/workers/electrum/client/batching.ts b/packages/blockchain-link/src/workers/electrum/client/batching.ts index 3467e8390fc..926dc276eee 100644 --- a/packages/blockchain-link/src/workers/electrum/client/batching.ts +++ b/packages/blockchain-link/src/workers/electrum/client/batching.ts @@ -1,3 +1,5 @@ +import { TimerId } from '@trezor/type-utils'; + import { JsonRpcClient } from './json-rpc'; type Options = { @@ -11,7 +13,7 @@ const MAX_QUEUE_LENGTH = 15; // TODO batching should in theory improve performance export class BatchingJsonRpcClient extends JsonRpcClient { private queue: string[] = []; - private batchTimer?: ReturnType; + private batchTimer?: TimerId; private timeoutMs: number; private maxQueueLength: number; diff --git a/packages/blockchain-link/src/workers/electrum/client/caching.ts b/packages/blockchain-link/src/workers/electrum/client/caching.ts index cbe8dd58002..d681e837bcc 100644 --- a/packages/blockchain-link/src/workers/electrum/client/caching.ts +++ b/packages/blockchain-link/src/workers/electrum/client/caching.ts @@ -1,4 +1,5 @@ import { Status } from '@trezor/blockchain-link-types/src/electrum'; +import { IntervalId } from '@trezor/type-utils'; import { ElectrumClient } from './electrum'; @@ -15,7 +16,7 @@ export class CachingElectrumClient extends ElectrumClient { private readonly statuses: Statuses = {}; private cached = 0; private total = 0; - private logTimer: ReturnType; + private logTimer: IntervalId; constructor() { super(); diff --git a/packages/blockchain-link/src/workers/electrum/client/electrum.ts b/packages/blockchain-link/src/workers/electrum/client/electrum.ts index 17733b50ef2..fb6eaee6fce 100644 --- a/packages/blockchain-link/src/workers/electrum/client/electrum.ts +++ b/packages/blockchain-link/src/workers/electrum/client/electrum.ts @@ -1,5 +1,6 @@ import { Network, networks } from '@trezor/utxo-lib'; import { ElectrumAPI, BlockHeader, Version } from '@trezor/blockchain-link-types/src/electrum'; +import { IntervalId } from '@trezor/type-utils'; import { JsonRpcClientOptions } from './json-rpc'; import { BatchingJsonRpcClient } from './batching'; @@ -91,7 +92,8 @@ export class ElectrumClient extends BatchingJsonRpcClient implements ElectrumAPI return super.request(method, ...params); } - private keepAliveHandle?: ReturnType; + private keepAliveHandle?: IntervalId; + private keepAlive() { if (!this.socket) return; this.keepAliveHandle = setInterval(async () => { diff --git a/packages/blockchain-link/src/workers/ripple/index.ts b/packages/blockchain-link/src/workers/ripple/index.ts index 94224e1153f..f6d34d69435 100644 --- a/packages/blockchain-link/src/workers/ripple/index.ts +++ b/packages/blockchain-link/src/workers/ripple/index.ts @@ -7,6 +7,7 @@ import { MESSAGES, RESPONSES } from '@trezor/blockchain-link-types/src/constants import * as utils from '@trezor/blockchain-link-utils/src/ripple'; import type { Response, SubscriptionAccountInfo, AccountInfo } from '@trezor/blockchain-link-types'; import type * as MessageTypes from '@trezor/blockchain-link-types/src/messages'; +import { TimerId } from '@trezor/type-utils'; import { BaseWorker, CONTEXT, ContextType } from '../baseWorker'; @@ -420,7 +421,7 @@ const onRequest = (request: Request) => { }; class RippleWorker extends BaseWorker { - pingTimeout?: ReturnType; + pingTimeout?: TimerId; cleanup() { if (this.pingTimeout) { diff --git a/packages/blockchain-link/src/workers/solana/index.ts b/packages/blockchain-link/src/workers/solana/index.ts index 6bf012afb5a..b44e9ca02f3 100644 --- a/packages/blockchain-link/src/workers/solana/index.ts +++ b/packages/blockchain-link/src/workers/solana/index.ts @@ -55,6 +55,7 @@ import { TOKEN_PROGRAM_PUBLIC_KEY, } from '@trezor/blockchain-link-utils/src/solana'; import { getSuiteVersion } from '@trezor/env-utils'; +import { IntervalId } from '@trezor/type-utils'; import { getBaseFee, getPriorityFee } from './fee'; import { BaseWorker, ContextType, CONTEXT } from '../baseWorker'; @@ -474,7 +475,7 @@ const subscribeBlock = async ({ state, connect, post }: Context) => { const unsubscribeBlock = ({ state }: Context) => { if (!state.getSubscription('block')) return; - const interval = state.getSubscription('block') as ReturnType; + const interval = state.getSubscription('block') as IntervalId; clearInterval(interval); state.removeSubscription('block'); }; @@ -769,7 +770,7 @@ class SolanaWorker extends BaseWorker { }); if (this.state.getSubscription('block')) { - const interval = this.state.getSubscription('block') as ReturnType; + const interval = this.state.getSubscription('block') as IntervalId; clearInterval(interval); this.state.removeSubscription('block'); } diff --git a/packages/coinjoin/src/client/CoinjoinPrison.ts b/packages/coinjoin/src/client/CoinjoinPrison.ts index 7eb8d357a23..58fca2e376b 100644 --- a/packages/coinjoin/src/client/CoinjoinPrison.ts +++ b/packages/coinjoin/src/client/CoinjoinPrison.ts @@ -1,4 +1,5 @@ import { TypedEmitter } from '@trezor/utils'; +import { ImmediateId, TimerId } from '@trezor/type-utils'; import { CoinjoinPrisonInmate, CoinjoinPrisonEvents } from '../types/client'; import { WabiSabiProtocolErrorCode } from '../enums'; @@ -28,10 +29,7 @@ export interface DetainOptions { export class CoinjoinPrison extends TypedEmitter { inmates: CoinjoinPrisonInmate[] = []; - private changeEventThrottle: - | ReturnType - | ReturnType - | undefined; + private changeEventThrottle: ImmediateId | TimerId | undefined; constructor(initialState: CoinjoinPrisonInmate[] = []) { super(); diff --git a/packages/coinjoin/src/client/Status.ts b/packages/coinjoin/src/client/Status.ts index 68ea510ddd9..61fa51335a1 100644 --- a/packages/coinjoin/src/client/Status.ts +++ b/packages/coinjoin/src/client/Status.ts @@ -1,4 +1,5 @@ import { TypedEmitter } from '@trezor/utils'; +import { TimerId } from '@trezor/type-utils'; import * as coordinator from './coordinator'; import { transformStatus } from '../utils/roundUtils'; @@ -38,7 +39,7 @@ export class Status extends TypedEmitter { mode: StatusMode = 'idle'; private settings: CoinjoinClientSettings; private abortController: AbortController; - private statusTimeout?: ReturnType; + private statusTimeout?: TimerId; private identities: string[]; // registered identities private runningAffiliateServer = false; diff --git a/packages/components/src/components/VirtualizedList/VirtualizedList.tsx b/packages/components/src/components/VirtualizedList/VirtualizedList.tsx index 4ae6dd13404..72e94fdde95 100644 --- a/packages/components/src/components/VirtualizedList/VirtualizedList.tsx +++ b/packages/components/src/components/VirtualizedList/VirtualizedList.tsx @@ -3,12 +3,13 @@ import React, { useState, useEffect, useCallback, forwardRef, useRef } from 'rea import styled from 'styled-components'; import { isChanged } from '@suite-common/suite-utils'; +import { TimerId } from '@trezor/type-utils'; function debounce void>( func: T, wait: number, ): (...args: Parameters) => void { - let timeout: ReturnType | null = null; + let timeout: TimerId | null = null; return (...args: Parameters) => { if (timeout !== null) { diff --git a/packages/connect-popup/src/index.tsx b/packages/connect-popup/src/index.tsx index 709eadae37b..57008e8f99b 100644 --- a/packages/connect-popup/src/index.tsx +++ b/packages/connect-popup/src/index.tsx @@ -28,6 +28,7 @@ import { analytics, EventType } from '@trezor/connect-analytics'; import { getSystemInfo } from '@trezor/connect-common'; import { initLog, setLogWriter, LogWriter } from '@trezor/connect/src/utils/debug'; import { DEFAULT_DOMAIN } from '@trezor/connect/src/data/version'; +import { TimerId } from '@trezor/type-utils'; import * as view from './view'; import { @@ -46,7 +47,7 @@ const INTERVAL_HANDSHAKE_TIMEOUT_MS = 90 * 1000; const log = initLog('@trezor/connect-popup'); const proxyLogger = initLog('@trezor/connect-webextension'); -let handshakeTimeout: ReturnType; +let handshakeTimeout: TimerId; let renderConnectUIPromise: Promise | undefined; // browser built-in functionality to quickly and safely escape the string diff --git a/packages/connect-popup/src/log.tsx b/packages/connect-popup/src/log.tsx index 95397127d8c..d63794a1167 100644 --- a/packages/connect-popup/src/log.tsx +++ b/packages/connect-popup/src/log.tsx @@ -9,6 +9,7 @@ import { InfoPanel } from '@trezor/connect-ui/src/components/InfoPanel'; import { View } from '@trezor/connect-ui/src/components/View'; import { Button, Paragraph, intermediaryTheme } from '@trezor/components'; import { LogMessage } from '@trezor/connect/src/utils/debug'; +import { TimerId } from '@trezor/type-utils'; interface ReactWrapperProps { children: React.ReactNode; @@ -79,7 +80,7 @@ const DownloadButton = ({ array, filename }: { array: any[]; filename: string }) }; let logDebounceCache: any[] = []; -let logDebounceTimeout: ReturnType | undefined; +let logDebounceTimeout: TimerId | undefined; const logInConsole = (logs: any[]) => { // Logs in console are debounced in order to try to make sure that diff --git a/packages/connect-web/src/popup/index.ts b/packages/connect-web/src/popup/index.ts index 1019596eb3f..c9395f3c326 100644 --- a/packages/connect-web/src/popup/index.ts +++ b/packages/connect-web/src/popup/index.ts @@ -12,6 +12,7 @@ import { AbstractMessageChannel, Message, } from '@trezor/connect-common/src/messageChannel/abstract'; +import { IntervalId, TimerId } from '@trezor/type-utils'; import { showPopupRequest } from './showPopupRequest'; import { ServiceWorkerWindowChannel } from '../channels/serviceworker-window'; @@ -59,11 +60,11 @@ export class PopupManager extends EventEmitter { popupPromise: Deferred | undefined; - requestTimeout: ReturnType | undefined; + requestTimeout: TimerId | undefined; - openTimeout: ReturnType | undefined; + openTimeout: TimerId | undefined; - closeInterval: ReturnType | undefined; + closeInterval: IntervalId | undefined; extensionTabId = 0; diff --git a/packages/connect/src/backend/BackendManager.ts b/packages/connect/src/backend/BackendManager.ts index fbe4767963f..ace8dd3c4fe 100644 --- a/packages/connect/src/backend/BackendManager.ts +++ b/packages/connect/src/backend/BackendManager.ts @@ -1,3 +1,5 @@ +import { TimerId } from '@trezor/type-utils'; + import { DataManager } from '../data/DataManager'; import { ERRORS } from '../constants'; import { Blockchain, BlockchainOptions } from './Blockchain'; @@ -7,7 +9,7 @@ import type { CoinInfo, BlockchainLink } from '../types'; type CoinShortcut = CoinInfo['shortcut']; type Identity = string; type CoinShortcutIdentity = `${CoinShortcut}/${Identity}`; -type Reconnect = { attempts: number; handle: ReturnType }; +type Reconnect = { attempts: number; handle: TimerId }; type BackendParams = Pick; const DEFAULT_IDENTITY = 'default'; diff --git a/packages/react-utils/src/hooks/useDebounce.ts b/packages/react-utils/src/hooks/useDebounce.ts index 70503de32f6..64543d5c1c7 100644 --- a/packages/react-utils/src/hooks/useDebounce.ts +++ b/packages/react-utils/src/hooks/useDebounce.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef } from 'react'; import { createDeferred } from '@trezor/utils'; -import type { Timeout } from '@trezor/type-utils'; +import type { TimerId } from '@trezor/type-utils'; type AsyncFunction = (...args: any) => Promise; type SyncFunction = (...args: any) => any; @@ -10,7 +10,7 @@ type SyncFunction = (...args: any) => any; // `timeout` prevents from calling '@trezor/connect' method to many times (inputs mad-clicking) // TODO: maybe it should be converted to regular module, could be useful elsewhere export const useDebounce = () => { - const timeout = useRef(null); + const timeout = useRef(null); const debounce = useCallback( async (fn: F): Promise> => { diff --git a/packages/suite-desktop-core/e2e/support/networkAnalyzer.ts b/packages/suite-desktop-core/e2e/support/networkAnalyzer.ts index e94550b9cfd..0042bd49cd1 100644 --- a/packages/suite-desktop-core/e2e/support/networkAnalyzer.ts +++ b/packages/suite-desktop-core/e2e/support/networkAnalyzer.ts @@ -1,7 +1,9 @@ import { exec } from 'child_process'; +import { IntervalId } from '@trezor/type-utils'; + export class NetworkAnalyzer { - interval?: string | number | ReturnType; + interval?: string | number | IntervalId; tcp: string[]; constructor() { diff --git a/packages/suite-desktop-core/src/app.ts b/packages/suite-desktop-core/src/app.ts index ede3f18a8ae..854a8b79ceb 100644 --- a/packages/suite-desktop-core/src/app.ts +++ b/packages/suite-desktop-core/src/app.ts @@ -6,6 +6,7 @@ import type { HandshakeClient } from '@trezor/suite-desktop-api'; import { validateIpcMessage } from '@trezor/ipc-proxy'; import { createDeferred, createTimeoutPromise } from '@trezor/utils'; import { isMacOs } from '@trezor/env-utils'; +import { TimerId } from '@trezor/type-utils'; import { ipcMain } from './typed-electron'; import { APP_NAME } from './libs/constants'; @@ -51,7 +52,7 @@ const createMainWindow = (winBounds: WinBounds) => { icon: path.join(global.resourcesPath, 'images', 'icons', '512x512.png'), }); - let resizeDebounce: ReturnType | null = null; + let resizeDebounce: TimerId | null = null; mainWindow.on('resize', () => { if (resizeDebounce) return; diff --git a/packages/suite-desktop-core/src/hang-detect.ts b/packages/suite-desktop-core/src/hang-detect.ts index 80be3785350..79e3f509caf 100644 --- a/packages/suite-desktop-core/src/hang-detect.ts +++ b/packages/suite-desktop-core/src/hang-detect.ts @@ -2,6 +2,7 @@ import { BrowserWindow, dialog } from 'electron'; import { validateIpcMessage } from '@trezor/ipc-proxy'; import { ElectronIpcMainInvokeEvent } from '@trezor/ipc-proxy/src/proxy-handler'; +import { TimerId } from '@trezor/type-utils'; import { ipcMain } from './typed-electron'; import { APP_SRC } from './libs/constants'; @@ -27,7 +28,7 @@ export const hangDetect = (mainWindow: BrowserWindow, statePatch?: Record; + let timeout: TimerId; const handshake = new Promise(resolve => { const timeoutCallback = async () => { diff --git a/packages/suite-desktop-core/src/libs/logger.ts b/packages/suite-desktop-core/src/libs/logger.ts index 586a0d3e15e..30fffaf8456 100644 --- a/packages/suite-desktop-core/src/libs/logger.ts +++ b/packages/suite-desktop-core/src/libs/logger.ts @@ -6,6 +6,7 @@ import { app } from 'electron'; import { isDevEnv } from '@suite-common/suite-utils'; import { ensureDirectoryExists } from '@trezor/node-utils'; +import { TimerId } from '@trezor/type-utils'; import { getBuildInfo, getComputerInfo } from './info'; @@ -130,7 +131,7 @@ export class Logger implements ILogger { } private dedupeMessage?: RepeatedLogMessage; - private dedupeTimeout?: ReturnType; + private dedupeTimeout?: TimerId; private handleMessage(message: LogMessage) { if (!this.options.dedupeTimeout) { diff --git a/packages/suite-desktop-core/src/libs/processes/BaseProcess.ts b/packages/suite-desktop-core/src/libs/processes/BaseProcess.ts index 4110a22a2d5..c557e71d793 100644 --- a/packages/suite-desktop-core/src/libs/processes/BaseProcess.ts +++ b/packages/suite-desktop-core/src/libs/processes/BaseProcess.ts @@ -2,6 +2,8 @@ import { app } from 'electron'; import path from 'path'; import { spawn, ChildProcess } from 'child_process'; +import { TimerId } from '@trezor/type-utils'; + import { b2t } from '../utils'; export type Status = { @@ -31,7 +33,7 @@ export abstract class BaseProcess { resourceName: string; processName: string; options: Options; - startupThrottle: ReturnType | null; + startupThrottle: TimerId | null; supportedSystems = ['linux-arm64', 'linux-x64', 'mac-arm64', 'mac-x64', 'win-x64']; stopped = false; logger: ILogger; @@ -158,7 +160,7 @@ export abstract class BaseProcess { // that started the process, so if it fails an error is thrown to let the module knows something // went wrong. // eslint-disable-next-line prefer-const - let resolveTimeout: ReturnType | undefined; + let resolveTimeout: TimerId | undefined; const spawnErrorHandler = (message: any) => { // This error handler will be triggered if there is an error during spawn of the process, // it will reject with an error so the user can be notified that something went wrong. diff --git a/packages/suite/src/components/suite/labeling/MetadataLabeling/MetadataLabeling.tsx b/packages/suite/src/components/suite/labeling/MetadataLabeling/MetadataLabeling.tsx index 543e0986e37..fbd9f60bedb 100644 --- a/packages/suite/src/components/suite/labeling/MetadataLabeling/MetadataLabeling.tsx +++ b/packages/suite/src/components/suite/labeling/MetadataLabeling/MetadataLabeling.tsx @@ -3,7 +3,7 @@ import { useEffect, useState, useMemo, useRef } from 'react'; import styled from 'styled-components'; import { Button, DropdownMenuItemProps, Row } from '@trezor/components'; -import type { Timeout } from '@trezor/type-utils'; +import type { TimerId } from '@trezor/type-utils'; import { StaticSessionId } from '@trezor/connect'; import { useDiscovery, useDispatch, useSelector } from 'src/hooks/suite'; @@ -293,7 +293,7 @@ export const MetadataLabeling = ({ const dataTestBase = `@metadata/${payload.type}/${payload.defaultValue}`; const actionButtonsDisabled = isDiscoveryRunning || pending; const isSubscribedToSubmitResult = useRef(payload.defaultValue); - let timeout: Timeout | undefined; + let timeout: TimerId | undefined; useEffect(() => { setPending(false); setShowSuccess(false); diff --git a/packages/suite/src/components/suite/layouts/SuiteLayout/DeviceSelector/DeviceSelector.tsx b/packages/suite/src/components/suite/layouts/SuiteLayout/DeviceSelector/DeviceSelector.tsx index 9ce90f39b07..1ea9da16997 100644 --- a/packages/suite/src/components/suite/layouts/SuiteLayout/DeviceSelector/DeviceSelector.tsx +++ b/packages/suite/src/components/suite/layouts/SuiteLayout/DeviceSelector/DeviceSelector.tsx @@ -3,7 +3,7 @@ import { useState, useEffect, useRef } from 'react'; import styled, { css } from 'styled-components'; import { selectDevicesCount, selectDevice } from '@suite-common/wallet-core'; -import type { Timeout } from '@trezor/type-utils'; +import type { TimerId } from '@trezor/type-utils'; import { borders, spacingsPx } from '@trezor/theme'; import { focusStyleTransition, getFocusShadowStyle } from '@trezor/components/src/utils/utils'; import { Icon } from '@trezor/components'; @@ -78,8 +78,8 @@ export const DeviceSelector = () => { const [isAnimationTriggered, setIsAnimationTriggered] = useState(false); const countChanged = localCount && localCount !== deviceCount; - const shakeAnimationTimerRef = useRef(undefined); - const stateAnimationTimerRef = useRef(undefined); + const shakeAnimationTimerRef = useRef(undefined); + const stateAnimationTimerRef = useRef(undefined); useEffect( () => diff --git a/packages/transport/src/sessions/background.ts b/packages/transport/src/sessions/background.ts index 20b5acf0452..c078d3182da 100644 --- a/packages/transport/src/sessions/background.ts +++ b/packages/transport/src/sessions/background.ts @@ -10,6 +10,7 @@ */ import { createDeferred, Deferred, TypedEmitter } from '@trezor/utils'; +import { TimerId } from '@trezor/type-utils'; import type { EnumerateDoneRequest, @@ -53,8 +54,8 @@ export class SessionsBackground private pathInternalPathPublicMap: Record = {}; // if lock is set, somebody is doing something with device. we have to wait - private locksQueue: { id: ReturnType; dfd: Deferred }[] = []; - private locksTimeoutQueue: ReturnType[] = []; + private locksQueue: { id: TimerId; dfd: Deferred }[] = []; + private locksTimeoutQueue: TimerId[] = []; private lastSessionId = 0; private lastPathId = 0; diff --git a/packages/transport/src/transports/udp.ts b/packages/transport/src/transports/udp.ts index 4687439fc95..b9199627f48 100644 --- a/packages/transport/src/transports/udp.ts +++ b/packages/transport/src/transports/udp.ts @@ -1,3 +1,5 @@ +import { TimerId } from '@trezor/type-utils'; + import { AbstractTransportParams } from './abstract'; import { UdpApi } from '../api/udp'; import { AbstractApiTransport } from './abstractApi'; @@ -5,7 +7,7 @@ import { AbstractApiTransport } from './abstractApi'; export class UdpTransport extends AbstractApiTransport { public name = 'UdpTransport' as const; public apiType = 'udp' as const; - private enumerateTimeout: ReturnType | undefined; + private enumerateTimeout: TimerId | undefined; constructor(params: AbstractTransportParams) { const { logger, debugLink, ...rest } = params; diff --git a/packages/type-utils/src/index.ts b/packages/type-utils/src/index.ts index 04bca77e0de..5f0d9cd5fd7 100644 --- a/packages/type-utils/src/index.ts +++ b/packages/type-utils/src/index.ts @@ -1 +1,2 @@ export * from './utils'; +export * from './timeout'; diff --git a/packages/type-utils/src/timeout.ts b/packages/type-utils/src/timeout.ts new file mode 100644 index 00000000000..4e1756c620e --- /dev/null +++ b/packages/type-utils/src/timeout.ts @@ -0,0 +1,11 @@ +/** + * Hack to workaround NodeJS.Timeout vs number type issue. + * + * Some reads on the topic: + * - https://stackoverflow.com/questions/45802988/typescript-use-correct-version-of-settimeout-node-vs-window + * - https://guilhermesimoes.github.io/blog/making-settimeout-return-number-in-typescript + * + */ +export type TimerId = ReturnType; +export type ImmediateId = ReturnType; +export type IntervalId = ReturnType; diff --git a/packages/type-utils/src/utils.ts b/packages/type-utils/src/utils.ts index 8f59b7e0178..11e814f1edb 100644 --- a/packages/type-utils/src/utils.ts +++ b/packages/type-utils/src/utils.ts @@ -1,4 +1,5 @@ // make key required + export type RequiredKey = Omit & Required>; // object values types @@ -47,8 +48,6 @@ export type DeepPartial = T extends () => any export type PrimitiveType = string | number | boolean | Date | null | undefined; -export type Timeout = ReturnType; - // Record with optional key and required value. // example of using partial union as keys: // const p: PartialRecord<'a' | 'b' | 'c', string>; = { b: 'value' }; diff --git a/packages/utils/src/createDeferredManager.ts b/packages/utils/src/createDeferredManager.ts index dc10c9d5a9f..1552e2eb3f8 100644 --- a/packages/utils/src/createDeferredManager.ts +++ b/packages/utils/src/createDeferredManager.ts @@ -1,3 +1,5 @@ +import { TimerId } from '@trezor/type-utils'; + import { createDeferred, Deferred } from './createDeferred'; type ManagedDeferred = Deferred & { deadline: number }; @@ -42,7 +44,7 @@ export const createDeferredManager = ( const promises: ManagedDeferred[] = []; let ID = initialId; - let timeoutHandle: ReturnType | undefined; + let timeoutHandle: TimerId | undefined; const length = () => promises.length; diff --git a/packages/utils/src/scheduleAction.ts b/packages/utils/src/scheduleAction.ts index 12e34aac8af..7167281e14e 100644 --- a/packages/utils/src/scheduleAction.ts +++ b/packages/utils/src/scheduleAction.ts @@ -1,3 +1,5 @@ +import { TimerId } from '@trezor/type-utils'; + export type ScheduledAction = (signal?: AbortSignal) => Promise; type AttemptParams = { @@ -28,7 +30,7 @@ const resolveAfterMs = (ms: number | undefined, clear: AbortSignal) => if (clear.aborted) return reject(); if (ms === undefined) return resolve(); // eslint-disable-next-line prefer-const - let timeout: ReturnType; + let timeout: TimerId; const onClear = () => { clearTimeout(timeout); clear.removeEventListener('abort', onClear); @@ -45,7 +47,7 @@ const rejectAfterMs = (ms: number, reason: () => Error, clear: AbortSignal) => new Promise((_, reject) => { if (clear.aborted) return reject(); // eslint-disable-next-line prefer-const - let timeout: ReturnType | undefined; + let timeout: TimerId | undefined; const onClear = () => { clearTimeout(timeout); clear.removeEventListener('abort', onClear); diff --git a/packages/utils/src/throttler.ts b/packages/utils/src/throttler.ts index 6a093d7dc23..b658f438470 100644 --- a/packages/utils/src/throttler.ts +++ b/packages/utils/src/throttler.ts @@ -1,6 +1,8 @@ +import { IntervalId } from '@trezor/type-utils'; + export class Throttler { private readonly delay: number; - private readonly intervals: { [id: string]: ReturnType }; + private readonly intervals: { [id: string]: IntervalId }; private readonly callbacks: { [id: string]: () => void }; constructor(delay: number) { diff --git a/suite-common/token-definitions/src/tokenDefinitionsThunks.ts b/suite-common/token-definitions/src/tokenDefinitionsThunks.ts index 72a5c46f3ed..2e851ed6fc3 100644 --- a/suite-common/token-definitions/src/tokenDefinitionsThunks.ts +++ b/suite-common/token-definitions/src/tokenDefinitionsThunks.ts @@ -4,7 +4,7 @@ import { D, G } from '@mobily/ts-belt'; import { getJWSPublicKey, isCodesignBuild } from '@trezor/env-utils'; import { createThunk } from '@suite-common/redux-utils'; import { NetworkSymbol, getCoingeckoId } from '@suite-common/wallet-config'; -import { Timeout } from '@trezor/type-utils'; +import { TimerId } from '@trezor/type-utils'; import { selectNetworkTokenDefinitions } from './tokenDefinitionsSelectors'; import { @@ -117,7 +117,7 @@ export const initTokenDefinitionsThunk = createThunk( }, ); -let tokenDefinitionsTimeout: Timeout | null = null; +let tokenDefinitionsTimeout: TimerId | null = null; export const periodicCheckTokenDefinitionsThunk = createThunk( `${TOKEN_DEFINITIONS_MODULE}/periodicCheckTokenDefinitionsThunk`, diff --git a/suite-common/wallet-core/src/blockchain/blockchainActions.ts b/suite-common/wallet-core/src/blockchain/blockchainActions.ts index 9a8d4a51dc6..140a928ed60 100644 --- a/suite-common/wallet-core/src/blockchain/blockchainActions.ts +++ b/suite-common/wallet-core/src/blockchain/blockchainActions.ts @@ -2,7 +2,7 @@ import { createAction } from '@reduxjs/toolkit'; import { NetworkSymbol } from '@suite-common/wallet-config'; import type { CustomBackend, NetworksFees } from '@suite-common/wallet-types'; -import type { Timeout } from '@trezor/type-utils'; +import type { TimerId } from '@trezor/type-utils'; export const BLOCKCHAIN_MODULE_PREFIX = '@common/wallet-core/blockchain'; @@ -22,7 +22,7 @@ const updateFee = createAction( const synced = createAction( `${BLOCKCHAIN_MODULE_PREFIX}/synced`, - (payload: { symbol: NetworkSymbol; timeout?: Timeout }) => ({ + (payload: { symbol: NetworkSymbol; timeout?: TimerId }) => ({ payload, }), ); diff --git a/suite-common/wallet-core/src/blockchain/blockchainThunks.ts b/suite-common/wallet-core/src/blockchain/blockchainThunks.ts index 53b60cabffa..3a9add02fe0 100644 --- a/suite-common/wallet-core/src/blockchain/blockchainThunks.ts +++ b/suite-common/wallet-core/src/blockchain/blockchainThunks.ts @@ -28,7 +28,7 @@ import TrezorConnect, { } from '@trezor/connect'; import { arrayDistinct, arrayToDictionary } from '@trezor/utils'; import type { Account, CustomBackend, NetworksFees } from '@suite-common/wallet-types'; -import type { Timeout } from '@trezor/type-utils'; +import type { TimerId } from '@trezor/type-utils'; import { notificationsActions } from '@suite-common/toast-notifications'; import { selectAccounts } from '../accounts/accountsReducer'; @@ -327,7 +327,7 @@ export const unsubscribeBlockchainThunk = createThunk( }, ); -const tryClearTimeout = (timeout?: Timeout) => { +const tryClearTimeout = (timeout?: TimerId) => { if (timeout) clearTimeout(timeout); }; diff --git a/suite-common/wallet-core/src/fiat-rates/fiatRatesThunks.ts b/suite-common/wallet-core/src/fiat-rates/fiatRatesThunks.ts index 22a09e75a93..7b656b99f0b 100644 --- a/suite-common/wallet-core/src/fiat-rates/fiatRatesThunks.ts +++ b/suite-common/wallet-core/src/fiat-rates/fiatRatesThunks.ts @@ -17,6 +17,7 @@ import { } from '@suite-common/wallet-utils'; import { getNetworkFeatures, NetworkSymbol } from '@suite-common/wallet-config'; import { selectIsSpecificCoinDefinitionKnown } from '@suite-common/token-definitions'; +import { TimerId } from '@trezor/type-utils'; import { FIAT_RATES_MODULE_PREFIX, REFETCH_INTERVAL } from './fiatRatesConstants'; import { selectTickersToBeUpdated, selectTransactionsWithMissingRates } from './fiatRatesSelectors'; @@ -191,7 +192,7 @@ export const fetchFiatRatesThunk = createThunk( }, ); -const ratesTimeouts: Record | null> = { +const ratesTimeouts: Record = { current: null, lastWeek: null, }; diff --git a/suite-common/wallet-core/src/stake/stakeThunks.ts b/suite-common/wallet-core/src/stake/stakeThunks.ts index 85f581fca26..936ecb8ad61 100644 --- a/suite-common/wallet-core/src/stake/stakeThunks.ts +++ b/suite-common/wallet-core/src/stake/stakeThunks.ts @@ -1,6 +1,6 @@ import { BigNumber } from '@trezor/utils/src/bigNumber'; import { createThunk } from '@suite-common/redux-utils'; -import { Timeout } from '@trezor/type-utils'; +import { TimerId } from '@trezor/type-utils'; import { getStakingSymbols } from '@suite-common/wallet-utils'; import { SupportedNetworkSymbol } from '@suite-common/wallet-types'; @@ -92,7 +92,7 @@ export const initStakeDataThunk = createThunk( }, ); -let stakeDataTimeout: Timeout | null = null; +let stakeDataTimeout: TimerId | null = null; export const periodicCheckStakeDataThunk = createThunk( `${STAKE_MODULE}/periodicCheckStakeDataThunk`, diff --git a/suite-common/wallet-types/src/backend.ts b/suite-common/wallet-types/src/backend.ts index 797f5371013..1a395709291 100644 --- a/suite-common/wallet-types/src/backend.ts +++ b/suite-common/wallet-types/src/backend.ts @@ -1,5 +1,5 @@ import { Explorer, NetworkSymbol, BackendType } from '@suite-common/wallet-config'; -import { Timeout } from '@trezor/type-utils'; +import { TimerId } from '@trezor/type-utils'; /** * @deprecated @@ -35,7 +35,7 @@ export interface Blockchain extends ConnectionStatus { blockHash: string; blockHeight: number; version: string; - syncTimeout?: Timeout; + syncTimeout?: TimerId; backends: BackendSettings; identityConnections?: { [identity: string]: ConnectionStatus; diff --git a/suite-native/app/src/hooks/useCoinEnablingInitialCheck.tsx b/suite-native/app/src/hooks/useCoinEnablingInitialCheck.tsx index b00382804e2..18ff46e3db4 100644 --- a/suite-native/app/src/hooks/useCoinEnablingInitialCheck.tsx +++ b/suite-native/app/src/hooks/useCoinEnablingInitialCheck.tsx @@ -18,6 +18,7 @@ import { StackNavigationProps, } from '@suite-native/navigation'; import { selectIsOnboardingFinished } from '@suite-native/settings'; +import { TimerId } from '@trezor/type-utils'; export const useCoinEnablingInitialCheck = () => { const dispatch = useDispatch(); @@ -38,7 +39,7 @@ export const useCoinEnablingInitialCheck = () => { useEffect(() => { if (shouldShowCoinEnablingInitFlow && canShowCoinEnablingInitFlow) { - let timeoutId: ReturnType; + let timeoutId: TimerId; //if btc only device, just run discovery for btc and do not show the UI if (hasBitcoinOnlyFirmware) { dispatch(setEnabledDiscoveryNetworkSymbols(['btc'])); diff --git a/suite-native/discovery/src/useIsDiscoveryDurationTooLong.tsx b/suite-native/discovery/src/useIsDiscoveryDurationTooLong.tsx index 8b3ac669929..f117802fa60 100644 --- a/suite-native/discovery/src/useIsDiscoveryDurationTooLong.tsx +++ b/suite-native/discovery/src/useIsDiscoveryDurationTooLong.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { selectHasDeviceDiscovery } from '@suite-common/wallet-core'; +import { IntervalId } from '@trezor/type-utils'; import { selectDiscoveryInfo } from './discoveryConfigSlice'; @@ -15,7 +16,7 @@ export const useIsDiscoveryDurationTooLong = () => { const [loadingTakesLongerThanExpected, setLoadingTakesLongerThanExpected] = useState(false); useEffect(() => { - let interval: ReturnType; + let interval: IntervalId; if (hasDiscovery && discoveryInfo?.startTimestamp) { interval = setInterval(() => { if ( diff --git a/suite-native/graph/src/components/Graph.tsx b/suite-native/graph/src/components/Graph.tsx index cd68d873bc9..122dc75945f 100644 --- a/suite-native/graph/src/components/Graph.tsx +++ b/suite-native/graph/src/components/Graph.tsx @@ -12,6 +12,7 @@ import { GroupedBalanceMovementEventPayload, } from '@suite-common/graph'; import { Translation } from '@suite-native/intl'; +import { TimerId } from '@trezor/type-utils'; import { getExtremaFromGraphPoints } from '../utils'; import { AxisLabel } from './AxisLabel'; @@ -91,7 +92,7 @@ export const Graph = ({ useEffect(() => { // We need to delay the loading a bit, because when switching between cached timeframes, it will break the // path interpolation animation. - let timeout: ReturnType; + let timeout: TimerId; if (loading) { timeout = setTimeout(() => { setDelayedLoading(true); diff --git a/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx b/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx index 774e7d1cda5..26f7e1c342a 100644 --- a/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx +++ b/suite-native/module-home/src/screens/HomeScreen/components/BiometricsBottomSheet.tsx @@ -17,6 +17,7 @@ import { } from '@suite-native/biometrics'; import { Translation } from '@suite-native/intl'; import { selectIsCoinEnablingInitFinished } from '@suite-native/discovery'; +import { TimerId } from '@trezor/type-utils'; const SHOW_TIMEOUT = 1500; @@ -53,7 +54,7 @@ export const BiometricsBottomSheet = () => { useEffect(() => { let isMounted = true; - let timerId: ReturnType; + let timerId: TimerId; const checkBiometrics = async () => { const isBiometricsAvailable = await getIsBiometricsFeatureAvailable(); diff --git a/suite-native/module-home/src/screens/HomeScreen/components/EnableViewOnlyBottomSheet.tsx b/suite-native/module-home/src/screens/HomeScreen/components/EnableViewOnlyBottomSheet.tsx index 2be4a96f35d..1043d20dd2c 100644 --- a/suite-native/module-home/src/screens/HomeScreen/components/EnableViewOnlyBottomSheet.tsx +++ b/suite-native/module-home/src/screens/HomeScreen/components/EnableViewOnlyBottomSheet.tsx @@ -22,6 +22,7 @@ import { setViewOnlyCancelationTimestamp, } from '@suite-native/settings'; import { useToast } from '@suite-native/toasts'; +import { TimerId } from '@trezor/type-utils'; import { DisconnectedTrezorSvg } from '../../../assets/DisconnectedTrezorSvg'; @@ -79,7 +80,7 @@ export const EnableViewOnlyBottomSheet = () => { useEffect(() => { let isMounted = true; - let timerId: ReturnType; + let timerId: TimerId; //show after a delay if (canBeShowed) {