diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 9492bd3d0..689b11783 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -154,17 +154,6 @@ "count": 2 } }, - "packages/solana-wallet-snap/snap.config.ts": { - "import-x/no-nodejs-modules": { - "count": 1 - }, - "n/no-process-env": { - "count": 1 - }, - "no-restricted-globals": { - "count": 17 - } - }, "packages/solana-wallet-snap/src/core/caching/useCache.test.ts": { "@typescript-eslint/explicit-function-return-type": { "count": 4 @@ -181,9 +170,6 @@ "packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts": { "@typescript-eslint/explicit-function-return-type": { "count": 5 - }, - "no-unused-private-class-members": { - "count": 1 } }, "packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts": { @@ -240,11 +226,6 @@ "count": 1 } }, - "packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.ts": { - "@typescript-eslint/no-unused-vars": { - "count": 1 - } - }, "packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.test.tsx": { "@typescript-eslint/explicit-function-return-type": { "count": 2 @@ -327,6 +308,16 @@ "count": 1 } }, + "packages/solana-wallet-snap/src/core/services/__mocks__/mockConnection.ts": { + "@typescript-eslint/explicit-function-return-type": { + "count": 9 + } + }, + "packages/solana-wallet-snap/src/core/services/__mocks__/scanResponses.ts": { + "@typescript-eslint/no-explicit-any": { + "count": 1 + } + }, "packages/solana-wallet-snap/src/core/services/analytics/AnalyticsService.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -448,16 +439,6 @@ "count": 1 } }, - "packages/solana-wallet-snap/src/core/services/mocks/mockConnection.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 9 - } - }, - "packages/solana-wallet-snap/src/core/services/mocks/scanResponses.ts": { - "@typescript-eslint/no-explicit-any": { - "count": 1 - } - }, "packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.test.ts": { "@typescript-eslint/no-explicit-any": { "count": 1 @@ -698,9 +679,6 @@ }, "no-restricted-syntax": { "count": 2 - }, - "no-unused-private-class-members": { - "count": 1 } }, "packages/solana-wallet-snap/src/core/services/transactions/utils/isSpam.ts": { @@ -1029,25 +1007,6 @@ "count": 2 } }, - "packages/solana-wallet-snap/src/core/utils/logMaybeSolanaError.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 1 - }, - "@typescript-eslint/no-explicit-any": { - "count": 1 - } - }, - "packages/solana-wallet-snap/src/core/utils/logger.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 3 - }, - "@typescript-eslint/no-explicit-any": { - "count": 10 - }, - "no-empty-function": { - "count": 5 - } - }, "packages/solana-wallet-snap/src/core/utils/parseOrigin.ts": { "@typescript-eslint/explicit-function-return-type": { "count": 1 diff --git a/packages/solana-wallet-snap/.env.sample b/packages/solana-wallet-snap/.env.sample index 6896527c2..9a689eec5 100644 --- a/packages/solana-wallet-snap/.env.sample +++ b/packages/solana-wallet-snap/.env.sample @@ -4,6 +4,11 @@ # - production before submitting a PR ENVIRONMENT= +# Log Level +# Possible Options: error, warn, info, debug, trace, silent +# Default: info +LOG_LEVEL= + # List of RPC URLs for each network. # The first one in the list is the primary one, the others are fallbacks. RPC_URL_MAINNET_LIST= diff --git a/packages/solana-wallet-snap/jest.setup.ts b/packages/solana-wallet-snap/jest.setup.ts index df1465e94..b0723960b 100644 --- a/packages/solana-wallet-snap/jest.setup.ts +++ b/packages/solana-wallet-snap/jest.setup.ts @@ -1,24 +1,7 @@ -import { jest } from '@jest/globals'; import BigNumber from 'bignumber.js'; import dotenv from 'dotenv'; -import logger from './src/core/utils/logger'; - dotenv.config(); // Lowest precision we ever go for: MicroLamports represented in Sol amount BigNumber.config({ EXPONENTIAL_AT: 16 }); - -// Mock the console methods -jest.spyOn(logger, 'log').mockImplementation(() => { - /* no-op */ -}); -jest.spyOn(logger, 'info').mockImplementation(() => { - /* no-op */ -}); -jest.spyOn(logger, 'warn').mockImplementation(() => { - /* no-op */ -}); -jest.spyOn(logger, 'error').mockImplementation(() => { - /* no-op */ -}); diff --git a/packages/solana-wallet-snap/package.json b/packages/solana-wallet-snap/package.json index 2e99a34bd..50660952f 100644 --- a/packages/solana-wallet-snap/package.json +++ b/packages/solana-wallet-snap/package.json @@ -56,6 +56,7 @@ "@metamask/key-tree": "^10.1.1", "@metamask/keyring-api": "^23.7.0", "@metamask/keyring-snap-sdk": "^9.2.1", + "@metamask/snap-networks-utils": "^1.0.0", "@metamask/snaps-cli": "^8.4.1", "@metamask/snaps-jest": "^10.2.0", "@metamask/snaps-sdk": "^11.2.0", diff --git a/packages/solana-wallet-snap/snap.config.ts b/packages/solana-wallet-snap/snap.config.ts index 4501facac..0d2268a0f 100644 --- a/packages/solana-wallet-snap/snap.config.ts +++ b/packages/solana-wallet-snap/snap.config.ts @@ -1,4 +1,4 @@ -/* eslint-disable n/no-process-env */ +/* eslint-disable import-x/no-nodejs-modules, no-restricted-globals -- Snap configuration executes in Node.js. */ import type { SnapConfig } from '@metamask/snaps-cli'; import * as dotenv from 'dotenv'; import { resolve } from 'path'; @@ -7,6 +7,7 @@ dotenv.config(); const environment = { ENVIRONMENT: process.env.ENVIRONMENT ?? '', + LOG_LEVEL: process.env.LOG_LEVEL ?? '', RPC_URL_MAINNET_LIST: process.env.RPC_URL_MAINNET_LIST ?? '', RPC_URL_DEVNET_LIST: process.env.RPC_URL_DEVNET_LIST ?? '', RPC_URL_TESTNET_LIST: process.env.RPC_URL_TESTNET_LIST ?? '', diff --git a/packages/solana-wallet-snap/snap.manifest.json b/packages/solana-wallet-snap/snap.manifest.json index 0632d4d28..744d35c2a 100644 --- a/packages/solana-wallet-snap/snap.manifest.json +++ b/packages/solana-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "YaPEFBNuMbbASorQCj4MFJKRSlqOjSOqJoOGUB9ET2I=", + "shasum": "dlsGUfU2sircQb9+jdv2u74wqp3t/Zn82O0JrY2lHAw=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts b/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts index f5e733c04..2e360f4ff 100644 --- a/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/InMemoryCache.ts @@ -1,8 +1,7 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { assert } from '@metamask/utils'; import type { Serializable } from '../serialization/types'; -import { createPrefixedLogger } from '../utils/logger'; -import type { ILogger } from '../utils/logger'; import type { ICache } from './ICache'; import type { CacheEntry } from './types'; @@ -15,10 +14,10 @@ import type { CacheEntry } from './types'; export class InMemoryCache implements ICache { readonly #cache: Map = new Map(); - public readonly logger: ILogger; + public readonly logger: Logger; - constructor(logger: ILogger) { - this.logger = createPrefixedLogger(logger, '[💾 InMemoryCache]'); + constructor(logger: Logger) { + this.logger = logger.withPrefix('[💾 InMemoryCache]'); } #validateTtlOrThrow(ttlMilliseconds?: number): void { diff --git a/packages/solana-wallet-snap/src/core/caching/StateCache.ts b/packages/solana-wallet-snap/src/core/caching/StateCache.ts index dbfbec1f4..b4806ecdb 100644 --- a/packages/solana-wallet-snap/src/core/caching/StateCache.ts +++ b/packages/solana-wallet-snap/src/core/caching/StateCache.ts @@ -1,8 +1,9 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { assert } from '@metamask/utils'; import type { Serializable } from '../serialization/types'; import type { IStateManager } from '../services/state/IStateManager'; -import type { ILogger } from '../utils/logger'; +import defaultLogger from '../utils/logger'; import type { ICache } from './ICache'; import type { CacheEntry } from './types'; @@ -74,11 +75,11 @@ export class StateCache implements ICache { public readonly prefix: CachePrefix; - public readonly logger: ILogger; + public readonly logger: Logger; constructor( state: IStateManager, - logger: ILogger = console, + logger: Logger = defaultLogger, prefix: CachePrefix = '__cache__default', ) { this.#state = state; diff --git a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts index a22f0fa79..f3f7295de 100644 --- a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts +++ b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.test.ts @@ -1,8 +1,9 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { ICache } from '../../caching/ICache'; import { InMemoryCache } from '../../caching/InMemoryCache'; import type { Serializable } from '../../serialization/types'; +import { mockLogger } from '../../services/__mocks__/logger'; import type { ConfigProvider } from '../../services/config'; -import { mockLogger } from '../../services/mocks/logger'; import { trackError } from '../../utils/errors'; import { MOCK_NFT_METADATA_RESPONSE_MAPPED } from './mocks/mockNftMetadataResponseMapped'; import { MOCK_NFT_METADATA_RESPONSE_RAW } from './mocks/mockNftMetadataResponseRaw'; @@ -38,12 +39,7 @@ describe('NftApiClient', () => { }), } as unknown as ConfigProvider; - client = new NftApiClient( - mockConfigProvider, - mockCache, - mockFetch, - mockLogger, - ); + client = new NftApiClient(mockConfigProvider, mockCache, mockFetch); }); describe('constructor', () => { @@ -61,13 +57,7 @@ describe('NftApiClient', () => { } as unknown as ConfigProvider; expect( - () => - new NftApiClient( - invalidConfigProvider, - mockCache, - mockFetch, - mockLogger, - ), + () => new NftApiClient(invalidConfigProvider, mockCache, mockFetch), ).toThrow('Invalid URL format'); }); }); diff --git a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts index dd4d819c4..376fc55d4 100644 --- a/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts +++ b/packages/solana-wallet-snap/src/core/clients/nft-api/NftApiClient.ts @@ -8,8 +8,6 @@ import type { Serializable } from '../../serialization/types'; import type { ConfigProvider } from '../../services/config'; import { buildUrl } from '../../utils/buildUrl'; import { trackError } from '../../utils/errors'; -import type { ILogger } from '../../utils/logger'; -import logger from '../../utils/logger'; import { UrlStruct } from '../../validation/structs'; import type { Balance, @@ -22,8 +20,6 @@ import type { export class NftApiClient { readonly #fetch: typeof globalThis.fetch; - readonly #logger: ILogger; - readonly #baseUrl: string; readonly #cache: ICache; @@ -37,14 +33,12 @@ export class NftApiClient { configProvider: ConfigProvider, _cache: ICache, _fetch: typeof globalThis.fetch = globalThis.fetch, - _logger: ILogger = logger, ) { const { baseUrl, cacheTtlsMilliseconds } = configProvider.get().nftApi; assert(baseUrl, UrlStruct); this.#fetch = _fetch; - this.#logger = _logger; this.#baseUrl = baseUrl; this.#cacheTtlsMilliseconds = cacheTtlsMilliseconds; diff --git a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts index ac5ec77e0..6661ea2dc 100644 --- a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts +++ b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { CaipAssetType } from '@metamask/keyring-api'; import { cloneDeep } from 'lodash'; @@ -6,8 +7,8 @@ import type { ICache } from '../../caching/ICache'; import { InMemoryCache } from '../../caching/InMemoryCache'; import { KnownCaip19Id } from '../../constants/solana'; import type { Serializable } from '../../serialization/types'; +import { mockLogger } from '../../services/__mocks__/logger'; import type { ConfigProvider } from '../../services/config'; -import { mockLogger } from '../../services/mocks/logger'; import { MOCK_EXCHANGE_RATES } from '../../test/mocks/price-api/exchange-rates'; import { MOCK_HISTORICAL_PRICES } from './mocks/historical-prices'; import { MOCK_SPOT_PRICES } from './mocks/spot-prices'; diff --git a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts index 70e592ad9..c63908ef5 100644 --- a/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts +++ b/packages/solana-wallet-snap/src/core/clients/price-api/PriceApiClient.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ import type { CaipAssetType } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { array, assert } from '@metamask/superstruct'; import { CaipAssetTypeStruct } from '@metamask/utils'; import { mapKeys } from 'lodash'; @@ -10,7 +11,6 @@ import { useCache } from '../../caching/useCache'; import type { Serializable } from '../../serialization/types'; import type { ConfigProvider } from '../../services/config'; import { buildUrl } from '../../utils/buildUrl'; -import type { ILogger } from '../../utils/logger'; import logger from '../../utils/logger'; import { UrlStruct } from '../../validation/structs'; import type { @@ -31,7 +31,7 @@ import { export class PriceApiClient { readonly #fetch: typeof globalThis.fetch; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #baseUrl: string; @@ -49,7 +49,7 @@ export class PriceApiClient { configProvider: ConfigProvider, _cache: ICache, _fetch: typeof globalThis.fetch = globalThis.fetch, - _logger: ILogger = logger, + _logger: Logger = logger, ) { const { baseUrl, chunkSize, cacheTtlsMilliseconds } = configProvider.get().priceApi; diff --git a/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.test.ts b/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.test.ts index 178805ed7..822a38303 100644 --- a/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.test.ts +++ b/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.test.ts @@ -1,6 +1,7 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { Network } from '../../constants/solana'; +import { mockLogger } from '../../services/__mocks__/logger'; import type { ConfigProvider } from '../../services/config'; -import { mockLogger } from '../../services/mocks/logger'; import { SecurityAlertsApiClient } from './SecurityAlertsApiClient'; describe('SecurityAlertsApiClient', () => { diff --git a/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.ts b/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.ts index 29c1034cd..3bc70108f 100644 --- a/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.ts +++ b/packages/solana-wallet-snap/src/core/clients/security-alerts-api/SecurityAlertsApiClient.ts @@ -1,9 +1,9 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; /* eslint-disable no-restricted-globals */ import bs58 from 'bs58'; import { Network } from '../../constants/solana'; import type { ConfigProvider } from '../../services/config'; -import type { ILogger } from '../../utils/logger'; import logger from '../../utils/logger'; import type { SecurityAlertSimulationValidationResponse } from './types'; @@ -17,14 +17,14 @@ const SCOPE_TO_CHAIN: Record = { export class SecurityAlertsApiClient { readonly #fetch: typeof globalThis.fetch; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #baseUrl: string; constructor( configProvider: ConfigProvider, _fetch: typeof globalThis.fetch = globalThis.fetch, - _logger: ILogger = logger, + _logger: Logger = logger, ) { const { baseUrl } = configProvider.get().securityAlertsApi; diff --git a/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.test.ts b/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.test.ts index c8e0acf6e..3929c5ae1 100644 --- a/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.test.ts +++ b/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.test.ts @@ -1,7 +1,8 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { TokenCaipAssetType } from '../../constants/solana'; import { KnownCaip19Id, Network } from '../../constants/solana'; +import { mockLogger } from '../../services/__mocks__/logger'; import type { ConfigProvider } from '../../services/config'; -import { mockLogger } from '../../services/mocks/logger'; import { tokenAddressToCaip19 } from '../../utils/tokenAddressToCaip19'; import { TokenApiClient } from './TokenApiClient'; diff --git a/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.ts b/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.ts index eab9a186d..4c6e416e1 100644 --- a/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.ts +++ b/packages/solana-wallet-snap/src/core/clients/token-api-client/TokenApiClient.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { FungibleAssetMetadata } from '@metamask/snaps-sdk'; import { array, assert } from '@metamask/superstruct'; import type { Infer } from '@metamask/superstruct'; @@ -7,7 +8,6 @@ import type { TokenCaipAssetType } from '../../constants/solana'; import { Network, TokenCaipAssetTypeStruct } from '../../constants/solana'; import type { ConfigProvider } from '../../services/config'; import { buildUrl } from '../../utils/buildUrl'; -import type { ILogger } from '../../utils/logger'; import logger from '../../utils/logger'; import { UrlStruct } from '../../validation/structs'; import type { TokenMetadataStruct } from './structs'; @@ -26,7 +26,7 @@ const DEFAULT_TOKEN_METADATA: FungibleAssetMetadata = { export class TokenApiClient { readonly #fetch: typeof globalThis.fetch; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #baseUrl: string; @@ -39,7 +39,7 @@ export class TokenApiClient { constructor( configProvider: ConfigProvider, _fetch: typeof globalThis.fetch = globalThis.fetch, - _logger: ILogger = logger, + _logger: Logger = logger, ) { this.#fetch = _fetch; this.#logger = _logger; diff --git a/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.test.ts b/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.test.ts index 94862d9b4..05de1a513 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.test.ts +++ b/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.test.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { InvalidParamsError } from '@metamask/snaps-sdk'; import type { JsonRpcRequest } from '@metamask/snaps-sdk'; import { getBase64Codec, getUtf8Codec, pipe } from '@solana/kit'; @@ -12,7 +13,6 @@ import { MOCK_SOLANA_KEYRING_ACCOUNT_0, MOCK_SOLANA_KEYRING_ACCOUNT_1, } from '../../test/mocks/solana-keyring-accounts'; -import type { ILogger } from '../../utils/logger'; import { ClientRequestHandler } from './ClientRequestHandler'; import { ClientRequestMethod } from './types'; @@ -40,7 +40,7 @@ describe('ClientRequestHandler', () => { let handler: ClientRequestHandler; let mockAccountsService: jest.Mocked; let mockWalletService: jest.Mocked; - let mockLogger: jest.Mocked; + let mockLogger: jest.Mocked; let sendService: jest.Mocked; let mockApproveTokenService: jest.Mocked; @@ -60,7 +60,8 @@ describe('ClientRequestHandler', () => { // Create mock logger mockLogger = { log: jest.fn(), - } as unknown as jest.Mocked; + withPrefix: jest.fn().mockReturnThis(), + } as unknown as jest.Mocked; sendService = { onAmountInput: jest.fn(), diff --git a/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.ts b/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.ts index bf56dd90c..89df73a61 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.ts +++ b/packages/solana-wallet-snap/src/core/handlers/onClientRequest/ClientRequestHandler.ts @@ -1,4 +1,5 @@ import { FeeType } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { InvalidParamsError, MethodNotFoundError } from '@metamask/snaps-sdk'; import type { Json, JsonRpcRequest } from '@metamask/snaps-sdk'; import { assert, create } from '@metamask/superstruct'; @@ -13,7 +14,6 @@ import { } from '@solana/kit'; import { METAMASK_ORIGIN, Networks } from '../../constants/solana'; -import type { Network } from '../../constants/solana'; import { FeeCalculator } from '../../fees'; import { fromTransactionToBase64String } from '../../sdk-extensions/codecs'; import type { AccountsService, ApproveTokenService } from '../../services'; @@ -21,8 +21,6 @@ import type { SendService } from '../../services/send/SendService'; import type { OnAddressInputRequest } from '../../services/send/types'; import type { WalletService } from '../../services/wallet/WalletService'; import { lamportsToSol } from '../../utils/conversion'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import { ClientRequestMethod } from './types'; import { ApproveCardAmountRequestStruct, @@ -55,7 +53,7 @@ export class ClientRequestHandler { readonly #walletService: WalletService; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #sendService: SendService; @@ -64,13 +62,13 @@ export class ClientRequestHandler { constructor( accountsService: AccountsService, walletService: WalletService, - logger: ILogger, + logger: Logger, sendService: SendService, approveTokenService: ApproveTokenService, ) { this.#accountsService = accountsService; this.#walletService = walletService; - this.#logger = createPrefixedLogger(logger, '[👋 ClientRequestHandler]'); + this.#logger = logger.withPrefix('[👋 ClientRequestHandler]'); this.#sendService = sendService; this.#approveTokenService = approveTokenService; } diff --git a/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx b/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx index dec3596c7..fcb5b46dc 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx +++ b/packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx @@ -11,13 +11,10 @@ import { getInterfaceContext, updateInterface, } from '../../../utils/interface'; -import baseLogger, { createPrefixedLogger } from '../../../utils/logger'; +import baseLogger from '../../../utils/logger'; export const refreshConfirmationEstimation: OnCronjobHandler = async () => { - const logger = createPrefixedLogger( - baseLogger, - '[refreshConfirmationEstimation]', - ); + const logger = baseLogger.withPrefix('[refreshConfirmationEstimation]'); logger.info(`Background event triggered`); diff --git a/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.test.ts b/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.test.ts index 2a8284d9c..10c3d286c 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.test.ts +++ b/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.test.ts @@ -2,6 +2,7 @@ import type { KeyringRequest } from '@metamask/keyring-api'; import { AccountCreationType, SolMethod } from '@metamask/keyring-api'; +import { Logger } from '@metamask/snap-networks-utils/logger'; import { InvalidParamsError, SnapError } from '@metamask/snaps-sdk'; import type { CaipAssetType, JsonRpcRequest } from '@metamask/snaps-sdk'; import { signature } from '@solana/kit'; @@ -240,18 +241,17 @@ describe('SolanaKeyring', () => { // so a single SnapError and a SnapError-of-SnapError look identical at // the message level. We instead detect double-wrapping via the log // pattern: each wrap site logs 'Error getting account'. - const errorLogSpy = jest.spyOn(logger, 'error'); + const errorLogSpy = jest.spyOn(Logger.prototype, 'error'); const caught = await keyring .getAccount(MOCK_SOLANA_KEYRING_ACCOUNT_1.id) .catch((error: unknown) => error); expect(caught).toBeInstanceOf(SnapError); - // The prefixed logger calls the underlying logger as - // (prefix, errorContext, message), so the human-readable message - // sits at index 2. + // Spying on the shared logger's prototype captures the derived prefixed + // logger. The message is the second argument to `error`. const errorLogCalls = errorLogSpy.mock.calls.filter( - (call) => call[2] === 'Error getting account', + (call) => call[1] === 'Error getting account', ); expect(errorLogCalls).toHaveLength(1); }); diff --git a/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.ts b/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.ts index 4feadc899..06de637d2 100644 --- a/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.ts +++ b/packages/solana-wallet-snap/src/core/handlers/onKeyringRequest/Keyring.ts @@ -24,6 +24,7 @@ import type { ExportedAccount, KeyringSnapRpc, } from '@metamask/keyring-api/v2'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { CaipAssetType, JsonRpcRequest } from '@metamask/snaps-sdk'; import { InvalidParamsError, @@ -71,8 +72,6 @@ import { listEntropySources, startTrace, } from '../../utils/interface'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import { Base58Struct, DeleteAccountStruct, @@ -105,7 +104,7 @@ type SubmitRequestResult = export class SolanaKeyring implements KeyringSnapRpc { readonly #state: IStateManager; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #transactionsService: TransactionsService; @@ -129,7 +128,7 @@ export class SolanaKeyring implements KeyringSnapRpc { keyringAccountMonitor, }: { state: IStateManager; - logger: ILogger; + logger: Logger; transactionsService: TransactionsService; assetsService: AssetsService; walletService: WalletService; @@ -137,7 +136,7 @@ export class SolanaKeyring implements KeyringSnapRpc { keyringAccountMonitor: KeyringAccountMonitor; }) { this.#state = state; - this.#logger = createPrefixedLogger(logger, '[🔑 Keyring]'); + this.#logger = logger.withPrefix('[🔑 Keyring]'); this.#transactionsService = transactionsService; this.#assetsService = assetsService; this.#walletService = walletService; diff --git a/packages/solana-wallet-snap/src/core/sdk-extensions/transaction-messages.test.ts b/packages/solana-wallet-snap/src/core/sdk-extensions/transaction-messages.test.ts index 834e01eaa..2bf1eac73 100644 --- a/packages/solana-wallet-snap/src/core/sdk-extensions/transaction-messages.test.ts +++ b/packages/solana-wallet-snap/src/core/sdk-extensions/transaction-messages.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { Rpc, SimulateTransactionApi } from '@solana/kit'; import { address, @@ -7,7 +8,7 @@ import { } from '@solana/kit'; import { Network } from '../constants/solana'; -import { createMockConnection } from '../services/mocks/mockConnection'; +import { createMockConnection } from '../services/__mocks__/mockConnection'; import { estimateAndOverrideComputeUnitLimit, isComputeUnitLimitInstruction, diff --git a/packages/solana-wallet-snap/src/core/services/__mocks__/logger.ts b/packages/solana-wallet-snap/src/core/services/__mocks__/logger.ts new file mode 100644 index 000000000..6c6f19503 --- /dev/null +++ b/packages/solana-wallet-snap/src/core/services/__mocks__/logger.ts @@ -0,0 +1,10 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; + +export const mockLogger = { + log: jest.fn(), + info: jest.fn(), + warn: jest.fn(), + error: jest.fn(), + debug: jest.fn(), + withPrefix: jest.fn().mockReturnThis(), +} as unknown as Logger; diff --git a/packages/solana-wallet-snap/src/core/services/mocks/mockConnection.ts b/packages/solana-wallet-snap/src/core/services/__mocks__/mockConnection.ts similarity index 100% rename from packages/solana-wallet-snap/src/core/services/mocks/mockConnection.ts rename to packages/solana-wallet-snap/src/core/services/__mocks__/mockConnection.ts diff --git a/packages/solana-wallet-snap/src/core/services/mocks/mockSolanaRpcResponses.ts b/packages/solana-wallet-snap/src/core/services/__mocks__/mockSolanaRpcResponses.ts similarity index 100% rename from packages/solana-wallet-snap/src/core/services/mocks/mockSolanaRpcResponses.ts rename to packages/solana-wallet-snap/src/core/services/__mocks__/mockSolanaRpcResponses.ts diff --git a/packages/solana-wallet-snap/src/core/services/mocks/scanResponses.ts b/packages/solana-wallet-snap/src/core/services/__mocks__/scanResponses.ts similarity index 100% rename from packages/solana-wallet-snap/src/core/services/mocks/scanResponses.ts rename to packages/solana-wallet-snap/src/core/services/__mocks__/scanResponses.ts diff --git a/packages/solana-wallet-snap/src/core/services/accounts/AccountsSynchronizer.ts b/packages/solana-wallet-snap/src/core/services/accounts/AccountsSynchronizer.ts index d214690c5..2563e4d49 100644 --- a/packages/solana-wallet-snap/src/core/services/accounts/AccountsSynchronizer.ts +++ b/packages/solana-wallet-snap/src/core/services/accounts/AccountsSynchronizer.ts @@ -1,6 +1,6 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; + import type { SolanaKeyringAccount } from '../../../entities'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { AssetsService } from '../assets/AssetsService'; import type { TransactionsService } from '../transactions'; import type { AccountsService } from './AccountsService'; @@ -12,18 +12,18 @@ export class AccountsSynchronizer { readonly #transactionsService: TransactionsService; - readonly #logger: ILogger; + readonly #logger: Logger; constructor( accountsService: AccountsService, assetsService: AssetsService, transactionsService: TransactionsService, - logger: ILogger, + logger: Logger, ) { this.#accountsService = accountsService; this.#assetsService = assetsService; this.#transactionsService = transactionsService; - this.#logger = createPrefixedLogger(logger, '[🔄 AccountsSynchronizer]'); + this.#logger = logger.withPrefix('[🔄 AccountsSynchronizer]'); } async synchronize(accounts?: SolanaKeyringAccount[]): Promise { diff --git a/packages/solana-wallet-snap/src/core/services/analytics/AnalyticsService.ts b/packages/solana-wallet-snap/src/core/services/analytics/AnalyticsService.ts index 71b4e6d9a..a50d0d5de 100644 --- a/packages/solana-wallet-snap/src/core/services/analytics/AnalyticsService.ts +++ b/packages/solana-wallet-snap/src/core/services/analytics/AnalyticsService.ts @@ -1,11 +1,11 @@ import type { Transaction } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { Json } from '@metamask/utils'; import type { SolanaKeyringAccount } from '../../../entities'; import type { Network, TransactionMetadata } from '../../constants/solana'; import { trackError } from '../../utils/errors'; -import type { ILogger } from '../../utils/logger'; -import logger, { createPrefixedLogger } from '../../utils/logger'; +import logger from '../../utils/logger'; import type { ScanStatus, SecurityAlertResponse, @@ -15,10 +15,10 @@ import type { * Service for tracking events related to transactions. */ export class AnalyticsService { - readonly #logger: ILogger; + readonly #logger: Logger; constructor(_logger = logger) { - this.#logger = createPrefixedLogger(_logger, '[📣 AnalyticsService]'); + this.#logger = _logger.withPrefix('[📣 AnalyticsService]'); } async #trackEvent( diff --git a/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.test.ts b/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.test.ts index 1e8818651..23af75817 100644 --- a/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.test.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { COMPUTE_BUDGET_PROGRAM_ADDRESS } from '@solana-program/compute-budget'; import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token'; /* eslint-disable @typescript-eslint/no-require-imports */ @@ -5,7 +6,6 @@ import { address as asAddress } from '@solana/kit'; import { Network } from '../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNT_0 } from '../../test/mocks/solana-keyring-accounts'; -import type { ILogger } from '../../utils/logger'; import type { TokenHelper } from '../assets/TokenHelper'; import type { SolanaConnection } from '../connection'; import { ApproveTokenService } from './ApproveTokenService'; @@ -26,7 +26,7 @@ describe('ApproveTokenService', () => { let service: ApproveTokenService; let mockConnection: jest.Mocked; let mockTokenHelper: jest.Mocked; - let mockLogger: jest.Mocked; + let mockLogger: jest.Mocked; const mockMint = asAddress('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); const mockDelegate = asAddress( @@ -56,7 +56,8 @@ describe('ApproveTokenService', () => { mockLogger = { log: jest.fn(), - } as unknown as jest.Mocked; + withPrefix: jest.fn().mockReturnThis(), + } as unknown as jest.Mocked; service = new ApproveTokenService( mockConnection, diff --git a/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.ts b/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.ts index fd2dd6fbd..4c89c82e3 100644 --- a/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.ts +++ b/packages/solana-wallet-snap/src/core/services/approve-token/ApproveTokenService.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction, @@ -30,8 +31,6 @@ import { import type { SolanaKeyringAccount } from '../../../entities'; import type { Network } from '../../constants/solana'; import { deriveSolanaKeypair } from '../../utils/deriveSolanaKeypair'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { TokenHelper } from '../assets/TokenHelper'; import type { SolanaConnection } from '../connection'; @@ -52,7 +51,7 @@ export class ApproveTokenService { readonly #tokenHelper: TokenHelper; - readonly #logger: ILogger; + readonly #logger: Logger; /** * The transaction built here consumes up to ~10,000 compute units when approving @@ -66,11 +65,11 @@ export class ApproveTokenService { constructor( connection: SolanaConnection, tokenHelper: TokenHelper, - logger: ILogger, + logger: Logger, ) { this.#connection = connection; this.#tokenHelper = tokenHelper; - this.#logger = createPrefixedLogger(logger, '[🔐 ApproveTokenService]'); + this.#logger = logger.withPrefix('[🔐 ApproveTokenService]'); } /** diff --git a/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts b/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts index 3bb5fca22..cadfa4956 100644 --- a/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/assets/AssetsService.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { KeyringEvent } from '@metamask/keyring-api'; import { emitSnapKeyringEvent } from '@metamask/keyring-snap-sdk'; import { cloneDeep } from 'lodash'; @@ -17,12 +18,12 @@ import { SOLANA_MOCK_TOKEN_METADATA, } from '../../test/mocks/asset-entities'; import { MOCK_SOLANA_KEYRING_ACCOUNT_0 } from '../../test/mocks/solana-keyring-accounts'; +import { mockLogger } from '../__mocks__/logger'; +import { createMockConnection } from '../__mocks__/mockConnection'; +import { MOCK_SOLANA_RPC_GET_TOKEN_ACCOUNTS_BY_OWNER_RESPONSE } from '../__mocks__/mockSolanaRpcResponses'; import type { AccountsService } from '../accounts/AccountsService'; import type { ConfigProvider } from '../config'; import type { SolanaConnection } from '../connection'; -import { mockLogger } from '../mocks/logger'; -import { createMockConnection } from '../mocks/mockConnection'; -import { MOCK_SOLANA_RPC_GET_TOKEN_ACCOUNTS_BY_OWNER_RESPONSE } from '../mocks/mockSolanaRpcResponses'; import type { TokenPricesService } from '../token-prices/TokenPrices'; import type { AssetsRepository } from './AssetsRepository'; import { AssetsService } from './AssetsService'; diff --git a/packages/solana-wallet-snap/src/core/services/assets/AssetsService.ts b/packages/solana-wallet-snap/src/core/services/assets/AssetsService.ts index 7a58bfeb0..aac6b3ae0 100644 --- a/packages/solana-wallet-snap/src/core/services/assets/AssetsService.ts +++ b/packages/solana-wallet-snap/src/core/services/assets/AssetsService.ts @@ -7,6 +7,7 @@ import type { Balance, } from '@metamask/keyring-api'; import { emitSnapKeyringEvent } from '@metamask/keyring-snap-sdk'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { FungibleAssetMarketData, FungibleAssetMetadata, @@ -43,8 +44,6 @@ import type { TokenAccountInfoWithJsonData } from '../../sdk-extensions/rpc-api' import type { Serializable } from '../../serialization/types'; import { fromTokenUnits } from '../../utils/fromTokenUnit'; import { getNetworkFromToken } from '../../utils/getNetworkFromToken'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import { tokenAddressToCaip19 } from '../../utils/tokenAddressToCaip19'; import type { AccountsService } from '../accounts/AccountsService'; import type { ConfigProvider } from '../config'; @@ -64,7 +63,7 @@ type TokenAccountWithMetadata = { } & Serializable; export class AssetsService { - readonly #logger: ILogger; + readonly #logger: Logger; readonly #connection: SolanaConnection; @@ -98,7 +97,7 @@ export class AssetsService { nftApiClient, }: { connection: SolanaConnection; - logger: ILogger; + logger: Logger; configProvider: ConfigProvider; assetsRepository: AssetsRepository; accountsService: AccountsService; @@ -107,7 +106,7 @@ export class AssetsService { cache: ICache; nftApiClient: NftApiClient; }) { - this.#logger = createPrefixedLogger(logger, '[🪙 AssetsService]'); + this.#logger = logger.withPrefix('[🪙 AssetsService]'); this.#connection = connection; this.#configProvider = configProvider; this.#assetsRepository = assetsRepository; diff --git a/packages/solana-wallet-snap/src/core/services/assets/TokenHelper.test.ts b/packages/solana-wallet-snap/src/core/services/assets/TokenHelper.test.ts index 3fc5ba308..4d0898391 100644 --- a/packages/solana-wallet-snap/src/core/services/assets/TokenHelper.test.ts +++ b/packages/solana-wallet-snap/src/core/services/assets/TokenHelper.test.ts @@ -1,12 +1,13 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { Mint } from '@solana-program/token-2022'; import type { Account, Address } from '@solana/kit'; import { lamports } from '@solana/kit'; import { cloneDeep } from 'lodash'; import { Network } from '../../constants/solana'; +import { createMockConnection } from '../__mocks__/mockConnection'; +import { MOCK_MINT_ACCOUNT } from '../__mocks__/mockSolanaRpcResponses'; import type { SolanaConnection } from '../connection/SolanaConnection'; -import { createMockConnection } from '../mocks/mockConnection'; -import { MOCK_MINT_ACCOUNT } from '../mocks/mockSolanaRpcResponses'; import { TokenHelper } from './TokenHelper'; describe('TokenHelper', () => { diff --git a/packages/solana-wallet-snap/src/core/services/config/ConfigProvider.ts b/packages/solana-wallet-snap/src/core/services/config/ConfigProvider.ts index 465100f1b..a77f1e587 100644 --- a/packages/solana-wallet-snap/src/core/services/config/ConfigProvider.ts +++ b/packages/solana-wallet-snap/src/core/services/config/ConfigProvider.ts @@ -1,3 +1,4 @@ +import { LogLevel } from '@metamask/snap-networks-utils/logger'; /* eslint-disable no-restricted-globals */ import type { Infer } from '@metamask/superstruct'; import { @@ -37,6 +38,7 @@ const CommaSeparatedListOfStringsStruct = coerce( const EnvStruct = object({ ENVIRONMENT: enums(['local', 'test', 'production']), + LOG_LEVEL: enums(Object.values(LogLevel)), RPC_URL_MAINNET_LIST: CommaSeparatedListOfUrlsStruct, RPC_URL_DEVNET_LIST: CommaSeparatedListOfUrlsStruct, RPC_URL_TESTNET_LIST: CommaSeparatedListOfUrlsStruct, @@ -63,6 +65,7 @@ export type NetworkConfig = (typeof Networks)[Network] & { export type Config = { environment: string; + logLevel: LogLevel; networks: NetworkConfig[]; explorerBaseUrl: string; priceApi: { @@ -125,6 +128,7 @@ export class ConfigProvider { #parseEnvironment() { const rawEnvironment = { ENVIRONMENT: process.env.ENVIRONMENT, + LOG_LEVEL: process.env.LOG_LEVEL, RPC_URL_MAINNET_LIST: process.env.RPC_URL_MAINNET_LIST, RPC_URL_DEVNET_LIST: process.env.RPC_URL_DEVNET_LIST, RPC_URL_TESTNET_LIST: process.env.RPC_URL_TESTNET_LIST, @@ -150,6 +154,7 @@ export class ConfigProvider { #buildConfig(environment: Env): Config { return { environment: environment.ENVIRONMENT, + logLevel: environment.LOG_LEVEL, networks: [ { ...Networks[Network.Mainnet], diff --git a/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts b/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts index 1f6a0487b..580196c2d 100644 --- a/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts +++ b/packages/solana-wallet-snap/src/core/services/connection/SolanaConnection.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ /* eslint-disable @typescript-eslint/no-require-imports */ import { fetchJsonParsedAccount } from '@solana/kit'; @@ -6,12 +7,12 @@ import type { ICache } from '../../caching/ICache'; import { InMemoryCache } from '../../caching/InMemoryCache'; import { KnownCaip19Id, Network } from '../../constants/solana'; import type { Serializable } from '../../serialization/types'; -import type { ConfigProvider } from '../config'; -import { mockLogger } from '../mocks/logger'; +import { mockLogger } from '../__mocks__/logger'; import { MOCK_JSON_PARSED_ACCOUNT, MOCK_MINT_ACCOUNT, -} from '../mocks/mockSolanaRpcResponses'; +} from '../__mocks__/mockSolanaRpcResponses'; +import type { ConfigProvider } from '../config'; import { SolanaConnection } from './SolanaConnection'; jest.mock('@solana/kit', () => ({ diff --git a/packages/solana-wallet-snap/src/core/services/mocks/logger.ts b/packages/solana-wallet-snap/src/core/services/mocks/logger.ts deleted file mode 100644 index 3fd9aa340..000000000 --- a/packages/solana-wallet-snap/src/core/services/mocks/logger.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ILogger } from '../../utils/logger'; - -export const mockLogger = { - log: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - debug: jest.fn(), -} as unknown as ILogger; diff --git a/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.test.ts b/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.test.ts index 0c32394fd..7392c2267 100644 --- a/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { expect } from '@jest/globals'; import { resolveDomain, @@ -6,8 +7,8 @@ import { import type { Address } from '@solana/kit'; import { Network } from '../../constants/solana'; +import { mockLogger } from '../__mocks__/logger'; import type { SolanaConnection } from '../connection/SolanaConnection'; -import { mockLogger } from '../mocks/logger'; import { NameResolutionService } from './NameResolutionService'; jest.mock('@solana-name-service/sns-sdk-kit'); diff --git a/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.ts b/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.ts index 7312f80e3..07dec74f0 100644 --- a/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.ts +++ b/packages/solana-wallet-snap/src/core/services/name-resolution/NameResolutionService.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { resolveDomain, getPrimaryDomain, @@ -6,17 +7,16 @@ import type { Address } from '@solana/kit'; import { address as asAddress } from '@solana/kit'; import type { Network } from '../../constants/solana'; -import type { ILogger } from '../../utils/logger'; import type { SolanaConnection } from '../connection/SolanaConnection'; export class NameResolutionService { readonly #connection: SolanaConnection; - readonly #logger: ILogger; + readonly #logger: Logger; tld = '.sol'; - constructor(connection: SolanaConnection, logger: ILogger) { + constructor(connection: SolanaConnection, logger: Logger) { this.#connection = connection; this.#logger = logger; } diff --git a/packages/solana-wallet-snap/src/core/services/nft/NftService.test.ts b/packages/solana-wallet-snap/src/core/services/nft/NftService.test.ts index 28bca9f92..083bb923f 100644 --- a/packages/solana-wallet-snap/src/core/services/nft/NftService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/nft/NftService.test.ts @@ -1,5 +1,6 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ +import { mockLogger } from '../__mocks__/logger'; import type { SolanaConnection } from '../connection'; -import { mockLogger } from '../mocks/logger'; import { NftService } from './NftService'; describe.skip('NftService', () => { diff --git a/packages/solana-wallet-snap/src/core/services/nft/NftService.ts b/packages/solana-wallet-snap/src/core/services/nft/NftService.ts index 33417d9db..318bb3cf0 100644 --- a/packages/solana-wallet-snap/src/core/services/nft/NftService.ts +++ b/packages/solana-wallet-snap/src/core/services/nft/NftService.ts @@ -1,13 +1,14 @@ -import type { ILogger } from '../../utils/logger'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; + import logger from '../../utils/logger'; import type { SolanaConnection } from '../connection'; export class NftService { readonly #connection: SolanaConnection; - readonly #logger: ILogger; + readonly #logger: Logger; - constructor(connection: SolanaConnection, _logger: ILogger = logger) { + constructor(connection: SolanaConnection, _logger: Logger = logger) { this.#connection = connection; this.#logger = _logger; } diff --git a/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.test.ts b/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.test.ts index 4f618d16d..d035a8a00 100644 --- a/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.test.ts +++ b/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.test.ts @@ -1,10 +1,11 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { SYSTEM_PROGRAM_ADDRESS } from '@solana-program/system'; import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token'; import { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022'; import { Network } from '../../constants/solana'; +import { mockLogger } from '../__mocks__/logger'; import type { SolanaConnection } from '../connection'; -import { mockLogger } from '../mocks/logger'; import { RecipientClassifier } from './RecipientClassifier'; // Mock the @solana/kit functions diff --git a/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.ts b/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.ts index c37072339..12f6ae05c 100644 --- a/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.ts +++ b/packages/solana-wallet-snap/src/core/services/send/RecipientClassifier.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { SYSTEM_PROGRAM_ADDRESS } from '@solana-program/system'; import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token'; import { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022'; @@ -6,8 +7,6 @@ import { assertAccountExists } from '@solana/kit'; import { get } from 'lodash'; import type { Network } from '../../constants/solana'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { SolanaConnection } from '../connection'; export type RecipientClassification = @@ -37,11 +36,11 @@ export type RecipientClassification = export class RecipientClassifier { readonly #connection: SolanaConnection; - readonly #logger: ILogger; + readonly #logger: Logger; - constructor(connection: SolanaConnection, logger: ILogger) { + constructor(connection: SolanaConnection, logger: Logger) { this.#connection = connection; - this.#logger = createPrefixedLogger(logger, '[👀 RecipientClassifier]'); + this.#logger = logger.withPrefix('[👀 RecipientClassifier]'); } async classify( diff --git a/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts b/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts index 7ef7660cc..30df99431 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendService.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { SolMethod } from '@metamask/keyring-api'; import { lamports } from '@solana/kit'; @@ -18,10 +19,10 @@ import { MOCK_SOLANA_KEYRING_ACCOUNT_0, MOCK_SOLANA_KEYRING_ACCOUNT_1, } from '../../test/mocks/solana-keyring-accounts'; +import { mockLogger } from '../__mocks__/logger'; +import { createMockConnection } from '../__mocks__/mockConnection'; import type { AssetsService } from '../assets'; import type { SolanaConnection } from '../connection'; -import { mockLogger } from '../mocks/logger'; -import { createMockConnection } from '../mocks/mockConnection'; import type { RecipientClassifier } from './RecipientClassifier'; import { SendService } from './SendService'; import type { SendSolBuilder } from './SendSolBuilder'; diff --git a/packages/solana-wallet-snap/src/core/services/send/SendService.ts b/packages/solana-wallet-snap/src/core/services/send/SendService.ts index 242ba86cc..240467495 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendService.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendService.ts @@ -1,5 +1,6 @@ import type { KeyringRequest } from '@metamask/keyring-api'; import { SolMethod } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { Json } from '@metamask/snaps-sdk'; import { Duration, parseCaipAssetType } from '@metamask/utils'; import { address as asAddress, compileTransaction } from '@solana/kit'; @@ -13,8 +14,6 @@ import type { SolanaKeyring } from '../../handlers/onKeyringRequest/Keyring'; import { fromTransactionToBase64String } from '../../sdk-extensions/codecs'; import type { Serializable } from '../../serialization/types'; import { solToLamports } from '../../utils/conversion'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { AssetsService } from '../assets'; import type { SolanaConnection } from '../connection'; import type { RecipientClassifier } from './RecipientClassifier'; @@ -33,7 +32,7 @@ export class SendService { readonly #keyring: SolanaKeyring; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #cache: ICache; @@ -52,7 +51,7 @@ export class SendService { constructor( connection: SolanaConnection, keyring: SolanaKeyring, - logger: ILogger, + logger: Logger, cache: ICache, recipientClassifier: RecipientClassifier, sendSolBuilder: SendSolBuilder, @@ -62,7 +61,7 @@ export class SendService { this.#connection = connection; this.#keyring = keyring; this.#cache = cache; - this.#logger = createPrefixedLogger(logger, '[📬 SendService]'); + this.#logger = logger.withPrefix('[📬 SendService]'); this.#recipientClassifier = recipientClassifier; this.#sendSolBuilder = sendSolBuilder; this.#sendSplTokenBuilder = sendSplTokenBuilder; diff --git a/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.test.ts b/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.test.ts index af461ceb7..b61b0af43 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.test.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.test.ts @@ -1,10 +1,11 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { address } from '@solana/kit'; import BigNumber from 'bignumber.js'; import { Network } from '../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNTS } from '../../test/mocks/solana-keyring-accounts'; import logger from '../../utils/logger'; -import { createMockConnection } from '../mocks/mockConnection'; +import { createMockConnection } from '../__mocks__/mockConnection'; import { SendSolBuilder } from './SendSolBuilder'; describe('SendSolBuilder', () => { diff --git a/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.ts b/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.ts index 66f9a5e5d..bf1553285 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendSolBuilder.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { getSetComputeUnitLimitInstruction, getSetComputeUnitPriceInstruction, @@ -16,7 +17,6 @@ import { } from '@solana/kit'; import { solToLamports } from '../../utils/conversion'; -import type { ILogger } from '../../utils/logger'; import type { SolanaConnection } from '../connection'; import type { BuildSendTransactionParams, @@ -29,14 +29,14 @@ import type { export class SendSolBuilder implements ISendTransactionBuilder { readonly #connection: SolanaConnection; - readonly #logger: ILogger; + readonly #logger: Logger; // The send SOL transaction has a predictable compute unit consumption of 450. readonly #computeUnitLimit = 450; readonly #computeUnitPriceMicroLamportsPerComputeUnit = 10000n; - constructor(connection: SolanaConnection, logger: ILogger) { + constructor(connection: SolanaConnection, logger: Logger) { this.#connection = connection; this.#logger = logger; } diff --git a/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.test.ts b/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.test.ts index 87034f9ff..7dff1e102 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.test.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { Mint } from '@solana-program/token-2022'; /* eslint-disable @typescript-eslint/no-require-imports */ import { address, lamports } from '@solana/kit'; @@ -9,10 +10,10 @@ import type { RecipientClassifier } from '..'; import { TokenHelper } from '..'; import { Network } from '../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNTS } from '../../test/mocks/solana-keyring-accounts'; +import { mockLogger } from '../__mocks__/logger'; +import { createMockConnection } from '../__mocks__/mockConnection'; +import { MOCK_MINT_ACCOUNT } from '../__mocks__/mockSolanaRpcResponses'; import type { SolanaConnection } from '../connection/SolanaConnection'; -import { mockLogger } from '../mocks/logger'; -import { createMockConnection } from '../mocks/mockConnection'; -import { MOCK_MINT_ACCOUNT } from '../mocks/mockSolanaRpcResponses'; import { RecipientUnsupportedError } from './errors'; import { SendSplTokenBuilder } from './SendSplTokenBuilder'; diff --git a/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.ts b/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.ts index 833dbbfd0..545d61b1d 100644 --- a/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.ts +++ b/packages/solana-wallet-snap/src/core/services/send/SendSplTokenBuilder.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { assert } from '@metamask/utils'; import { getSetComputeUnitLimitInstruction, @@ -27,8 +28,6 @@ import type { Address } from '@solana/kit'; import type { TokenHelper } from '..'; import { deriveSolanaKeypair } from '../../utils/deriveSolanaKeypair'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { SolanaConnection } from '../connection'; import { RecipientTokenAccountMintMismatchError, @@ -47,7 +46,7 @@ export class SendSplTokenBuilder implements ISendTransactionBuilder { readonly #connection: SolanaConnection; - readonly #logger: ILogger; + readonly #logger: Logger; /** * The transaction built here consumes up to ~30,000 compute units when just transferring @@ -62,12 +61,12 @@ export class SendSplTokenBuilder implements ISendTransactionBuilder { tokenHelper: TokenHelper, recipientClassifier: RecipientClassifier, connection: SolanaConnection, - logger: ILogger, + logger: Logger, ) { this.#tokenHelper = tokenHelper; this.#recipientClassifier = recipientClassifier; this.#connection = connection; - this.#logger = createPrefixedLogger(logger, '[📩 SendSplTokenBuilder]'); + this.#logger = logger.withPrefix('[📩 SendSplTokenBuilder]'); } async buildTransactionMessage( diff --git a/packages/solana-wallet-snap/src/core/services/signer/Signer.test.ts b/packages/solana-wallet-snap/src/core/services/signer/Signer.test.ts index 3ed04dbe1..59d3f74f5 100644 --- a/packages/solana-wallet-snap/src/core/services/signer/Signer.test.ts +++ b/packages/solana-wallet-snap/src/core/services/signer/Signer.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { getSignatureFromTransaction, isTransactionMessageWithBlockhashLifetime, @@ -12,8 +13,8 @@ import { } from '../../sdk-extensions/transaction-messages'; import { deriveSolanaKeypairMock } from '../../test/mocks/utils/deriveSolanaKeypair'; import logger from '../../utils/logger'; +import { createMockConnection } from '../__mocks__/mockConnection'; import type { SolanaConnection } from '../connection'; -import { createMockConnection } from '../mocks/mockConnection'; import { MOCK_SIGN_SCENARIO_JUPITERZ_WITH_DIFFERENT_FEE_PAYER } from './mocks/jupiterzWithDifferentFeePayer'; import { MOCK_EXECUTION_SCENARIOS } from './mocks/scenarios'; import { Signer } from './Signer'; diff --git a/packages/solana-wallet-snap/src/core/services/signer/Signer.ts b/packages/solana-wallet-snap/src/core/services/signer/Signer.ts index 937ae15a5..a94dd3600 100644 --- a/packages/solana-wallet-snap/src/core/services/signer/Signer.ts +++ b/packages/solana-wallet-snap/src/core/services/signer/Signer.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { Infer } from '@metamask/superstruct'; import type { BaseTransactionMessage, @@ -30,8 +31,6 @@ import { setTransactionMessageLifetimeUsingBlockhashIfMissing, } from '../../sdk-extensions/transaction-messages'; import { deriveSolanaKeypair } from '../../utils/deriveSolanaKeypair'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { Base64Struct } from '../../validation/structs'; import type { SolanaConnection } from '../connection'; @@ -41,13 +40,13 @@ import type { SolanaConnection } from '../connection'; export class Signer { readonly #connection: SolanaConnection; - readonly #logger: ILogger; + readonly #logger: Logger; static readonly defaultComputeUnitPriceInMicroLamportsPerComputeUnit = 10000n; - constructor(connection: SolanaConnection, logger: ILogger) { + constructor(connection: SolanaConnection, logger: Logger) { this.#connection = connection; - this.#logger = createPrefixedLogger(logger, '[🖋️ Signer]'); + this.#logger = logger.withPrefix('[🖋️ Signer]'); } /** diff --git a/packages/solana-wallet-snap/src/core/services/state/State.test.ts b/packages/solana-wallet-snap/src/core/services/state/State.test.ts index 724758dfe..44c701aba 100644 --- a/packages/solana-wallet-snap/src/core/services/state/State.test.ts +++ b/packages/solana-wallet-snap/src/core/services/state/State.test.ts @@ -1,9 +1,10 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ /* eslint-disable jest/prefer-strict-equal */ import BigNumber from 'bignumber.js'; import { EventEmitter } from '../../../infrastructure/event-emitter/EventEmitter'; -import { mockLogger } from '../mocks/logger'; +import { mockLogger } from '../__mocks__/logger'; import { State } from './State'; const snap = { diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.test.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.test.ts index 578e2dca6..3aff64bff 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.test.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { TransactionType } from '@metamask/keyring-api'; @@ -17,11 +18,11 @@ import type { import { KnownCaip19Id, Network } from '../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNTS } from '../../test/mocks/solana-keyring-accounts'; import { trackError } from '../../utils/errors'; +import { mockLogger } from '../__mocks__/logger'; import type { AccountsSynchronizer } from '../accounts'; import type { AccountsService } from '../accounts/AccountsService'; import type { AssetsService, TokenHelper } from '../assets'; import type { ConfigProvider } from '../config'; -import { mockLogger } from '../mocks/logger'; import type { TransactionsService } from '../transactions'; import { KeyringAccountMonitor } from './KeyringAccountMonitor'; import type { SubscriptionService } from './SubscriptionService'; diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.ts index 38eb4c325..71a31f071 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/KeyringAccountMonitor.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { assert, number, string } from '@metamask/superstruct'; import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token'; import { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022'; @@ -16,8 +17,6 @@ import type { Network } from '../../constants/solana'; import { SolanaCaip19Tokens } from '../../constants/solana'; import { trackError } from '../../utils/errors'; import { fromTokenUnits } from '../../utils/fromTokenUnit'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import { tokenAddressToCaip19 } from '../../utils/tokenAddressToCaip19'; import type { AccountsSynchronizer } from '../accounts'; import type { AccountsService } from '../accounts/AccountsService'; @@ -52,7 +51,7 @@ export class KeyringAccountMonitor { readonly #configProvider: ConfigProvider; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #tokenProgramsAddresses = [ TOKEN_PROGRAM_ADDRESS, @@ -67,7 +66,7 @@ export class KeyringAccountMonitor { accountsSynchronizer: AccountsSynchronizer, tokenHelper: TokenHelper, configProvider: ConfigProvider, - logger: ILogger, + logger: Logger, ) { this.#subscriptionService = subscriptionService; this.#accountService = accountService; @@ -76,7 +75,7 @@ export class KeyringAccountMonitor { this.#accountsSynchronizer = accountsSynchronizer; this.#tokenHelper = tokenHelper; this.#configProvider = configProvider; - this.#logger = createPrefixedLogger(logger, '[🗝️ KeyringAccountMonitor]'); + this.#logger = logger.withPrefix('[🗝️ KeyringAccountMonitor]'); this.#bindHandlers(); } diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/MonitoredAccountsInitializer.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/MonitoredAccountsInitializer.ts index d9de8b34f..6c5857dbd 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/MonitoredAccountsInitializer.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/MonitoredAccountsInitializer.ts @@ -1,6 +1,6 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; + import type { EventEmitter } from '../../../infrastructure/event-emitter'; -import type { ILogger } from '../../utils/logger'; -import { createPrefixedLogger } from '../../utils/logger'; import type { AccountsService } from '../accounts/AccountsService'; import type { KeyringAccountMonitor } from './KeyringAccountMonitor'; @@ -15,21 +15,18 @@ export class MonitoredAccountsInitializer { readonly #eventEmitter: EventEmitter; - readonly #logger: ILogger; + readonly #logger: Logger; constructor( accountsService: AccountsService, keyringAccountMonitor: KeyringAccountMonitor, eventEmitter: EventEmitter, - logger: ILogger, + logger: Logger, ) { this.#accountsService = accountsService; this.#keyringAccountMonitor = keyringAccountMonitor; this.#eventEmitter = eventEmitter; - this.#logger = createPrefixedLogger( - logger, - '[🥾 MonitoredAccountsInitializer]', - ); + this.#logger = logger.withPrefix('[🥾 MonitoredAccountsInitializer]'); this.#bindHandlers(); } diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.test.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.test.ts index 0e7c3abf7..1a2d82335 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.test.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { Transaction } from '@metamask/keyring-api'; @@ -10,11 +11,11 @@ import type { import { Network } from '../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNTS } from '../../test/mocks/solana-keyring-accounts'; import { trackError } from '../../utils/errors'; +import { mockLogger } from '../__mocks__/logger'; import type { AccountsService } from '../accounts'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { ConfigProvider } from '../config'; import type { SolanaConnection } from '../connection'; -import { mockLogger } from '../mocks/logger'; import type { TransactionsService } from '../transactions'; import { SignatureMonitor } from './SignatureMonitor'; import type { SubscriptionService } from './SubscriptionService'; diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.ts index d0f6df3a6..5439af593 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/SignatureMonitor.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import { assert, string } from '@metamask/superstruct'; import { Duration } from '@metamask/utils'; import { signature as asSignature } from '@solana/kit'; @@ -12,8 +13,6 @@ import type { } from '../../../entities'; import type { Network } from '../../constants/solana'; import { trackError } from '../../utils/errors'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { AccountsService } from '../accounts/AccountsService'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { ConfigProvider } from '../config'; @@ -35,7 +34,7 @@ export class SignatureMonitor { readonly #configProvider: ConfigProvider; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #pendingSubscriptions: Map = new Map(); // subscriptionId -> subscriptionRequest @@ -54,7 +53,7 @@ export class SignatureMonitor { analyticsService: AnalyticsService, connection: SolanaConnection, configProvider: ConfigProvider, - logger: ILogger, + logger: Logger, ) { this.#subscriptionService = subscriptionService; this.#accountService = accountService; @@ -62,7 +61,7 @@ export class SignatureMonitor { this.#analyticsService = analyticsService; this.#connection = connection; this.#configProvider = configProvider; - this.#logger = createPrefixedLogger(logger, '[✍️ SignatureMonitor]'); + this.#logger = logger.withPrefix('[✍️ SignatureMonitor]'); this.#bindHandlers(); } diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.test.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.test.ts index 1e09bef8d..724c946ff 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { WebSocketMessage } from '@metamask/snaps-sdk'; import { Duration } from '@metamask/utils'; @@ -11,7 +12,7 @@ import type { } from '../../../entities'; import { EventEmitter } from '../../../infrastructure'; import { Network } from '../../constants/solana'; -import { mockLogger } from '../mocks/logger'; +import { mockLogger } from '../__mocks__/logger'; import type { SubscriptionRepository } from './SubscriptionRepository'; import { SubscriptionService } from './SubscriptionService'; import type { WebSocketConnectionService } from './WebSocketConnectionService'; diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.ts index 19105126b..b24a6e94c 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/SubscriptionService.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { WebSocketEvent } from '@metamask/snaps-sdk'; import { isJsonRpcFailure } from '@metamask/utils'; @@ -17,8 +18,6 @@ import type { import { subscribeMethodToUnsubscribeMethod } from '../../../entities'; import type { EventEmitter } from '../../../infrastructure'; import type { Network } from '../../constants/solana'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import { SUPPORTED_NETWORKS } from '../config/ConfigProvider'; import { parseWebSocketMessage } from './parseWebSocketMessage'; import type { SubscriptionRepository } from './SubscriptionRepository'; @@ -41,7 +40,7 @@ export class SubscriptionService { readonly #eventEmitter: EventEmitter; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #notificationHandlers: Map> = new Map(); @@ -50,12 +49,12 @@ export class SubscriptionService { connectionService: WebSocketConnectionService, subscriptionRepository: SubscriptionRepository, eventEmitter: EventEmitter, - logger: ILogger, + logger: Logger, ) { this.#connectionService = connectionService; this.#subscriptionRepository = subscriptionRepository; this.#eventEmitter = eventEmitter; - this.#logger = createPrefixedLogger(logger, '[🔔 SubscriptionService]'); + this.#logger = logger.withPrefix('[🔔 SubscriptionService]'); this.#bindHandlers(); } diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.test.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.test.ts index 1b24e37be..b95025dc1 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.test.ts @@ -1,11 +1,12 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { WebSocketConnection } from '../../../entities'; import { EventEmitter } from '../../../infrastructure'; import { Network } from '../../constants/solana'; import { trackError } from '../../utils/errors'; +import { mockLogger } from '../__mocks__/logger'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { ConfigProvider } from '../config'; import type { NetworkConfig } from '../config/ConfigProvider'; -import { mockLogger } from '../mocks/logger'; import { InMemoryState } from '../state/InMemoryState'; import type { IStateManager } from '../state/IStateManager'; import { DEFAULT_UNENCRYPTED_STATE } from '../state/State'; diff --git a/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.ts b/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.ts index acd943d11..720f86cf0 100644 --- a/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.ts +++ b/packages/solana-wallet-snap/src/core/services/subscriptions/WebSocketConnectionService.ts @@ -1,3 +1,4 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { WebSocketCloseEvent, WebSocketEvent, @@ -12,8 +13,6 @@ import type { EventEmitter } from '../../../infrastructure'; import type { Network } from '../../constants/solana'; import { trackError } from '../../utils/errors'; import { getClientStatus } from '../../utils/interface'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { ConfigProvider } from '../config'; import type { IStateManager } from '../state/IStateManager'; @@ -43,7 +42,7 @@ export class WebSocketConnectionService { readonly #eventEmitter: EventEmitter; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #maxReconnectAttempts: number; @@ -66,7 +65,7 @@ export class WebSocketConnectionService { configProvider: ConfigProvider, state: IStateManager, eventEmitter: EventEmitter, - logger: ILogger, + logger: Logger, ) { const { maxReconnectAttempts, @@ -79,10 +78,7 @@ export class WebSocketConnectionService { this.#configProvider = configProvider; this.#state = state; this.#eventEmitter = eventEmitter; - this.#logger = createPrefixedLogger( - logger, - '[🔌 WebSocketConnectionService]', - ); + this.#logger = logger.withPrefix('[🔌 WebSocketConnectionService]'); this.#maxReconnectAttempts = maxReconnectAttempts; this.#reconnectDelayMilliseconds = reconnectDelayMilliseconds; this.#closeConnectionsGracePeriodMilliseconds = diff --git a/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.test.ts b/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.test.ts index 37491e961..3b7b39dc3 100644 --- a/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.test.ts +++ b/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { Duration } from '@metamask/utils'; import { MOCK_HISTORICAL_PRICES } from '../../clients/price-api/mocks/historical-prices'; @@ -6,8 +7,8 @@ import type { PriceApiClient } from '../../clients/price-api/PriceApiClient'; import type { SpotPrice } from '../../clients/price-api/types'; import { MOCK_EXCHANGE_RATES } from '../../test/mocks/price-api/exchange-rates'; import { trackError } from '../../utils/errors'; +import { mockLogger } from '../__mocks__/logger'; import { ConfigProvider } from '../config'; -import { mockLogger } from '../mocks/logger'; /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { TokenPricesService } from './TokenPrices'; diff --git a/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.ts b/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.ts index a43efd907..251b1701e 100644 --- a/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.ts +++ b/packages/solana-wallet-snap/src/core/services/token-prices/TokenPrices.ts @@ -1,5 +1,6 @@ import { CaipAssetTypeStruct } from '@metamask/keyring-api'; import type { CaipAssetType } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { AssetConversion, FungibleAssetMarketData, @@ -19,14 +20,13 @@ import type { SpotPrice } from '../../clients/price-api/types'; import type { FiatTicker } from '../../clients/price-api/types'; import { trackError } from '../../utils/errors'; import { isFiat } from '../../utils/isFiat'; -import type { ILogger } from '../../utils/logger'; import type { ConfigProvider } from '../config'; import type { HistoricalPrice } from './types'; export class TokenPricesService { readonly #priceApiClient: PriceApiClient; - readonly #logger: ILogger; + readonly #logger: Logger; readonly cacheTtlsMilliseconds: { fiatExchangeRates: number; @@ -41,7 +41,7 @@ export class TokenPricesService { }: { configProvider: ConfigProvider; priceApiClient: PriceApiClient; - logger: ILogger; + logger: Logger; }) { this.#priceApiClient = priceApiClient; this.#logger = logger; diff --git a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts index b33e83a08..fab7c65fc 100644 --- a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts +++ b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.test.ts @@ -1,9 +1,10 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; + import type { SecurityAlertsApiClient } from '../../clients/security-alerts-api/SecurityAlertsApiClient'; import type { SecurityAlertSimulationValidationResponse } from '../../clients/security-alerts-api/types'; import { Network } from '../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNT_0 } from '../../test/mocks/solana-keyring-accounts'; import { trackError } from '../../utils/errors'; -import type { ILogger } from '../../utils/logger'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import { TransactionScanService } from './TransactionScan'; import { ScanStatus, SecurityAlertResponse } from './types'; @@ -15,7 +16,7 @@ jest.mock('../../utils/errors', () => ({ describe('TransactionScan', () => { let transactionScanService: TransactionScanService; let mockSecurityAlertsApiClient: SecurityAlertsApiClient; - let mockLogger: ILogger; + let mockLogger: Logger; let mockAnalyticsService: AnalyticsService; beforeEach(() => { @@ -25,7 +26,8 @@ describe('TransactionScan', () => { mockLogger = { error: jest.fn(), - } as unknown as ILogger; + withPrefix: jest.fn().mockReturnThis(), + } as unknown as Logger; mockAnalyticsService = { trackEventSecurityScanCompleted: jest.fn().mockResolvedValue(undefined), diff --git a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts index 98c54befc..b1e206734 100644 --- a/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts +++ b/packages/solana-wallet-snap/src/core/services/transaction-scan/TransactionScan.ts @@ -1,10 +1,11 @@ +import type { Logger } from '@metamask/snap-networks-utils/logger'; + import type { SolanaKeyringAccount } from '../../../entities'; import type { SecurityAlertsApiClient } from '../../clients/security-alerts-api/SecurityAlertsApiClient'; import type { SecurityAlertSimulationValidationResponse } from '../../clients/security-alerts-api/types'; import { METAMASK_ORIGIN, METAMASK_ORIGIN_URL } from '../../constants/solana'; import type { Network } from '../../constants/solana'; import { trackError } from '../../utils/errors'; -import type { ILogger } from '../../utils/logger'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { TransactionScanResult, TransactionScanValidation } from './types'; import { ScanStatus, SecurityAlertResponse } from './types'; @@ -12,14 +13,14 @@ import { ScanStatus, SecurityAlertResponse } from './types'; export class TransactionScanService { readonly #securityAlertsApiClient: SecurityAlertsApiClient; - readonly #logger: ILogger; + readonly #logger: Logger; readonly #analyticsService: AnalyticsService; constructor( securityAlertsApiClient: SecurityAlertsApiClient, analyticsService: AnalyticsService, - logger: ILogger, + logger: Logger, ) { this.#securityAlertsApiClient = securityAlertsApiClient; this.#analyticsService = analyticsService; diff --git a/packages/solana-wallet-snap/src/core/services/transactions/TransactionMapper.ts b/packages/solana-wallet-snap/src/core/services/transactions/TransactionMapper.ts index 6f0bcdc2e..0ffb9fcbe 100644 --- a/packages/solana-wallet-snap/src/core/services/transactions/TransactionMapper.ts +++ b/packages/solana-wallet-snap/src/core/services/transactions/TransactionMapper.ts @@ -1,5 +1,6 @@ import type { Transaction } from '@metamask/keyring-api'; import { TransactionStatus, TransactionType } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { CaipAssetType } from '@metamask/utils'; import { SYSTEM_PROGRAM_ADDRESS } from '@solana-program/system'; import { address as asAddress, lamports } from '@solana/kit'; @@ -20,7 +21,6 @@ import type { Network } from '../../constants/solana'; import type { SolanaTransaction } from '../../types/solana'; import { lamportsToSol } from '../../utils/conversion'; import { trackError } from '../../utils/errors'; -import type { ILogger } from '../../utils/logger'; import { tokenAddressToCaip19 } from '../../utils/tokenAddressToCaip19'; import type { AssetMetadata } from '../assets/types'; @@ -29,12 +29,12 @@ export class TransactionMapper { readonly #assetsService: AssetsService; - readonly #logger: ILogger; + readonly #logger: Logger; constructor( tokenHelper: TokenHelper, assetsService: AssetsService, - logger: ILogger, + logger: Logger, ) { this.#tokenHelper = tokenHelper; this.#assetsService = assetsService; diff --git a/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.test.ts b/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.test.ts index 6bcba5b69..924b750d4 100644 --- a/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { Transaction } from '@metamask/keyring-api'; import { address as asAddress } from '@solana/kit'; @@ -11,11 +12,10 @@ import { import { MOCK_GET_SIGNATURES_FOR_ADDRESS } from '../../test/mocks/transactions'; import { ADDRESS_1_TRANSACTION_1_DATA } from '../../test/mocks/transactions-data/address-1/transaction-1'; import { trackError } from '../../utils/errors'; +import { createMockConnection } from '../__mocks__/mockConnection'; import type { AccountsService } from '../accounts/AccountsService'; import type { AssetsService } from '../assets/AssetsService'; import type { SolanaConnection } from '../connection/SolanaConnection'; -import { mockLogger } from '../mocks/logger'; -import { createMockConnection } from '../mocks/mockConnection'; import type { TransactionMapper } from './TransactionMapper'; import type { TransactionsRepository } from './TransactionsRepository'; import { TransactionsService } from './TransactionsService'; @@ -63,7 +63,6 @@ describe('TransactionsService', () => { mockAccountsService, mockAssetsService, mockConnection, - mockLogger, ); const snap = { diff --git a/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.ts b/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.ts index 400e0a083..6a80ed81e 100644 --- a/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.ts +++ b/packages/solana-wallet-snap/src/core/services/transactions/TransactionsService.ts @@ -10,8 +10,6 @@ import type { SolanaKeyringAccount } from '../../../entities/keyring-account'; import type { Network } from '../../constants/solana'; import type { SolanaTransaction } from '../../types/solana'; import { trackError } from '../../utils/errors'; -import { createPrefixedLogger } from '../../utils/logger'; -import type { ILogger } from '../../utils/logger'; import { tokenAddressToCaip19 } from '../../utils/tokenAddressToCaip19'; import type { AccountsService } from '../accounts'; import type { AssetsService } from '../assets/AssetsService'; @@ -31,22 +29,18 @@ export class TransactionsService { readonly #connection: SolanaConnection; - readonly #logger: ILogger; - constructor( transactionsRepository: TransactionsRepository, transactionMapper: TransactionMapper, accountsService: AccountsService, assetsService: AssetsService, connection: SolanaConnection, - logger: ILogger, ) { this.#transactionsRepository = transactionsRepository; this.#transactionMapper = transactionMapper; this.#accountsService = accountsService; this.#assetsService = assetsService; this.#connection = connection; - this.#logger = createPrefixedLogger(logger, '[💱 TransactionsService]'); } async fetchBySignature( diff --git a/packages/solana-wallet-snap/src/core/services/transactions/utils/isSpam.test.ts b/packages/solana-wallet-snap/src/core/services/transactions/utils/isSpam.test.ts index aee19f4ec..7b2af53af 100644 --- a/packages/solana-wallet-snap/src/core/services/transactions/utils/isSpam.test.ts +++ b/packages/solana-wallet-snap/src/core/services/transactions/utils/isSpam.test.ts @@ -1,12 +1,13 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { address as asAddress } from '@solana/kit'; import { Network } from '../../../constants/solana'; import { MOCK_SOLANA_KEYRING_ACCOUNT_0 } from '../../../test/mocks/solana-keyring-accounts'; import { EXPECTED_SPAM_TRANSACTION_DATA } from '../../../test/mocks/transactions-data/spam'; import { EXPECTED_SPAM_TRANSACTION_DATA_2 } from '../../../test/mocks/transactions-data/spam-2'; +import { mockLogger } from '../../__mocks__/logger'; import type { AssetsService } from '../../assets/AssetsService'; import type { TokenHelper } from '../../assets/TokenHelper'; -import { mockLogger } from '../../mocks/logger'; import { TransactionMapper } from '../TransactionMapper'; import { isSpam } from './isSpam'; diff --git a/packages/solana-wallet-snap/src/core/services/wallet/WalletService.test.ts b/packages/solana-wallet-snap/src/core/services/wallet/WalletService.test.ts index 772991216..438d55bb2 100644 --- a/packages/solana-wallet-snap/src/core/services/wallet/WalletService.test.ts +++ b/packages/solana-wallet-snap/src/core/services/wallet/WalletService.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import { SolMethod } from '@metamask/keyring-api'; import { Network } from '../../constants/solana'; @@ -11,9 +12,9 @@ import { } from '../../test/mocks/solana-keyring-accounts'; import { getBip32EntropyMock } from '../../test/mocks/utils/getBip32Entropy'; import logger from '../../utils/logger'; +import { createMockConnection } from '../__mocks__/mockConnection'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { SolanaConnection } from '../connection'; -import { createMockConnection } from '../mocks/mockConnection'; import { MOCK_EXECUTION_SCENARIOS } from '../signer/mocks/scenarios'; import type { Signer } from '../signer/Signer'; import type { SignatureMonitor } from '../subscriptions'; diff --git a/packages/solana-wallet-snap/src/core/services/wallet/WalletService.ts b/packages/solana-wallet-snap/src/core/services/wallet/WalletService.ts index a5ebd96b0..9e13b9c5f 100644 --- a/packages/solana-wallet-snap/src/core/services/wallet/WalletService.ts +++ b/packages/solana-wallet-snap/src/core/services/wallet/WalletService.ts @@ -1,4 +1,5 @@ import { SolMethod } from '@metamask/keyring-api'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; import type { Infer } from '@metamask/superstruct'; import { assert, instance, object } from '@metamask/superstruct'; import type { Commitment, SignatureBytes } from '@solana/kit'; @@ -23,8 +24,7 @@ import { fromTransactionToBase64String } from '../../sdk-extensions/codecs'; import { addressToCaip10 } from '../../utils/addressToCaip10'; import { deriveSolanaKeypair } from '../../utils/deriveSolanaKeypair'; import { getSolanaExplorerUrl } from '../../utils/getSolanaExplorerUrl'; -import type { ILogger } from '../../utils/logger'; -import logger, { createPrefixedLogger } from '../../utils/logger'; +import logger from '../../utils/logger'; import { Base58Struct, Base64Struct } from '../../validation/structs'; import type { AnalyticsService } from '../analytics/AnalyticsService'; import type { SolanaConnection } from '../connection'; @@ -58,7 +58,7 @@ export class WalletService { readonly #analyticsService: AnalyticsService; - readonly #logger: ILogger; + readonly #logger: Logger; constructor( connection: SolanaConnection, @@ -71,7 +71,7 @@ export class WalletService { this.#signer = signer; this.#signatureMonitor = signatureMonitor; this.#analyticsService = analyticsService; - this.#logger = createPrefixedLogger(_logger, '[👛 WalletService]'); + this.#logger = _logger.withPrefix('[👛 WalletService]'); } /** diff --git a/packages/solana-wallet-snap/src/core/utils/errors.test.ts b/packages/solana-wallet-snap/src/core/utils/errors.test.ts index cd68623a5..2f435a7a8 100644 --- a/packages/solana-wallet-snap/src/core/utils/errors.test.ts +++ b/packages/solana-wallet-snap/src/core/utils/errors.test.ts @@ -18,7 +18,7 @@ const setupTest = () => { request: mockSnapRequest, }; - return { mockSnapRequest, mockLogger: logger as jest.Mocked }; + return { mockSnapRequest, mockLogger: logger }; }; describe('errors', () => { @@ -114,7 +114,8 @@ describe('errors', () => { expect(mockLogger.error).toHaveBeenCalledTimes(1); const logCall = mockLogger.error.mock.calls[0]; - const loggedError = logCall?.[0]?.error; + const loggedError = (logCall?.[0] as { error?: Error } | undefined) + ?.error; expect(loggedError).toBeInstanceOf(SnapError); }); @@ -130,7 +131,8 @@ describe('errors', () => { expect(mockLogger.error).toHaveBeenCalledTimes(1); const logCall = mockLogger.error.mock.calls[0]; - const loggedError = logCall?.[0]?.error; + const loggedError = (logCall?.[0] as { error?: Error } | undefined) + ?.error; expect(loggedError).toBeInstanceOf(SnapError); }); @@ -207,7 +209,8 @@ describe('errors', () => { for (let i = 0; i < errorTypes.length; i++) { const logCall = logCalls[i]; - const loggedError = logCall?.[0]?.error; + const loggedError = (logCall?.[0] as { error?: Error } | undefined) + ?.error; expect(loggedError).toBeInstanceOf(SnapError); expect(loggedError?.message).toBe(errorTypes[i]?.message); } diff --git a/packages/solana-wallet-snap/src/core/utils/logMaybeSolanaError.ts b/packages/solana-wallet-snap/src/core/utils/logMaybeSolanaError.ts index 5d8a80648..8850389d5 100644 --- a/packages/solana-wallet-snap/src/core/utils/logMaybeSolanaError.ts +++ b/packages/solana-wallet-snap/src/core/utils/logMaybeSolanaError.ts @@ -1,9 +1,8 @@ +import type { LogMethod } from '@metamask/snap-networks-utils/logger'; import { getSystemErrorMessage, isSystemError } from '@solana-program/system'; import type { Address } from '@solana/kit'; import { isSolanaError } from '@solana/kit'; -import logger from './logger'; - type TransactionMessageIsh = { instructions: Record< number, @@ -17,19 +16,21 @@ type TransactionMessageIsh = { * Generic logging function for Solana errors. * * @param error - The Solana error to log. + * @param log - The logger output function for formatted error details. * @param transactionMessage - The transaction message to include in the error detail message. */ export const logMaybeSolanaError = ( - error: any, + error: unknown, + log: LogMethod, transactionMessage: TransactionMessageIsh = { instructions: {} }, -) => { +): void => { if (isSolanaError(error)) { const preflightErrorContext = error.context; const preflightErrorMessage = error.message; const errorDetailMessage = isSystemError(error.cause, transactionMessage) ? getSystemErrorMessage(error.cause.context.code) : error.cause; - logger.error( + log( preflightErrorContext, '%s: %s', preflightErrorMessage, diff --git a/packages/solana-wallet-snap/src/core/utils/logger.ts b/packages/solana-wallet-snap/src/core/utils/logger.ts index d3b253d06..9b20c8ea9 100644 --- a/packages/solana-wallet-snap/src/core/utils/logger.ts +++ b/packages/solana-wallet-snap/src/core/utils/logger.ts @@ -1,78 +1,20 @@ -/** - * A simple logger utility that provides methods for logging messages at different levels. - * For now, it's just a wrapper around console. - * - * @namespace logger - */ +import { Logger, LogLevel } from '@metamask/snap-networks-utils/logger'; +import { ConfigProvider } from '../services/config'; import { logMaybeSolanaError } from './logMaybeSolanaError'; -export type ILogger = { - log: (...args: any[]) => void; - info: (...args: any[]) => void; - warn: (...args: any[]) => void; - error: (...args: any[]) => void; - debug: (...args: any[]) => void; -}; +const configProvider = new ConfigProvider(); -const withSolanaErrorLogging = - (logFn: (...args: any[]) => void) => - (...args: any[]) => { - logMaybeSolanaError(args[0]); - logFn(...args); - }; - -/** - * A decorator function that noops if the environment is not local, - * and runs the decorated function otherwise. - * - * @param fn - The function to wrap. - * @returns The wrapped function. - */ -const withNoopInProduction = - (fn: (...args: any[]) => void) => - (...args: any[]) => { - // eslint-disable-next-line no-restricted-globals - if (process.env.ENVIRONMENT === 'production') { - return; - } - fn(...args); - }; - -/** - * A basic logger that wraps the console, extending its functionality to properly log Solana errors. - */ -const logger: ILogger = { - log: withNoopInProduction(console.log), - info: withNoopInProduction(console.info), - warn: withNoopInProduction(console.warn), - debug: withNoopInProduction(console.debug), - error: withNoopInProduction(withSolanaErrorLogging(console.error)), -}; - -export const noOpLogger: ILogger = { - log: () => {}, - info: () => {}, - warn: () => {}, - debug: () => {}, - error: () => {}, -}; - -export const createPrefixedLogger = ( - _logger: ILogger, - prefix: string, -): ILogger => { - return new Proxy(_logger, { - get(target, prop: keyof ILogger) { - const method = target[prop]; - if (typeof method === 'function') { - return (message: string, ...args: any[]) => { - return method.call(target, prefix, message, ...args); - }; - } - return method; +const logger = new Logger({ + level: configProvider.get().logLevel, + decorators: { + error: (next, error, ...args): void => { + logMaybeSolanaError(error, next); + next(error, ...args); }, - }); -}; + }, +}); + +export const noOpLogger = new Logger({ level: LogLevel.SILENT }); export default logger; diff --git a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/render.test.tsx b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/render.test.tsx index 1a6c028c9..80b7b5118 100644 --- a/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/render.test.tsx +++ b/packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/render.test.tsx @@ -1,3 +1,4 @@ +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ import type { KeyringRequest } from '@metamask/keyring-api'; import { KeyringRpcMethod, SolMethod } from '@metamask/keyring-api'; import { installSnap } from '@metamask/snaps-jest'; @@ -9,11 +10,11 @@ import { MOCK_SOLANA_RPC_GET_FEE_FOR_MESSAGE_RESPONSE, MOCK_SOLANA_RPC_GET_LATEST_BLOCKHASH_RESPONSE, MOCK_SOLANA_RPC_GET_MULTIPLE_ACCOUNTS_SWAP_RESPONSE, -} from '../../../../core/services/mocks/mockSolanaRpcResponses'; +} from '../../../../core/services/__mocks__/mockSolanaRpcResponses'; import { MOCK_SCAN_TRANSACTION_RESPONSE, MOCK_SECURITY_ALERTS_API_SCAN_TRANSACTIONS_RESPONSE, -} from '../../../../core/services/mocks/scanResponses'; +} from '../../../../core/services/__mocks__/scanResponses'; import { MOCK_SOLANA_KEYRING_ACCOUNT_0, MOCK_SOLANA_KEYRING_ACCOUNT_1, diff --git a/packages/solana-wallet-snap/src/index.ts b/packages/solana-wallet-snap/src/index.ts index 78082a7ce..194addacf 100644 --- a/packages/solana-wallet-snap/src/index.ts +++ b/packages/solana-wallet-snap/src/index.ts @@ -35,7 +35,7 @@ import { onNameLookupHandler } from './core/handlers/onNameLookup/onNameLookup'; import { onProtocolRequest as onProtocolRequestHandler } from './core/handlers/onProtocolRequest/onProtocolRequest'; import { handlers as onRpcRequestHandlers } from './core/handlers/onRpcRequest'; import { withCatchAndThrowSnapError } from './core/utils/errors'; -import logger, { createPrefixedLogger } from './core/utils/logger'; +import logger from './core/utils/logger'; import { validateOrigin } from './core/validation/validators'; import { eventHandlers as confirmSignInEvents } from './features/confirmation/views/ConfirmSignIn/events'; import { eventHandlers as confirmSignMessageEvents } from './features/confirmation/views/ConfirmSignMessage/events'; @@ -173,7 +173,7 @@ export const onUserInput: OnUserInputHandler = async ({ * @see https://docs.metamask.io/snaps/reference/entry-points/#oncronjob */ export const onCronjob: OnCronjobHandler = async ({ request }) => { - const _logger = createPrefixedLogger(logger, '[⏱️ onCronjob]'); + const _logger = logger.withPrefix('[⏱️ onCronjob]'); _logger.log(request.method, request); diff --git a/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.test.ts b/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.test.ts index 3065c69a9..f9436bd3e 100644 --- a/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.test.ts +++ b/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.test.ts @@ -1,4 +1,5 @@ -import { mockLogger } from '../../core/services/mocks/logger'; +/* eslint-disable jest/no-mocks-import -- Test fixtures are imported directly. */ +import { mockLogger } from '../../core/services/__mocks__/logger'; import { EventEmitter } from './EventEmitter'; describe('EventEmitter', () => { diff --git a/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.ts b/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.ts index 88656c0dd..f9189b819 100644 --- a/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.ts +++ b/packages/solana-wallet-snap/src/infrastructure/event-emitter/EventEmitter.ts @@ -1,5 +1,4 @@ -import { createPrefixedLogger } from '../../core/utils/logger'; -import type { ILogger } from '../../core/utils/logger'; +import type { Logger } from '@metamask/snap-networks-utils/logger'; type Listener = (data?: any) => Promise; @@ -17,12 +16,12 @@ type Listener = (data?: any) => Promise; * ``` */ export class EventEmitter { - readonly #logger: ILogger; + readonly #logger: Logger; readonly #listeners: Map> = new Map(); - constructor(logger: ILogger) { - this.#logger = createPrefixedLogger(logger, '[⚡ EventEmitter]'); + constructor(logger: Logger) { + this.#logger = logger.withPrefix('[⚡ EventEmitter]'); } /** diff --git a/packages/solana-wallet-snap/src/snapContext.ts b/packages/solana-wallet-snap/src/snapContext.ts index 32fc38f63..fb5fb54d9 100644 --- a/packages/solana-wallet-snap/src/snapContext.ts +++ b/packages/solana-wallet-snap/src/snapContext.ts @@ -172,7 +172,6 @@ const transactionsService = new TransactionsService( accountsService, assetsService, connection, - logger, ); const accountsSynchronizer = new AccountsSynchronizer( diff --git a/yarn.lock b/yarn.lock index ee0ba714f..27d5c29a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3671,6 +3671,7 @@ __metadata: "@metamask/key-tree": "npm:^10.1.1" "@metamask/keyring-api": "npm:^23.7.0" "@metamask/keyring-snap-sdk": "npm:^9.2.1" + "@metamask/snap-networks-utils": "npm:^1.0.0" "@metamask/snaps-cli": "npm:^8.4.1" "@metamask/snaps-jest": "npm:^10.2.0" "@metamask/snaps-sdk": "npm:^11.2.0"