From 41f029a11a0a4d5c11aacb06a15bbad2dd1f20e0 Mon Sep 17 00:00:00 2001 From: ruhil6789 Date: Tue, 30 Dec 2025 18:11:26 +0530 Subject: [PATCH 1/2] refactor: replace console statements with logger in extension-base - Replaced all console.* statements with logger calls across extension-base - Added logger instances to all service files, API files, and utilities - Fixed TypeScript errors related to missing logger declarations - Test files (.spec.ts) intentionally left unchanged --- packages/extension-base/package.json | 1 + .../src/background/handlers/helpers.ts | 8 +- .../src/background/handlers/subscriptions.ts | 5 +- .../extension-base/src/constants/index.ts | 6 +- .../src/core/logic-validation/request.ts | 17 +- packages/extension-base/src/core/utils.ts | 6 +- .../extension-base/src/koni/api/coingecko.ts | 11 +- .../src/koni/api/dotsama/crowdloan.ts | 7 +- .../src/koni/api/dotsama/domain.ts | 8 +- .../src/koni/api/nft/acala_nft/index.ts | 5 +- .../src/koni/api/nft/assethub_nft/index.ts | 5 +- .../src/koni/api/nft/assethub_unique/index.ts | 5 +- .../src/koni/api/nft/bit.country/index.ts | 7 +- .../src/koni/api/nft/blobinscription/index.ts | 5 +- .../src/koni/api/nft/evm_nft/index.ts | 7 +- .../extension-base/src/koni/api/nft/index.ts | 5 +- .../src/koni/api/nft/karura_nft/index.ts | 5 +- .../src/koni/api/nft/quartz_nft/index.ts | 5 +- .../src/koni/api/nft/quartz_nft/protobuf.ts | 6 +- .../src/koni/api/nft/rari/index.ts | 5 +- .../src/koni/api/nft/rmrk_nft/index.ts | 9 +- .../koni/api/nft/story_odyssey_nft/index.ts | 7 +- .../src/koni/api/nft/ternoa_nft/index.ts | 9 +- .../src/koni/api/nft/transfer.ts | 11 +- .../koni/api/nft/unique_network_nft/index.ts | 5 +- .../src/koni/api/nft/unique_nft/index.ts | 5 +- .../src/koni/api/nft/unique_nft/protobuf.ts | 8 +- .../koni/api/nft/unique_nft/uniqueNftV2.ts | 5 +- .../src/koni/api/nft/vara_nft/index.ts | 5 +- .../src/koni/api/nft/wasm_nft/index.ts | 9 +- .../src/koni/api/staking/bonding/astar.ts | 8 +- .../src/koni/api/staking/bonding/utils.ts | 6 +- .../src/koni/api/staking/relayChain.ts | 6 +- .../src/koni/api/staking/subsquidStaking.ts | 9 +- .../src/koni/background/cron.ts | 14 +- .../src/koni/background/handlers/Extension.ts | 49 +- .../src/koni/background/handlers/Mobile.ts | 27 +- .../src/koni/background/handlers/State.ts | 41 +- .../src/koni/background/handlers/Tabs.ts | 28 +- .../src/koni/background/handlers/index.ts | 7 +- .../src/koni/background/subscription.ts | 2 +- .../src/koni/background/utils.ts | 14 +- packages/extension-base/src/page/evm/index.ts | 5 +- .../src/page/substrate/Accounts.ts | 7 +- .../src/page/substrate/PostMessageProvider.ts | 7 +- .../src/page/substrate/index.ts | 6 +- .../helpers/subscribe/bitcoin.ts | 9 +- .../helpers/subscribe/cardano/index.ts | 5 +- .../helpers/subscribe/cardano/utils.ts | 5 +- .../balance-service/helpers/subscribe/evm.ts | 11 +- .../helpers/subscribe/index.ts | 5 +- .../subscribe/substrate/equilibrium.ts | 7 +- .../helpers/subscribe/substrate/gear.ts | 15 +- .../helpers/subscribe/substrate/index.ts | 23 +- .../helpers/subscribe/ton/ton.ts | 11 +- .../src/services/balance-service/index.ts | 19 +- .../transfer/bitcoin-transfer.ts | 5 +- .../transfer/cardano-transfer.ts | 7 +- .../transfer/smart-contract.ts | 9 +- .../balance-service/transfer/token.ts | 5 +- .../transfer/xcm/acrossBridge/index.ts | 5 +- .../transfer/xcm/availBridge.ts | 11 +- .../balance-service/transfer/xcm/index.ts | 5 +- .../balance-service/transfer/xcm/posBridge.ts | 7 +- .../transfer/xcm/snowBridge.ts | 7 +- .../balance-service/transfer/xcm/utils.ts | 11 +- .../src/services/buy-service/index.ts | 7 +- .../src/services/campaign-service/helpers.ts | 5 +- .../src/services/campaign-service/index.ts | 11 +- .../services/chain-online-service/index.ts | 11 +- .../chain-service/handler/CardanoApi.ts | 17 +- .../handler/CardanoChainHandler.ts | 11 +- .../services/chain-service/handler/EvmApi.ts | 9 +- .../chain-service/handler/EvmChainHandler.ts | 11 +- .../chain-service/handler/SubstrateApi.ts | 17 +- .../handler/SubstrateChainHandler.ts | 13 +- .../services/chain-service/handler/TonApi.ts | 9 +- .../chain-service/handler/TonChainHandler.ts | 11 +- .../handler/bitcoin/BitcoinApi.ts | 7 +- .../handler/bitcoin/BitcoinChainHandler.ts | 11 +- .../blockstream-testnet-strategy.ts | 11 +- .../mempool-testnet-strategy.ts | 11 +- .../strategy/SubWalletMainnet/index.ts | 13 +- .../handler/light-client/index.ts | 12 +- .../handler/manta/MantaPrivateHandler.ts | 9 +- .../chain-service/health-check/index.ts | 9 +- .../health-check/utils/asset-info.ts | 9 +- .../health-check/utils/provider.ts | 21 +- .../src/services/chain-service/index.ts | 43 +- .../handlers/liquid-staking/acala.ts | 5 +- .../handlers/liquid-staking/bifrost-manta.ts | 7 +- .../handlers/liquid-staking/bifrost.ts | 7 +- .../handlers/liquid-staking/stella-swap.ts | 7 +- .../handlers/native-staking/astar.ts | 9 +- .../handlers/native-staking/base.ts | 9 +- .../handlers/native-staking/dtao.ts | 15 +- .../handlers/native-staking/tanssi.ts | 7 +- .../handlers/native-staking/tao.ts | 1641 +++++++++-------- .../earning-service/handlers/special.ts | 7 +- .../src/services/earning-service/service.ts | 39 +- .../src/services/event-service/index.ts | 7 +- .../src/services/fee-service/service.ts | 9 +- .../src/services/fee-service/utils/index.ts | 9 +- .../services/fee-service/utils/tokenPayFee.ts | 11 +- .../src/services/hiro-service/utils/index.ts | 11 +- .../helpers/recoverHistoryStatus.ts | 25 +- .../src/services/history-service/index.ts | 39 +- .../history-service/subscan-history.ts | 5 +- .../subsquid-multi-chain-history.ts | 7 +- .../inapp-notification-service/index.ts | 17 +- .../inapp-notification-service/utils/avail.ts | 7 +- .../utils/polygon.ts | 7 +- .../context/handlers/Derive.ts | 5 +- .../keyring-service/context/handlers/Json.ts | 15 +- .../context/handlers/Migration.ts | 7 +- .../context/handlers/Modify.ts | 7 +- .../context/handlers/Secret.ts | 5 +- .../services/keyring-service/context/state.ts | 13 +- .../src/services/keyring-service/index.ts | 5 +- .../src/services/migration-service/Base.ts | 2 +- .../migration-service/scripts/DeleteChain.ts | 2 +- .../scripts/DeleteChainStaking.ts | 2 +- .../scripts/DeleteEarningData.ts | 2 +- .../scripts/DeleteEarningData20251010.ts | 2 +- .../scripts/DeleteEarningData20251105.ts | 2 +- .../scripts/DisableZeroBalanceTokens.ts | 2 +- .../scripts/EnableEarningChains.ts | 2 +- .../scripts/MigrateAuthUrls.ts | 2 +- .../scripts/MigrateAutoLock.ts | 2 +- .../scripts/MigrateChainPatrol.ts | 2 +- .../scripts/MigrateImportedToken.ts | 3 +- .../scripts/MigrateNewUnifiedAccount.ts | 2 +- .../scripts/MigrateSettings.ts | 2 +- .../scripts/MigrateWalletReference.ts | 2 +- .../scripts/databases/AutoEnableSomeTokens.ts | 2 +- .../scripts/databases/MigrateAssetSetting.ts | 2 +- .../databases/MigrateAssetSetting20251027.ts | 2 +- .../databases/MigrateAssetSetting20251107.ts | 2 +- .../databases/MigrateEarningHistory.ts | 2 +- .../databases/MigrateEarningVersion.ts | 2 +- .../scripts/databases/ReloadMetadata.ts | 2 +- .../scripts/keyring/MigrateLedgerAccount.ts | 2 +- .../scripts/keyring/MigrateLedgerAccountV2.ts | 2 +- .../scripts/keyring/MigratePairData.ts | 4 +- .../keyring/MigrateRemoveGenesisHash.ts | 4 +- .../services/mkt-campaign-service/index.ts | 17 +- .../src/services/nft-service/index.ts | 23 +- .../NotificationService.ts | 5 +- .../src/services/price-service/coingecko.ts | 11 +- .../src/services/price-service/index.ts | 14 +- .../handler/AuthRequestHandler.ts | 7 +- .../handler/BitcoinRequestHandler.ts | 4 +- .../handler/CardanoRequestHandler.ts | 10 +- .../handler/EvmRequestHandler.ts | 4 +- .../handler/TonRequestHandler.ts | 4 +- .../src/services/request-service/index.ts | 5 +- .../setting-service/SettingService.ts | 7 +- .../src/services/setting-service/i18n/i18n.ts | 5 +- .../storage-service/db-stores/Crowdloan.ts | 5 +- .../db-stores/InappNotification.ts | 5 +- .../swap-service/handler/base-handler.ts | 7 +- .../swap-service/handler/chainflip-handler.ts | 5 +- .../swap-service/handler/kyber-handler.ts | 13 +- .../swap-service/handler/optimex-handler.ts | 15 +- .../handler/simpleswap-handler.ts | 9 +- .../swap-service/handler/uniswap-handler.ts | 13 +- .../src/services/swap-service/index.ts | 19 +- .../src/services/swap-service/utils.ts | 5 +- .../src/services/transaction-service/index.ts | 55 +- .../handler/Eip155RequestHandler.ts | 7 +- .../handler/PolkadotRequestHandler.ts | 5 +- .../services/wallet-connect-service/index.ts | 21 +- packages/extension-base/src/storage/index.ts | 15 +- packages/extension-base/src/stores/Base.ts | 6 +- packages/extension-base/src/stores/Keyring.ts | 6 +- .../src/stores/TransactionHistory.ts | 5 +- .../strategy/api-request-strategy-v2/index.ts | 7 +- .../src/utils/eth/parseTransaction/base.ts | 6 +- .../extension-base/src/utils/fee/transfer.ts | 7 +- packages/extension-base/src/utils/index.ts | 1 + .../extension-base/src/utils/logger/Logger.ts | 298 +++ .../extension-base/src/utils/logger/index.ts | 32 + .../src/utils/logger/sentry-adapter.ts | 28 + .../extension-base/src/utils/logger/types.ts | 35 + packages/extension-base/src/utils/metadata.ts | 16 +- packages/extension-base/src/utils/promise.ts | 8 +- 186 files changed, 2283 insertions(+), 1416 deletions(-) create mode 100644 packages/extension-base/src/utils/logger/Logger.ts create mode 100644 packages/extension-base/src/utils/logger/index.ts create mode 100644 packages/extension-base/src/utils/logger/sentry-adapter.ts create mode 100644 packages/extension-base/src/utils/logger/types.ts diff --git a/packages/extension-base/package.json b/packages/extension-base/package.json index 77cd1e9ac76..8ad6d92527c 100644 --- a/packages/extension-base/package.json +++ b/packages/extension-base/package.json @@ -91,6 +91,7 @@ "is-buffer": "^2.0.5", "joi": "^17.13.3", "json-rpc-engine": "^6.1.0", + "loglevel": "^1.8.1", "manta-extension-sdk": "^1.1.0", "moment": "^2.29.4", "protobufjs": "^7.2.4", diff --git a/packages/extension-base/src/background/handlers/helpers.ts b/packages/extension-base/src/background/handlers/helpers.ts index 5142efc4850..9f89a038bd5 100644 --- a/packages/extension-base/src/background/handlers/helpers.ts +++ b/packages/extension-base/src/background/handlers/helpers.ts @@ -1,14 +1,18 @@ // Copyright 2019-2022 @polkadot/extension authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const backgroundHelpersLogger = createLogger('BackgroundHelpers'); + export function withErrorLog (fn: () => unknown): void { try { const p = fn(); if (p && typeof p === 'object' && typeof (p as Promise).catch === 'function') { - (p as Promise).catch(console.error); + (p as Promise).catch((e) => backgroundHelpersLogger.error('Error in withErrorLog promise', e)); } } catch (e) { - console.error(e); + backgroundHelpersLogger.error('Error in withErrorLog', e); } } diff --git a/packages/extension-base/src/background/handlers/subscriptions.ts b/packages/extension-base/src/background/handlers/subscriptions.ts index dd2d105a123..72d254983a5 100644 --- a/packages/extension-base/src/background/handlers/subscriptions.ts +++ b/packages/extension-base/src/background/handlers/subscriptions.ts @@ -3,9 +3,12 @@ import type { MessageTypesWithSubscriptions, SubscriptionMessageTypes } from '../types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + type Subscriptions = Record; const subscriptions: Subscriptions = {}; +const subscriptionsLogger = createLogger('Subscriptions'); // return a subscription callback, that will send the data to the caller via the port export function createSubscription (id: string, port: chrome.runtime.Port): (data: SubscriptionMessageTypes[TMessageType]) => void { @@ -27,6 +30,6 @@ export function unsubscribe (id: string): void { if (subscriptions[id]) { delete subscriptions[id]; } else { - console.error(`Unable to unsubscribe from ${id}`); + subscriptionsLogger.error(`Unable to unsubscribe from ${id}`); } } diff --git a/packages/extension-base/src/constants/index.ts b/packages/extension-base/src/constants/index.ts index 841cca2aa7a..5d94c43f117 100644 --- a/packages/extension-base/src/constants/index.ts +++ b/packages/extension-base/src/constants/index.ts @@ -58,9 +58,13 @@ export const getSupportTokenPayFeeChain = () => { return Object.values(_SUPPORT_TOKEN_PAY_FEE_GROUP).flat(); }; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const constantsLogger = createLogger('Constants'); + export const isChainSupportTokenPayFee = (chainSlug: string): boolean => { if (!chainSlug) { - console.error('You must provide chain slug!'); + constantsLogger.error('You must provide chain slug!'); return false; } diff --git a/packages/extension-base/src/core/logic-validation/request.ts b/packages/extension-base/src/core/logic-validation/request.ts index 7790ba63f75..5e78a8a8a1d 100644 --- a/packages/extension-base/src/core/logic-validation/request.ts +++ b/packages/extension-base/src/core/logic-validation/request.ts @@ -16,8 +16,11 @@ import { BN_ZERO, combineEthFee, createPromiseHandler, isSameAddress, reformatAd import { validateAddressNetwork } from '@subwallet/extension-base/utils/cardano'; import { isContractAddress, parseContractInput } from '@subwallet/extension-base/utils/eth/parseTransaction'; import { getId } from '@subwallet/extension-base/utils/getId'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isCardanoAddress, isCardanoBaseAddress, isCardanoRewardAddress, isSubstrateAddress } from '@subwallet/keyring'; import { KeyringPair } from '@subwallet/keyring/types'; + +const logicValidationLogger = createLogger('LogicValidation'); import { getBitcoinAddressInfo } from '@subwallet/keyring/utils'; import { isBitcoinAddress } from '@subwallet/keyring/utils/address/validate'; import { keyring } from '@subwallet/ui-keyring'; @@ -262,7 +265,7 @@ export async function validationConnectMiddleware (koni: KoniState, url: string, const [message, name] = convertErrorMessage(message_); const error = new EvmProviderError(EvmProviderErrorType.CHAIN_DISCONNECTED, message, undefined, name); - console.error(error); + logicValidationLogger.error('Validation error: chain disconnected', error); errors.push(error); }; @@ -356,7 +359,7 @@ export async function validationEvmDataTransactionMiddleware (koni: KoniState, u const [message, name] = convertErrorMessage(message_); const error = new TransactionError(BasicTxErrorType.INVALID_PARAMS, message, undefined, name); - console.error(error); + logicValidationLogger.error('Validation error: invalid params', error); errors.push(error); }; @@ -555,7 +558,7 @@ export async function validationEvmSignMessageMiddleware (koni: KoniState, url: const [message, name] = convertErrorMessage(message_); const error = new EvmProviderError(EvmProviderErrorType.INVALID_PARAMS, message, undefined, name); - console.error(error); + logicValidationLogger.error('Validation error: invalid params in evm signature', error); errors.push(error); }; @@ -614,7 +617,7 @@ export async function validationEvmSignMessageMiddleware (koni: KoniState, url: throw new Error('Unsupported action'); } } catch (e) { - console.error(e); + logicValidationLogger.error('Error in validationEvmSignMessageMiddleware', e); handleError((e as Error).message); } } else { @@ -760,7 +763,7 @@ export async function validationCardanoSignDataMiddleware (koni: KoniState, url: const [message, name] = convertErrorMessage(message_); const error = new CardanoProviderError(CardanoProviderErrorType.INVALID_REQUEST, message, undefined, name); - console.error(error); + logicValidationLogger.error('Validation error: invalid request in cardano signature', error); errors.push(error); }; @@ -823,7 +826,7 @@ export async function validationBitcoinConnectMiddleware (koni: KoniState, url: const [message, name] = convertErrorMessage(message_); const error = new TransactionError(BasicTxErrorType.INVALID_PARAMS, message, undefined, name); - console.error(error); + logicValidationLogger.error('Validation error: invalid params', error); errors.push(error); }; @@ -1074,7 +1077,7 @@ export async function validationBitcoinSendTransactionMiddleware (koni: KoniStat const [message, name] = [t('bg.TRANSACTION.core.validation.request.enableChainOnExtension', { replace: { chain: chainInfo.name } }), t('bg.TRANSACTION.core.validation.request.networkNotEnabled')]; const error = new BitcoinProviderError(BitcoinProviderErrorType.INVALID_PARAMS, message, undefined, name); - console.error(error); + logicValidationLogger.error('Validation error: network not enabled for bitcoin transaction', error); errors.push(error); } else { handleError(message); diff --git a/packages/extension-base/src/core/utils.ts b/packages/extension-base/src/core/utils.ts index 88a63121f39..914535fa539 100644 --- a/packages/extension-base/src/core/utils.ts +++ b/packages/extension-base/src/core/utils.ts @@ -16,6 +16,10 @@ import { getBitcoinAddressInfo, validateBitcoinAddress } from '@subwallet/keyrin import { AnyJson } from '@polkadot/types/types'; import { isEthereumAddress } from '@polkadot/util-crypto'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const coreUtilsLogger = createLogger('CoreUtils'); + export function getStrictMode (type: string, extrinsicType?: ExtrinsicType) { if (type === BalanceAccountType.FrameSystemAccountInfo) { return !extrinsicType || ![ExtrinsicType.TRANSFER_BALANCE].includes(extrinsicType); @@ -235,7 +239,7 @@ export const _isSufficientToken = async (tokenInfo: _ChainAsset, substrateApi: _ } } } catch (e) { - console.error(e); + coreUtilsLogger.error('Error in core utils', e); } } diff --git a/packages/extension-base/src/koni/api/coingecko.ts b/packages/extension-base/src/koni/api/coingecko.ts index 55872495105..44cb060828c 100644 --- a/packages/extension-base/src/koni/api/coingecko.ts +++ b/packages/extension-base/src/koni/api/coingecko.ts @@ -3,8 +3,11 @@ import { CurrencyJson, CurrencyType, ExchangeRateJSON, PriceJson } from '@subwallet/extension-base/background/KoniTypes'; import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import axios, { AxiosResponse } from 'axios'; +const coingeckoLogger = createLogger('Coingecko'); + interface GeckoItem { id: string, name: string, @@ -46,7 +49,7 @@ export const getTokenPrice = async (priceIds: Set, currencyCode: Currenc } if (rs?.status !== 200) { - console.warn('Failed to get token price'); + coingeckoLogger.warn('Failed to get token price'); } return rs; @@ -58,11 +61,11 @@ export const getTokenPrice = async (priceIds: Set, currencyCode: Currenc try { rs = await axios.get('https://api-cache.subwallet.app/exchange-rate'); } catch (e) { - console.warn('Failed to get exchange rate'); + coingeckoLogger.warn('Failed to get exchange rate', e); } if (rs?.status !== 200) { - console.warn('Failed to get exchange rate'); + coingeckoLogger.warn('Failed to get exchange rate - invalid status'); } return rs; @@ -109,7 +112,7 @@ export const getTokenPrice = async (priceIds: Set, currencyCode: Currenc price24hMap } as PriceJson; } catch (err) { - console.error(err); + coingeckoLogger.error('Error fetching price data', err); throw err; } }; diff --git a/packages/extension-base/src/koni/api/dotsama/crowdloan.ts b/packages/extension-base/src/koni/api/dotsama/crowdloan.ts index de7960e4db9..3ab3842759f 100644 --- a/packages/extension-base/src/koni/api/dotsama/crowdloan.ts +++ b/packages/extension-base/src/koni/api/dotsama/crowdloan.ts @@ -9,8 +9,11 @@ import registry from '@subwallet/extension-base/koni/api/dotsama/typeRegistry'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { fetchJson, getAddressesByChainType, reformatAddress } from '@subwallet/extension-base/utils'; import { fetchStaticData } from '@subwallet/extension-base/utils/fetchStaticData'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { DeriveOwnContributions } from '@polkadot/api-derive/types'; + +const crowdloanLogger = createLogger('Crowdloan'); import { BN } from '@polkadot/util'; const STATUS_MAP: Record<_FundStatus, CrowdloanParaState> = { @@ -74,7 +77,7 @@ function getRPCCrowdloan (parentAPI: _SubstrateApi, fundInfo: _CrowdloanFund, he .then((unsub) => { unsub(); }) - .catch(console.error); + .catch((e) => crowdloanLogger.error('Error unsubscribing from crowdloan', e)); }; } @@ -109,7 +112,7 @@ export const subscribeAcalaContributeInterval = (polkadotAddresses: string[], fu }; callback(rs); - }).catch(console.error); + }).catch((e) => crowdloanLogger.error('Error fetching Acala contribution info', e)); }; getContributeInfo(); diff --git a/packages/extension-base/src/koni/api/dotsama/domain.ts b/packages/extension-base/src/koni/api/dotsama/domain.ts index 57c7af86f52..10bd2f37562 100644 --- a/packages/extension-base/src/koni/api/dotsama/domain.ts +++ b/packages/extension-base/src/koni/api/dotsama/domain.ts @@ -5,6 +5,10 @@ import { resolveAddressToDomain, resolveDomainToAddress, SupportedChainId } from import { ApiPromise } from '@polkadot/api'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const domainResolverLogger = createLogger('DomainResolver'); + export const ENS_SUFFIX = '.eth'; export const TZERO_ID_SUFFIX = '.tzero'; @@ -42,7 +46,7 @@ export async function resolveAzeroDomainToAddress (domain: string, chain: string ); if (primaryDomains.error) { - console.debug(primaryDomains.error); + domainResolverLogger.debug('Error resolving domain to address', primaryDomains.error); } return primaryDomains?.address || undefined; @@ -64,7 +68,7 @@ export async function resolveAzeroAddressToDomain (address: string, chain: strin ); if (primaryDomains.error) { - console.debug(primaryDomains.error); + domainResolverLogger.debug('Error resolving address to domain', primaryDomains.error); } return primaryDomains?.primaryDomain || undefined; diff --git a/packages/extension-base/src/koni/api/nft/acala_nft/index.ts b/packages/extension-base/src/koni/api/nft/acala_nft/index.ts index adf09fbebc1..7e5468cad1e 100644 --- a/packages/extension-base/src/koni/api/nft/acala_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/acala_nft/index.ts @@ -6,6 +6,9 @@ import { getRandomIpfsGateway } from '@subwallet/extension-base/koni/api/nft/con import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const acalaNftLogger = createLogger('AcalaNft'); interface AssetId { classId: string | number, @@ -157,7 +160,7 @@ export class AcalaNftApi extends BaseNftApi { params.updateCollection(this.chain, parsedCollection); })); } catch (e) { - console.error(`${this.chain}`, e); + acalaNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/assethub_nft/index.ts b/packages/extension-base/src/koni/api/nft/assethub_nft/index.ts index 681efc80de4..ebc4517c98d 100644 --- a/packages/extension-base/src/koni/api/nft/assethub_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/assethub_nft/index.ts @@ -5,6 +5,9 @@ import { AssetHubNftType, NftCollection, NftItem } from '@subwallet/extension-ba import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const assethubNftLogger = createLogger('AssethubNft'); interface AssetId { classId: string | number, @@ -199,7 +202,7 @@ export default class AssetHubNftsPalletApi extends BaseNftApi { params.updateCollection(this.chain, parsedCollection); })); } catch (e) { - console.error(`${this.chain}`, e); + assethubNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/assethub_unique/index.ts b/packages/extension-base/src/koni/api/nft/assethub_unique/index.ts index 71c7c682b49..068b198e983 100644 --- a/packages/extension-base/src/koni/api/nft/assethub_unique/index.ts +++ b/packages/extension-base/src/koni/api/nft/assethub_unique/index.ts @@ -5,6 +5,9 @@ import { AssetHubNftType, NftCollection, NftItem } from '@subwallet/extension-ba import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const assethubUniqueLogger = createLogger('AssethubUnique'); interface AssetId { classId: string | number, @@ -167,7 +170,7 @@ export default class AssetHubUniquesPalletApi extends BaseNftApi { params.updateCollection(this.chain, parsedCollection); })); } catch (e) { - console.error(`${this.chain}`, e); + assethubUniqueLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/bit.country/index.ts b/packages/extension-base/src/koni/api/nft/bit.country/index.ts index 9adb4bb1925..db2a5022a9d 100644 --- a/packages/extension-base/src/koni/api/nft/bit.country/index.ts +++ b/packages/extension-base/src/koni/api/nft/bit.country/index.ts @@ -6,9 +6,12 @@ import { BIT_AVATAR_API, BIT_COUNTRY_IPFS_SERVER, BIT_COUNTRY_LAND_ESTATE_METADA import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BN_ZERO, hexToBn } from '@polkadot/util'; +const bitCountryNftLogger = createLogger('BitCountryNft'); + interface AssetId { classId: string | number, tokenId: string | number, @@ -126,7 +129,7 @@ export class BitCountryNftApi extends BaseNftApi { try { metaverseId = hexToBn(hexMetaverseId); } catch (e) { - console.warn('Error parsing metaverse id', e); + bitCountryNftLogger.warn('Error parsing metaverse id', e); } return { @@ -217,7 +220,7 @@ export class BitCountryNftApi extends BaseNftApi { params.updateCollection(this.chain, parsedCollection); })); } catch (e) { - console.error(`${this.chain}`, e); + bitCountryNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/blobinscription/index.ts b/packages/extension-base/src/koni/api/nft/blobinscription/index.ts index dd6eec3b6fe..c0e9b2404b1 100644 --- a/packages/extension-base/src/koni/api/nft/blobinscription/index.ts +++ b/packages/extension-base/src/koni/api/nft/blobinscription/index.ts @@ -6,9 +6,12 @@ import { COLLECT_ID } from '@subwallet/extension-base/koni/api/nft/blobinscripti import { ALC, getNftDetail, NftResponse, RemarkData, transferPayload } from '@subwallet/extension-base/koni/api/nft/blobinscription/types'; import { AVAIL_LIGHT_CLIENT_NFT } from '@subwallet/extension-base/koni/api/nft/config'; import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { hexToString } from '@polkadot/util'; +const blobInscriptionLogger = createLogger('BlobInscription'); + export class BlobInscriptionApi extends BaseNftApi { endpoint = AVAIL_LIGHT_CLIENT_NFT; @@ -162,7 +165,7 @@ export class BlobInscriptionApi extends BaseNftApi { } })); } catch (error) { - console.error('Failed to fetch blob inscription', error); + blobInscriptionLogger.error('Failed to fetch blob inscription', error); } } diff --git a/packages/extension-base/src/koni/api/nft/evm_nft/index.ts b/packages/extension-base/src/koni/api/nft/evm_nft/index.ts index 1296be6d653..8d01fd8bc3c 100644 --- a/packages/extension-base/src/koni/api/nft/evm_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/evm_nft/index.ts @@ -9,9 +9,12 @@ import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/ import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isEthereumAddress } from '@polkadot/util-crypto'; +const evmNftLogger = createLogger('EvmNft'); + export class EvmNftApi extends BaseNftApi { evmContracts: _ChainAsset[] = []; @@ -151,14 +154,14 @@ export class EvmNftApi extends BaseNftApi { ownItem = true; } } catch (e) { - console.error(`${this.chain}`, e); + evmNftLogger.error(`Error handling NFT for chain ${this.chain}`, e); } } })); nftOwnerMap[address] = nftIds; } catch (e) { - console.error(`${this.chain}`, e); + evmNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } })); diff --git a/packages/extension-base/src/koni/api/nft/index.ts b/packages/extension-base/src/koni/api/nft/index.ts index f6f1016303d..7a304923afc 100644 --- a/packages/extension-base/src/koni/api/nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/index.ts @@ -19,8 +19,11 @@ import { _NFT_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-servi import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { _isChainSupportEvmNft, _isChainSupportNativeNft, _isChainSupportWasmNft, _isSupportOrdinal } from '@subwallet/extension-base/services/chain-service/utils'; import { getAddressesByChainType, targetIsWeb } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import AssetHubNftsPalletApi from './assethub_nft'; + +const nftApiLogger = createLogger('NftApi'); import { RariNftApi } from './rari'; import { OdysseyNftApi } from './story_odyssey_nft'; import { TernoaNftApi } from './ternoa_nft'; @@ -223,7 +226,7 @@ export class NftHandler { this.needSetupApi = false; } } catch (e) { - console.error(e); + nftApiLogger.error('Error in NftHandler', e); } } diff --git a/packages/extension-base/src/koni/api/nft/karura_nft/index.ts b/packages/extension-base/src/koni/api/nft/karura_nft/index.ts index 4fd7395c036..12d5adfd83c 100644 --- a/packages/extension-base/src/koni/api/nft/karura_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/karura_nft/index.ts @@ -6,6 +6,9 @@ import { getRandomIpfsGateway } from '@subwallet/extension-base/koni/api/nft/con import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const karuraNftLogger = createLogger('KaruraNft'); interface AssetId { classId: string | number, @@ -163,7 +166,7 @@ export class KaruraNftApi extends BaseNftApi { params.updateCollection(this.chain, parsedCollection); })); } catch (e) { - console.error(`${this.chain}`, e); + karuraNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/quartz_nft/index.ts b/packages/extension-base/src/koni/api/nft/quartz_nft/index.ts index 01c307b6403..b52aadf8dbc 100644 --- a/packages/extension-base/src/koni/api/nft/quartz_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/quartz_nft/index.ts @@ -5,9 +5,12 @@ import { NftCollection, NftItem } from '@subwallet/extension-base/background/Kon import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { hexToStr, hexToUTF16, parseIpfsLink, utf16ToString } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { deserializeNft } from './protobuf'; +const quartzNftLogger = createLogger('QuartzNft'); + interface CollectionProperties { schemaVersion: string, offchainSchema: string, @@ -218,7 +221,7 @@ export default class QuartzNftApi extends BaseNftApi { } })); } catch (e) { - console.error(`${this.chain}`, e); + quartzNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/quartz_nft/protobuf.ts b/packages/extension-base/src/koni/api/nft/quartz_nft/protobuf.ts index 5ea2bbf3845..0f181e26610 100644 --- a/packages/extension-base/src/koni/api/nft/quartz_nft/protobuf.ts +++ b/packages/extension-base/src/koni/api/nft/quartz_nft/protobuf.ts @@ -3,6 +3,10 @@ import { Root } from 'protobufjs'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const quartzProtobufLogger = createLogger('QuartzProtobuf'); + function defineMessage (schema: string) { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument return Root.fromJSON(JSON.parse(schema)); @@ -26,7 +30,7 @@ function convertEnumToString (value: any, key: string, NFTMeta: any, locale: any result = translationObject[locale]; } } catch (e) { - console.log('Error parsing schema when trying to convert enum to string: ', e); + quartzProtobufLogger.error('Error parsing schema when trying to convert enum to string', e); } // eslint-disable-next-line @typescript-eslint/no-unsafe-return diff --git a/packages/extension-base/src/koni/api/nft/rari/index.ts b/packages/extension-base/src/koni/api/nft/rari/index.ts index 8aca1f0126c..8af22e078f7 100644 --- a/packages/extension-base/src/koni/api/nft/rari/index.ts +++ b/packages/extension-base/src/koni/api/nft/rari/index.ts @@ -2,9 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 import { NftCollection, NftItem } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseNftApi, HandleNftParams } from '../nft'; +const rariNftLogger = createLogger('RariNft'); + const options = { method: 'GET', headers: { @@ -63,7 +66,7 @@ export class RariNftApi extends BaseNftApi { ) .then((response) => response.json()) .catch((err) => { - console.error(err); + rariNftLogger.error('Error fetching Rari NFT', err); return null; }) as NftResponse; diff --git a/packages/extension-base/src/koni/api/nft/rmrk_nft/index.ts b/packages/extension-base/src/koni/api/nft/rmrk_nft/index.ts index fbae27554a8..2000da7338a 100644 --- a/packages/extension-base/src/koni/api/nft/rmrk_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/rmrk_nft/index.ts @@ -4,9 +4,12 @@ import { NftCollection, NftItem, RMRK_VER } from '@subwallet/extension-base/background/KoniTypes'; import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { isUrl, reformatAddress } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { SINGULAR_V1_COLLECTION_ENDPOINT, SINGULAR_V2_COLLECTION_ENDPOINT, SINGULAR_V2_ENDPOINT } from '../config'; +const rmrkNftLogger = createLogger('RmrkNft'); + enum RMRK_SOURCE { BIRD_KANARIA = 'bird_kanaria', KANARIA = 'kanaria', @@ -160,7 +163,7 @@ export class RmrkNftApi extends BaseNftApi { } } } catch (e) { - console.log('error fetching RMRK NFT', e); + rmrkNftLogger.error('Error fetching RMRK NFT', e); } })); @@ -270,7 +273,7 @@ export class RmrkNftApi extends BaseNftApi { allCollectionMeta[item?.id as string] = { ...data }; } } catch (e) { - console.error(item.url, e); + rmrkNftLogger.error(`Error fetching RMRK NFT collection metadata for ${item.url}`, e); } })); @@ -297,7 +300,7 @@ export class RmrkNftApi extends BaseNftApi { params.updateCollection(this.chain, parsedCollection); }); } catch (e) { - console.error(`${this.chain}`, e); + rmrkNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/story_odyssey_nft/index.ts b/packages/extension-base/src/koni/api/nft/story_odyssey_nft/index.ts index 1af814a68a2..1afe347fd7a 100644 --- a/packages/extension-base/src/koni/api/nft/story_odyssey_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/story_odyssey_nft/index.ts @@ -2,10 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { NftCollection, NftItem } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ODYSSEY_ENDPOINT } from '../config'; import { BaseNftApi, HandleNftParams } from '../nft'; +const storyOdysseyNftLogger = createLogger('StoryOdysseyNft'); + interface OdysseyTokenMetadata { name: string; image: string; @@ -92,7 +95,7 @@ export class OdysseyNftApi extends BaseNftApi { return result.data.odyssey.erc721_token; } catch (err) { - console.error('Error:', err); + storyOdysseyNftLogger.error('Error fetching Odyssey NFT', err); return null; } @@ -104,7 +107,7 @@ export class OdysseyNftApi extends BaseNftApi { return (await response.json()) as UrlMetadata; } catch (err) { - console.error('Error:', err); + storyOdysseyNftLogger.error('Error fetching URL metadata', err); return null; } diff --git a/packages/extension-base/src/koni/api/nft/ternoa_nft/index.ts b/packages/extension-base/src/koni/api/nft/ternoa_nft/index.ts index 117fefc3c1a..b2e7bd6583e 100644 --- a/packages/extension-base/src/koni/api/nft/ternoa_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/ternoa_nft/index.ts @@ -4,10 +4,13 @@ import { NftCollection, NftItem } from '@subwallet/extension-base/background/KoniTypes'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { baseParseIPFSUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { decodeAddress, encodeAddress } from '@polkadot/util-crypto'; import { TERNOA_MAINNET_CLIENT_NFT, TERNOA_MAINNET_GATEWAY } from '../config'; + +const ternoaNftLogger = createLogger('TernoaNft'); import { BaseNftApi, HandleNftParams } from '../nft'; interface NftMetadata { @@ -104,7 +107,7 @@ export class TernoaNftApi extends BaseNftApi { return { metadata: nft, detail: nftDetail }; } catch (err) { - console.error('Error:', err); + ternoaNftLogger.error('Error fetching NFT detail', err); return null; } @@ -112,7 +115,7 @@ export class TernoaNftApi extends BaseNftApi { return nftDetails.filter((nft) => nft !== null) as Array<{ metadata: NftMetadata; detail: NftDetail }>; } catch (err) { - console.error('Error:', err); + ternoaNftLogger.error('Error fetching NFT details', err); return null; } @@ -152,7 +155,7 @@ export class TernoaNftApi extends BaseNftApi { return collectionDetail; } catch (err) { - console.error('Error:', err); + ternoaNftLogger.error('Error fetching collection detail', err); return null; } diff --git a/packages/extension-base/src/koni/api/nft/transfer.ts b/packages/extension-base/src/koni/api/nft/transfer.ts index 2e2fd60154a..640649a389d 100644 --- a/packages/extension-base/src/koni/api/nft/transfer.ts +++ b/packages/extension-base/src/koni/api/nft/transfer.ts @@ -5,6 +5,9 @@ import { AssetHubNftType } from '@subwallet/extension-base/background/KoniTypes' import { SUPPORTED_TRANSFER_SUBSTRATE_CHAIN_NAME } from '@subwallet/extension-base/koni/api/nft/config'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { reformatAddress } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const nftTransferLogger = createLogger('NftTransfer'); interface CollectionInfo { limits: { @@ -23,7 +26,7 @@ export function acalaGetExtrinsic (substrateApi: _SubstrateApi, senderAddress: s return substrateApi.api.tx.nft.transfer(recipientAddress, [collectionId, itemId]); } catch (e) { - console.error(e); + nftTransferLogger.error('Error in acalaGetExtrinsic', e); return null; } @@ -44,7 +47,7 @@ export function rmrkGetExtrinsic (substrateApi: _SubstrateApi, senderAddress: st return substrateApi.api.tx.system.remark(parsedRemark); } catch (e) { - console.error(e); + nftTransferLogger.error('Error in rmrkGetExtrinsic', e); return null; } @@ -67,7 +70,7 @@ export async function uniqueGetExtrinsic (substrateApi: _SubstrateApi, senderAdd return null; } } catch (e) { - console.error(e); + nftTransferLogger.error('Error in uniqueGetExtrinsic', e); return null; } @@ -87,7 +90,7 @@ export function assetHubGetExtrinsic (substrateApi: _SubstrateApi, senderAddress return null; } catch (e) { - console.error(e); + nftTransferLogger.error('Error in assetHubGetExtrinsic', e); return null; } diff --git a/packages/extension-base/src/koni/api/nft/unique_network_nft/index.ts b/packages/extension-base/src/koni/api/nft/unique_network_nft/index.ts index 811b8ac9c73..af2c23604b2 100644 --- a/packages/extension-base/src/koni/api/nft/unique_network_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/unique_network_nft/index.ts @@ -6,9 +6,12 @@ import { OPAL_SCAN_ENDPOINT, QUARTZ_SCAN_ENDPOINT, UNIQUE_IPFS_GATEWAY, UNIQUE_S import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _NFT_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants'; import { baseParseIPFSUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { decodeAddress, encodeAddress } from '@polkadot/util-crypto'; +const uniqueNetworkNftLogger = createLogger('UniqueNetworkNft'); + interface NftAttribute { trait_type: string; value: any; @@ -160,7 +163,7 @@ export class UniqueNftApi extends BaseNftApi { } })); } catch (e) { - console.error(`Failed to fetch ${this.chain} nft`, e); + uniqueNetworkNftLogger.error(`Failed to fetch ${this.chain} nft`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/unique_nft/index.ts b/packages/extension-base/src/koni/api/nft/unique_nft/index.ts index 9b15376e2a2..3b92f31866e 100644 --- a/packages/extension-base/src/koni/api/nft/unique_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/unique_nft/index.ts @@ -5,9 +5,12 @@ import { NftCollection, NftItem } from '@subwallet/extension-base/background/Kon import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { hexToStr, hexToUTF16, utf16ToString } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { deserializeNft } from './protobuf'; +const uniqueNftLogger = createLogger('UniqueNft'); + interface Collection { SchemaVersion: string, OffchainSchema: string, @@ -209,7 +212,7 @@ export default class UniqueNftApi extends BaseNftApi { })); })); } catch (e) { - console.error(`${this.chain}`, e); + uniqueNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/unique_nft/protobuf.ts b/packages/extension-base/src/koni/api/nft/unique_nft/protobuf.ts index 71f6459c9eb..60597c78e78 100644 --- a/packages/extension-base/src/koni/api/nft/unique_nft/protobuf.ts +++ b/packages/extension-base/src/koni/api/nft/unique_nft/protobuf.ts @@ -3,12 +3,16 @@ import { Root } from 'protobufjs'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const uniqueProtobufLogger = createLogger('UniqueProtobuf'); + function defineMessage (schema: string) { try { // eslint-disable-next-line @typescript-eslint/no-unsafe-argument return Root.fromJSON(JSON.parse(schema)); } catch (e) { - console.log('Error parsing JSON schema', e); + uniqueProtobufLogger.error('Error parsing JSON schema', e); return null; } @@ -32,7 +36,7 @@ function convertEnumToString (value: any, key: string, NFTMeta: any, locale: any result = translationObject[locale]; } } catch (e) { - console.log('Error parsing schema when trying to convert enum to string: ', e); + uniqueProtobufLogger.error('Error parsing schema when trying to convert enum to string', e); } // eslint-disable-next-line @typescript-eslint/no-unsafe-return diff --git a/packages/extension-base/src/koni/api/nft/unique_nft/uniqueNftV2.ts b/packages/extension-base/src/koni/api/nft/unique_nft/uniqueNftV2.ts index 71f677e8c0a..8094a8b05af 100644 --- a/packages/extension-base/src/koni/api/nft/unique_nft/uniqueNftV2.ts +++ b/packages/extension-base/src/koni/api/nft/unique_nft/uniqueNftV2.ts @@ -3,6 +3,9 @@ import { UNIQUE_SCAN_ENDPOINT } from '@subwallet/extension-base/koni/api/nft/config'; import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const uniqueNftV2Logger = createLogger('UniqueNftV2'); interface NftData { collection_id: number; @@ -57,7 +60,7 @@ export class UniqueNftApiV2 extends BaseNftApi { allNfts = allNfts.concat(nfts); })); } catch (e) { - console.error(`Failed to fetch ${this.chain} nft`, e); + uniqueNftV2Logger.error(`Failed to fetch ${this.chain} nft`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/vara_nft/index.ts b/packages/extension-base/src/koni/api/nft/vara_nft/index.ts index 97e5e638e6f..ffe307b5f95 100644 --- a/packages/extension-base/src/koni/api/nft/vara_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/vara_nft/index.ts @@ -4,8 +4,11 @@ import { NftCollection, NftItem } from '@subwallet/extension-base/background/KoniTypes'; import { VARA_SCAN_ENDPOINT } from '@subwallet/extension-base/koni/api/nft/config'; import { BaseNftApi, HandleNftParams } from '@subwallet/extension-base/koni/api/nft/nft'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { hexAddPrefix, u8aToHex } from '@polkadot/util'; + +const varaNftLogger = createLogger('VaraNft'); import { decodeAddress } from '@polkadot/util-crypto'; interface NftData { @@ -109,7 +112,7 @@ export class VaraNftApi extends BaseNftApi { } })); } catch (e) { - console.error(`Failed to fetch ${this.chain} nft`, e); + varaNftLogger.error(`Failed to fetch ${this.chain} nft`, e); } } diff --git a/packages/extension-base/src/koni/api/nft/wasm_nft/index.ts b/packages/extension-base/src/koni/api/nft/wasm_nft/index.ts index 3d05cde7dcf..9c0693b764f 100644 --- a/packages/extension-base/src/koni/api/nft/wasm_nft/index.ts +++ b/packages/extension-base/src/koni/api/nft/wasm_nft/index.ts @@ -11,8 +11,11 @@ import { collectionApiFromArtZero, collectionDetailApiFromArtZero, externalUrlOn import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils'; import { isUrl } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ApiPromise } from '@polkadot/api'; + +const wasmNftLogger = createLogger('WasmNft'); import { ContractPromise } from '@polkadot/api-contract'; import { isEthereumAddress } from '@polkadot/util-crypto'; @@ -42,7 +45,7 @@ async function isArtZeroFeaturedCollection (networkKey: string, contractAddress: body: urlencoded }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((e) => wasmNftLogger.error('Error fetching collection info', e)); }); const collectionInfo = await Promise.race([ @@ -425,7 +428,7 @@ export class WasmNftApi extends BaseNftApi { tokenUri = ((tokenUriObj.ok || tokenUriObj.Ok) as string[])[0]; } } catch (e) { - console.debug(e); + wasmNftLogger.debug('Error getting token URI', e); } if (!tokenUri) { @@ -468,7 +471,7 @@ export class WasmNftApi extends BaseNftApi { nftOwnerMap[address] = nftIds; } catch (e) { - console.error(`${this.chain}`, e); + wasmNftLogger.error(`Error handling NFTs for chain ${this.chain}`, e); } })); diff --git a/packages/extension-base/src/koni/api/staking/bonding/astar.ts b/packages/extension-base/src/koni/api/staking/bonding/astar.ts index cc308c5a09d..08986013f92 100644 --- a/packages/extension-base/src/koni/api/staking/bonding/astar.ts +++ b/packages/extension-base/src/koni/api/staking/bonding/astar.ts @@ -14,6 +14,10 @@ import { Codec } from '@polkadot/types/types'; import { BN, BN_ZERO } from '@polkadot/util'; import { isEthereumAddress } from '@polkadot/util-crypto'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const astarStakingLogger = createLogger('AstarStaking'); + const convertAddress = (address: string) => { return isEthereumAddress(address) ? address.toLowerCase() : address; }; @@ -24,7 +28,7 @@ const fetchDApps = async (network: string) => { method: 'GET' }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((e) => astarStakingLogger.error('Error fetching dApps', e)); }); }; @@ -55,7 +59,7 @@ export async function getAstarStakingMetadata (chain: string, substrateApi: _Sub method: 'GET' }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((e) => astarStakingLogger.error('Error fetching APR', e)); }); const timeout = new Promise((resolve) => { diff --git a/packages/extension-base/src/koni/api/staking/bonding/utils.ts b/packages/extension-base/src/koni/api/staking/bonding/utils.ts index 47b9b88b3a8..82bd1158c9d 100644 --- a/packages/extension-base/src/koni/api/staking/bonding/utils.ts +++ b/packages/extension-base/src/koni/api/staking/bonding/utils.ts @@ -18,6 +18,10 @@ import { ApiPromise } from '@polkadot/api'; import { Codec } from '@polkadot/types/types'; import { BN, BN_BILLION, BN_HUNDRED, BN_MILLION, BN_THOUSAND, BN_ZERO, bnToU8a, stringToU8a, u8aConcat } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const stakingBondingUtilsLogger = createLogger('StakingBondingUtils'); + export interface PalletDappsStakingDappInfo { address: string, name: string, @@ -264,7 +268,7 @@ export async function calculateAnalogChainStakedReturn (): Promise, chain: string, stakingCallback: (networkKey: string, rs: StakingItem) => void, nominatorStateCallback: (rs: NominatorMetadata) => void) { const { symbol } = _getChainNativeTokenBasicInfo(chainInfoMap[chain]); @@ -178,6 +182,6 @@ export async function getNominationPoolReward (addresses: string[], chainInfoMap } })); } catch (e) { - console.debug(e); + relayChainStakingLogger.debug('Error in getRelayStakingOnChain', e); } } diff --git a/packages/extension-base/src/koni/api/staking/subsquidStaking.ts b/packages/extension-base/src/koni/api/staking/subsquidStaking.ts index 8936d3ae159..b4b6bfe2995 100644 --- a/packages/extension-base/src/koni/api/staking/subsquidStaking.ts +++ b/packages/extension-base/src/koni/api/staking/subsquidStaking.ts @@ -6,9 +6,12 @@ import { APIItemState, StakingRewardItem, StakingType } from '@subwallet/extensi import { INDEXER_SUPPORTED_STAKING_CHAINS, SUBSQUID_ENDPOINTS } from '@subwallet/extension-base/koni/api/staking/config'; import { _getChainSubstrateAddressPrefix, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils'; import { fetchJson, reformatAddress } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isEthereumAddress } from '@polkadot/util-crypto'; +const subsquidStakingLogger = createLogger('SubsquidStaking'); + interface RewardResponseItem { amount: string, blockNumber: string @@ -85,7 +88,7 @@ const getSubsquidStaking = async (accounts: string[], chain: string, chainInfoMa } } } catch (e) { - console.error(e); + subsquidStakingLogger.error('Error processing staking reward item', e); } if (stakingRewardItem.totalReward && parseFloat(stakingRewardItem.totalReward) > 0) { @@ -94,7 +97,7 @@ const getSubsquidStaking = async (accounts: string[], chain: string, chainInfoMa } })); } catch (e) { - console.debug(e); + subsquidStakingLogger.debug('Error in getSubsquidStaking', e); } }; @@ -112,6 +115,6 @@ export const getAllSubsquidStaking = async (accounts: string[], chainInfoMap: Re await getSubsquidStaking(accounts, network, chainInfoMap, callback); })); } catch (e) { - console.debug(e); + subsquidStakingLogger.debug('Error in getAllSubsquidStaking', e); } }; diff --git a/packages/extension-base/src/koni/background/cron.ts b/packages/extension-base/src/koni/background/cron.ts index 2ef0c6c0786..c7e3e5f6c02 100644 --- a/packages/extension-base/src/koni/background/cron.ts +++ b/packages/extension-base/src/koni/background/cron.ts @@ -11,8 +11,12 @@ import DatabaseService from '@subwallet/extension-base/services/storage-service/ import { waitTimeout } from '@subwallet/extension-base/utils'; import { Subject, Subscription } from 'rxjs'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + import KoniState from './handlers/State'; +const koniCronLogger = createLogger('KoniCron'); + export class KoniCron { subscriptions: KoniSubscription; public status: 'pending' | 'running' | 'stopped' = 'pending'; @@ -205,12 +209,12 @@ export class KoniCron { syncMantaPay = () => { if (this.state.isMantaPayEnabled) { - this.state.syncMantaPay().catch(console.warn); + this.state.syncMantaPay().catch((e) => koniCronLogger.warn('Error syncing MantaPay', e)); } }; fetchPoolInfo = () => { - this.state.earningService.runSubscribePoolsInfo().catch(console.error); + this.state.earningService.runSubscribePoolsInfo().catch((e) => koniCronLogger.error('Error fetching pool info', e)); }; fetchMktCampaignData = () => { @@ -242,13 +246,13 @@ export class KoniCron { addresses = this.state.keyringService.context.getDecodedAddresses(); if (!addresses.length) { - console.warn('[Cron] No decoded addresses found for ALL_ACCOUNT_KEY'); + koniCronLogger.warn('No decoded addresses found for ALL_ACCOUNT_KEY'); return; } this.state.nftDetectionService.fetchEvmCollectionsWithPreview(addresses) - .catch((err) => console.warn(`[Cron] NFT detection failed for ${address}:`, err)); + .catch((err) => koniCronLogger.warn(`NFT detection failed for ${address}`, err)); }; }; @@ -270,7 +274,7 @@ export class KoniCron { public async reloadStaking () { const address = this.state.keyringService.context.currentAccount.proxyId; - console.log('reload staking', address); + koniCronLogger.debug('reload staking', address); await waitTimeout(1800); diff --git a/packages/extension-base/src/koni/background/handlers/Extension.ts b/packages/extension-base/src/koni/background/handlers/Extension.ts index c552d4df910..d22a0596203 100644 --- a/packages/extension-base/src/koni/background/handlers/Extension.ts +++ b/packages/extension-base/src/koni/background/handlers/Extension.ts @@ -28,6 +28,7 @@ import { getTuringCancelCompoundingExtrinsic, getTuringCompoundExtrinsic } from import { getPoolingBondingExtrinsic, getPoolingUnbondingExtrinsic, validatePoolBondingCondition, validateRelayUnbondingCondition } from '@subwallet/extension-base/koni/api/staking/bonding/relayChain'; import { YIELD_EXTRINSIC_TYPES } from '@subwallet/extension-base/koni/api/yield/helper/utils'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { RequestOptimalTransferProcess } from '@subwallet/extension-base/services/balance-service/helpers/process'; import { DEFAULT_CARDANO_TTL_OFFSET } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/consts'; import { isBounceableAddress } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/ton/utils'; @@ -96,6 +97,8 @@ export function isJsonPayload (value: SignerPayloadJSON | SignerPayloadRaw): val return (value as SignerPayloadJSON).genesisHash !== undefined; } +const logger = createLogger('KoniExtension'); + export default class KoniExtension { #lockTimeOut: NodeJS.Timer | undefined = undefined; readonly #koniState: KoniState; @@ -141,7 +144,7 @@ export default class KoniExtension { }; const updateLatestSession = (time: number) => { - SWStorage.instance.setItem(LATEST_SESSION, JSON.stringify({ remind: true, timeCalculate: time })).catch(console.error); + SWStorage.instance.setItem(LATEST_SESSION, JSON.stringify({ remind: true, timeCalculate: time })).catch((error) => logger.error('Failed to update latest session', error)); }; this.#koniState.settingService.getSettings(updateTimeAutoLock); @@ -275,7 +278,7 @@ export default class KoniExtension { const url = `${chrome.runtime.getURL('index.html')}#${path}${subPath || ''}${paramString}`; if (!ALLOWED_PATH.includes(path)) { - console.error('Not allowed to open the url:', url); + logger.error('Not allowed to open the url:', url); return false; } @@ -395,7 +398,7 @@ export default class KoniExtension { const subscription = combineLatest({ chainInfoMap: chainInfoMapObservable, tokenInfoMap: tokenInfoMapObservable, accountProxies: accountObservable, contacts: contactObservable }).subscribe(({ accountProxies, chainInfoMap, contacts, tokenInfoMap }) => { combineFunction(chainInfoMap, tokenInfoMap, accountProxies, contacts) .then((rs) => cb(rs)) - .catch(console.error); + .catch((error) => logger.error('Error combining chain info map', error)); }); this.createUnsubscriptionHandle(id, () => { @@ -1090,7 +1093,7 @@ export default class KoniExtension { return true; } catch (e) { - console.error(e); + logger.error('Error in validation', e); return false; } @@ -1572,7 +1575,7 @@ export default class KoniExtension { inputData.value = transferAmount.value; } - console.log('PSPT transaction', transaction.toHex()); + logger.info('PSPT transaction', transaction.toHex()); } else { const substrateApi = this.#koniState.getSubstrateApi(chain); @@ -1879,7 +1882,7 @@ export default class KoniExtension { autoEnableNativeToken: false, tokenSlug: destinationTokenInfo.slug, assetSetting: { visible: true } - }).catch(console.error); + }).catch((error) => logger.error('Error enabling token', error)); } } catch (e) { } @@ -2185,7 +2188,7 @@ export default class KoniExtension { try { return await this.#koniState.upsertChainInfo(data); } catch (e) { - console.error(e); + logger.error('Error upserting chain info', e); return false; } @@ -2224,7 +2227,7 @@ export default class KoniExtension { try { return this.#koniState.refreshSubstrateApi(networkKey); } catch (e) { - console.error(e); + logger.error('Error refreshing substrate API', e); return false; } @@ -2295,7 +2298,7 @@ export default class KoniExtension { error: '' }; } catch (e) { - console.error(e); + logger.error('Error in request handler', e); return { success: false, @@ -2403,7 +2406,7 @@ export default class KoniExtension { next: ({ fee, freeBalance }) => { calculateMaxTransferable(id, _request, freeBalance, fee) .then(cb) - .catch(console.error); + .catch((error) => logger.error('Error calculating max transferable', error)); } }); @@ -2544,7 +2547,7 @@ export default class KoniExtension { }; error = (e as Error).message || e as string; - console.warn('Unable to estimate fee', e); + logger.warn('Unable to estimate fee', e); } return { @@ -2563,7 +2566,7 @@ export default class KoniExtension { next: ({ fee, freeBalance }) => { convertData(freeBalance, fee, _feeOptions, feeCustom) .then(cb) - .catch(console.error); + .catch((error) => logger.error('Error converting data', error)); } }); @@ -3907,17 +3910,17 @@ export default class KoniExtension { await this.saveCurrentAccountProxy({ address }); const unsubSyncProgress = await this.#koniState.chainService?.mantaPay?.subscribeSyncProgress(); - console.debug('Start initial sync for MantaPay'); + logger.debug('Start initial sync for MantaPay'); this.#koniState.initialSyncMantaPay(address) .then(() => { - console.debug('Finished initial sync for MantaPay'); + logger.debug('Finished initial sync for MantaPay'); this.#skipAutoLock = false; unsubSyncProgress && unsubSyncProgress(); }) .catch((e) => { - console.error('Error syncing MantaPay', e); + logger.error('Error syncing MantaPay', e); this.#skipAutoLock = false; unsubSyncProgress && unsubSyncProgress(); @@ -3953,11 +3956,11 @@ export default class KoniExtension { await this.saveCurrentAccountProxy({ address }); const unsubSyncProgress = await this.#koniState.chainService?.mantaPay?.subscribeSyncProgress(); - console.debug('Start initial sync for MantaPay'); + logger.debug('Start initial sync for MantaPay'); this.#koniState.initialSyncMantaPay(address) .then(() => { - console.debug('Finished initial sync for MantaPay'); + logger.debug('Finished initial sync for MantaPay'); this.#skipAutoLock = false; unsubSyncProgress && unsubSyncProgress(); @@ -3968,7 +3971,7 @@ export default class KoniExtension { }); }) .catch((e) => { - console.error('Error syncing MantaPay', e); + logger.error('Error syncing MantaPay', e); this.#skipAutoLock = false; unsubSyncProgress && unsubSyncProgress(); @@ -3993,7 +3996,7 @@ export default class KoniExtension { return !isActive && isBounceable; } catch (error) { - console.error(`Failed to validate address ${address} on chain ${chain}:`, error); + logger.error(`Failed to validate address ${address} on chain ${chain}:`, error); return false; } @@ -4779,7 +4782,7 @@ export default class KoniExtension { this.#koniState.transactionService.updateProcessStepStatus(step, { status: StepStatus.FAILED }); } - console.log('Error handling process step', e); + logger.error('Error handling process step', e); throw e; } @@ -5167,7 +5170,7 @@ export default class KoniExtension { unsub = _unsub; onRs(rs); }) - .catch(console.error); + .catch((error) => logger.error('Error in subscription', error)); } }); } @@ -5190,7 +5193,7 @@ export default class KoniExtension { return { isPassConfirmation: true, signAfterCreate: (id: string) => { - this.signingApprovePasswordV2({ id }).catch(console.log); + this.signingApprovePasswordV2({ id }).catch((error) => logger.error('Error signing after create', error)); } }; } else { @@ -5269,7 +5272,7 @@ export default class KoniExtension { try { this.#koniState.inappNotificationService.migrateNotificationProxyId(proxyIds, newProxyId, newName); } catch (error) { - console.error('Error on migrating notification for unified account migration', error); + logger.error('Error on migrating notification for unified account migration', error); } return response; diff --git a/packages/extension-base/src/koni/background/handlers/Mobile.ts b/packages/extension-base/src/koni/background/handlers/Mobile.ts index 4411f77fd92..a1d9c267060 100644 --- a/packages/extension-base/src/koni/background/handlers/Mobile.ts +++ b/packages/extension-base/src/koni/background/handlers/Mobile.ts @@ -8,8 +8,11 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State' import { SWStorage } from '@subwallet/extension-base/storage'; import { isSupportWindow, listMerge } from '@subwallet/extension-base/utils'; import { createPromiseHandler } from '@subwallet/extension-base/utils/promise'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { DexieExportJsonStructure } from 'dexie-export-import'; +const mobileHandlerLogger = createLogger('MobileHandler'); + export function isLocalStorageReset (): boolean { if (isSupportWindow && window?.localStorage) { return !window.localStorage.getItem('keyring:subwallet'); @@ -62,14 +65,14 @@ export default class Mobile { if (!isLocalStorageReset()) { swStorage.copy().then((data) => { this.lastRestoreData.storage = data; - }).catch(console.error); + }).catch((e) => mobileHandlerLogger.error('Error copying storage', e)); } (async () => { if (!(await isIndexedDBReset())) { this.lastRestoreData.indexedDB = await state.dbService.getExportJson(); } - })().catch(console.error); + })().catch((e) => mobileHandlerLogger.error('Error getting export JSON', e)); } public ping (): string { @@ -79,7 +82,7 @@ export default class Mobile { public initCronAndSubscription ( { cron: { activeServices: activeCronServices, intervalMap: cronIntervalMap }, subscription: { activeServices: activeSubscriptionServices } }: RequestInitCronAndSubscription): ActiveCronAndSubscriptionMap { - console.log('initCronAndSubscription'); + mobileHandlerLogger.debug('initCronAndSubscription'); return { subscription: { @@ -104,39 +107,39 @@ export default class Mobile { } public startCronAndSubscriptionServices ({ cronServices, subscriptionServices }: RequestCronAndSubscriptionAction): void { - console.log('startCronAndSubscriptionServices'); + mobileHandlerLogger.debug('startCronAndSubscriptionServices'); } public stopCronAndSubscriptionServices ({ cronServices, subscriptionServices }: RequestCronAndSubscriptionAction): void { - console.log('stopCronAndSubscriptionServices'); + mobileHandlerLogger.debug('stopCronAndSubscriptionServices'); } public restartCronAndSubscriptionServices ({ cronServices, subscriptionServices }: RequestCronAndSubscriptionAction): void { - console.log('restartCronAndSubscriptionServices'); + mobileHandlerLogger.debug('restartCronAndSubscriptionServices'); } public startCronServices (services: CronServiceType[]): void { - console.log('startCronServices'); + mobileHandlerLogger.debug('startCronServices'); } public stopCronServices (services: CronServiceType[]): void { - console.log('stopCronServices'); + mobileHandlerLogger.debug('stopCronServices'); } public restartCronServices (services: CronServiceType[]): void { - console.log('stopCronServices'); + mobileHandlerLogger.debug('stopCronServices'); } public startSubscriptionServices (services: SubscriptionServiceType[]): void { - console.log('startSubscriptionServices'); + mobileHandlerLogger.debug('startSubscriptionServices'); } public stopSubscriptionServices (services: SubscriptionServiceType[]): void { - console.log('stopSubscriptionServices'); + mobileHandlerLogger.debug('stopSubscriptionServices'); } public restartSubscriptionServices (services: SubscriptionServiceType[]): void { - console.log('restartSubscriptionServices'); + mobileHandlerLogger.debug('restartSubscriptionServices'); } private async _getLocalStorageExportData (): Promise { diff --git a/packages/extension-base/src/koni/background/handlers/State.ts b/packages/extension-base/src/koni/background/handlers/State.ts index bac073fedca..1b8ea808272 100644 --- a/packages/extension-base/src/koni/background/handlers/State.ts +++ b/packages/extension-base/src/koni/background/handlers/State.ts @@ -63,6 +63,7 @@ import { BehaviorSubject, Subject } from 'rxjs'; import { JsonRpcResponse, ProviderInterface, ProviderInterfaceCallback } from '@polkadot/rpc-provider/types'; import { assert, logger as createLogger, noop } from '@polkadot/util'; import { Logger } from '@polkadot/util/types'; +import { createLogger as createExtensionLogger } from '@subwallet/extension-base/utils/logger'; import { isEthereumAddress } from '@polkadot/util-crypto'; import { KoniCron } from '../cron'; @@ -90,6 +91,8 @@ const generateDefaultCrowdloanMap = (): Record => { const DEFAULT_CURRENCY: CurrencyType = 'USD'; +const extensionLogger = createExtensionLogger('State'); + export default class KoniState { private injectedProviders = new Map(); private readonly providers: Providers; @@ -190,8 +193,8 @@ export default class KoniState { // Init state if (targetIsWeb) { this.init().then(() => { - this.wakeup(true).catch(console.error); - }).catch(console.error); + this.wakeup(true).catch((error) => extensionLogger.error('Error waking up state', error)); + }).catch((error) => extensionLogger.error('Error initializing state', error)); } } @@ -336,9 +339,9 @@ export default class KoniState { const mantaPayConfig = await this.chainService?.mantaPay?.getMantaPayFirstConfig(_DEFAULT_MANTA_ZK_CHAIN) as MantaPayConfig; if (mantaPayConfig && mantaPayConfig.enabled && !this.isMantaPayEnabled) { // only init the first login - console.debug('Initiating MantaPay for', mantaPayConfig.address); + extensionLogger.debug('Initiating MantaPay for', mantaPayConfig.address); await this.enableMantaPay(false, mantaPayConfig.address, password); - console.debug('Initiated MantaPay for', mantaPayConfig.address); + extensionLogger.debug('Initiated MantaPay for', mantaPayConfig.address); this.isMantaPayEnabled = true; this.eventService.emit('mantaPay.enable', mantaPayConfig.address); @@ -1225,7 +1228,7 @@ export default class KoniState { return await calculateGasFeeParams(web3Api, slug, false, false); } catch (e) { - console.error(e); + extensionLogger.error('Error calculating gas fee params', e); return null; } @@ -1821,7 +1824,7 @@ export default class KoniState { if (!migrationStatus || migrationStatus !== 'done') { if (!isManifestV3) { - this.migrateMV3LocalStorage(JSON.stringify(self.localStorage)).catch(console.error); + this.migrateMV3LocalStorage(JSON.stringify(self.localStorage)).catch((error) => extensionLogger.error('Error migrating MV3 localStorage', error)); } } } @@ -1852,11 +1855,11 @@ export default class KoniState { // Reload some services use SWStorage // wallet connect - this.walletConnectService.initClient().catch(console.error); + this.walletConnectService.initClient().catch((error) => extensionLogger.error('Error initializing wallet connect client', error)); return true; } catch (e) { - console.error(e); + extensionLogger.error('Error migrating MV3 localStorage', e); return false; } @@ -1874,10 +1877,10 @@ export default class KoniState { public onInstallOrUpdate (details: chrome.runtime.InstalledDetails) { // Open mv3 migration window if (details.reason === 'install') { - this.onMV3Install().catch(console.error); + this.onMV3Install().catch((error) => extensionLogger.error('Error on MV3 install', error)); } else if (details.reason === 'update') { - this.onMV3Update().catch(console.error); - this.storePreviousVersionData(details).catch(console.error); + this.onMV3Update().catch((error) => extensionLogger.error('Error on MV3 update', error)); + this.storePreviousVersionData(details).catch((error) => extensionLogger.error('Error storing previous version data', error)); } } @@ -1892,7 +1895,7 @@ export default class KoniState { openPopup(url) .then(noop) - .catch(console.error) + .catch((error) => extensionLogger.error('Error opening popup for remind export account', error)) .finally(() => subscription.unsubscribe()); } else { setTimeout(() => { @@ -1913,7 +1916,7 @@ export default class KoniState { return true; } catch (e) { - console.error(e); + extensionLogger.error('Error setting storage from WS', e); return false; } @@ -1923,7 +1926,7 @@ export default class KoniState { try { return await SWStorage.instance.getItem(key); } catch (e) { - console.error(e); + extensionLogger.error('Error getting storage from WS', e); return null; } @@ -1931,7 +1934,7 @@ export default class KoniState { public onCheckToRemindUser () { this.onHandleRemindExportAccount() - .catch(console.error); + .catch((error) => extensionLogger.error('Error checking to remind user', error)); } public onInstall () { @@ -2155,10 +2158,10 @@ export default class KoniState { const stores = this.dbService.stores; // Remove NFT - stores.nft.deleteNftByAddress([address]).catch(console.error); + stores.nft.deleteNftByAddress([address]).catch((error) => extensionLogger.error('Error deleting NFT by address', error)); // Remove Staking Data - stores.staking.removeAllByAddress(address).catch(console.error); + stores.staking.removeAllByAddress(address).catch((error) => extensionLogger.error('Error removing staking data by address', error)); }); } @@ -2371,7 +2374,7 @@ export default class KoniState { this.balanceService.setBalanceItem([balanceItem]); } }) - .catch(console.warn); + .catch((error) => extensionLogger.warn('Error getting Manta ZK balance', error)); } public subscribeMantaPayBalance () { @@ -2385,7 +2388,7 @@ export default class KoniState { interval = setInterval(this.getMantaZkBalance, MANTA_PAY_BALANCE_INTERVAL); } }) - .catch(console.warn); + .catch((error) => extensionLogger.warn('Error subscribing MantaPay balance', error)); return () => { interval && clearInterval(interval); diff --git a/packages/extension-base/src/koni/background/handlers/Tabs.ts b/packages/extension-base/src/koni/background/handlers/Tabs.ts index 52c17158cb3..62afb2be720 100644 --- a/packages/extension-base/src/koni/background/handlers/Tabs.ts +++ b/packages/extension-base/src/koni/background/handlers/Tabs.ts @@ -41,6 +41,10 @@ import { SignerPayloadJSON, SignerPayloadRaw } from '@polkadot/types/types'; import { hexStripPrefix, isArray, isNumber, u8aToHex } from '@polkadot/util'; import { isEthereumAddress } from '@polkadot/util-crypto'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const tabsHandlerLogger = createLogger('TabsHandler'); + interface AccountSub { subscription: Subscription; url: string; @@ -381,7 +385,7 @@ export default class KoniTabs { return cb(transformAccountsV2(accounts, false, authInfo, accountAuthTypes, true)); }) - .catch(console.error); + .catch((e) => tabsHandlerLogger.error('Error transforming accounts', e)); }), url }; @@ -461,7 +465,7 @@ export default class KoniTabs { } resolve(accounts); - }).catch(console.error); + }).catch((e) => tabsHandlerLogger.error('Error getting current account', e)); }); } @@ -495,7 +499,7 @@ export default class KoniTabs { if (web3?.currentProvider instanceof Web3.providers.WebsocketProvider) { if (!web3.currentProvider.connected) { - console.log(`${slug} is disconnected, trying to connect...`); + tabsHandlerLogger.debug(`${slug} is disconnected, trying to connect...`); this.#koniState.refreshWeb3Api(slug); let checkingNum = 0; @@ -503,15 +507,15 @@ export default class KoniTabs { checkingNum += 1; if ((web3.currentProvider as WebsocketProvider).connected) { - console.log(`${slug} is connected.`); + tabsHandlerLogger.debug(`${slug} is connected.`); resolve(true); } else { - console.log(`Connecting to network [${slug}]`); + tabsHandlerLogger.debug(`Connecting to network [${slug}]`); if (checkingNum < 10) { setTimeout(() => poll(resolve), 900); } else { - console.log(`Max retry, stop checking [${slug}]`); + tabsHandlerLogger.debug(`Max retry, stop checking [${slug}]`); resolve(false); } } @@ -902,7 +906,7 @@ export default class KoniTabs { const accountListSubscription = this.#koniState.keyringService.context.observable.currentAccount .subscribe(() => { - onCurrentAccountChanged().catch(console.error); + onCurrentAccountChanged().catch((e) => tabsHandlerLogger.error('Error on current account changed', e)); }); // Detect network chain @@ -931,7 +935,7 @@ export default class KoniTabs { const authUrlSubscription = this.#koniState.subscribeEvmChainChange() .subscribe((rs) => { - _onAuthChanged().catch(console.error); + _onAuthChanged().catch((e) => tabsHandlerLogger.error('Error on auth changed', e)); }); // Detect network connection @@ -947,8 +951,8 @@ export default class KoniTabs { isConnected = connecting; }) - .catch(console.error); - }).catch(console.error); + .catch((e) => tabsHandlerLogger.error('Error checking network connection', e)); + }).catch((e) => tabsHandlerLogger.error('Error in network check', e)); }; const networkCheckInterval = setInterval(networkCheck, CRON_GET_API_MAP_STATUS); @@ -1134,7 +1138,7 @@ export default class KoniTabs { if (e.code) { throw e; } else { - console.error(e); + tabsHandlerLogger.error('Error in performWeb3Method', e); throw new EvmProviderError(EvmProviderErrorType.INTERNAL_ERROR, e?.toString()); } } @@ -1612,7 +1616,7 @@ export default class KoniTabs { if (e.code) { throw e; } else { - console.error(e); + tabsHandlerLogger.error('Error in performBitcoinMethod', e); throw new BitcoinProviderError(BitcoinProviderErrorType.INTERNAL_ERROR, e?.toString()); } } diff --git a/packages/extension-base/src/koni/background/handlers/index.ts b/packages/extension-base/src/koni/background/handlers/index.ts index f76503906bb..385311bc5bf 100644 --- a/packages/extension-base/src/koni/background/handlers/index.ts +++ b/packages/extension-base/src/koni/background/handlers/index.ts @@ -11,6 +11,10 @@ import KoniTabs from '@subwallet/extension-base/koni/background/handlers/Tabs'; import { assert } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const swHandlerLogger = createLogger('SWHandler'); + export class SWHandler { _state?: KoniState; _extensionHandler?: KoniExtension; @@ -77,8 +81,7 @@ export class SWHandler { port.postMessage({ id, response, sender: 'BACKGROUND' }); }) .catch((error: ProviderError): void => { - console.error(error); - console.log(`[err] ${source}:: ${error.message}`); + swHandlerLogger.error(`[err] ${source}`, error); // only send message back to port if it's still connected if (port) { diff --git a/packages/extension-base/src/koni/background/subscription.ts b/packages/extension-base/src/koni/background/subscription.ts index c42c0cf6c09..1a33524caf2 100644 --- a/packages/extension-base/src/koni/background/subscription.ts +++ b/packages/extension-base/src/koni/background/subscription.ts @@ -112,7 +112,7 @@ export class KoniSubscription { this.state.resetCrowdloanMap(address).then(() => { this.updateSubscription('crowdloan', this.initCrowdloanSubscription(addresses, substrateApiMap, onlyRunOnFirstTime)); - }).catch(console.error); + }).catch((e) => this.logger.error('Error resetting crowdloan map', e)); } initCrowdloanSubscription (addresses: string[], substrateApiMap: Record, onlyRunOnFirstTime?: boolean) { diff --git a/packages/extension-base/src/koni/background/utils.ts b/packages/extension-base/src/koni/background/utils.ts index 3a7566fe155..70d18cf2155 100644 --- a/packages/extension-base/src/koni/background/utils.ts +++ b/packages/extension-base/src/koni/background/utils.ts @@ -11,8 +11,12 @@ import { Metadata, TypeRegistry } from '@polkadot/types'; import { ChainProperties } from '@polkadot/types/interfaces'; import { Registry, SignerPayloadJSON } from '@polkadot/types/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + import KoniState from './handlers/State'; +const registryUtilsLogger = createLogger('RegistryUtils'); + export interface RegistrySource{ registry: Registry, specVersion: string | number, @@ -74,7 +78,7 @@ export async function setupApiRegistry (chainInfo: _ChainInfo | undefined, koniS specVersion: apiSpecVersion }; } catch (e) { - console.error('Error in setupApiRegistry:', e); + registryUtilsLogger.error('Error in setupApiRegistry', e); return null; } @@ -82,7 +86,7 @@ export async function setupApiRegistry (chainInfo: _ChainInfo | undefined, koniS export async function setupDatabaseRegistry (chainInfo: _ChainInfo | undefined, payload: SignerPayloadJSON, koniState: KoniState): Promise { if (!chainInfo) { - console.warn('setupDatabaseRegistry: Missing chainInfo'); + registryUtilsLogger.warn('setupDatabaseRegistry: Missing chainInfo'); return null; } @@ -91,7 +95,7 @@ export async function setupDatabaseRegistry (chainInfo: _ChainInfo | undefined, const metadata = await koniState.chainService.getMetadataByHash(payload.genesisHash) as MetadataItem; if (!metadata?.genesisHash) { - console.warn('setupDatabaseRegistry: Metadata not found or invalid for genesisHash:', payload.genesisHash); + registryUtilsLogger.warn('setupDatabaseRegistry: Metadata not found or invalid for genesisHash', payload.genesisHash); return null; } @@ -108,7 +112,7 @@ export async function setupDatabaseRegistry (chainInfo: _ChainInfo | undefined, specVersion: metadata.specVersion }; } catch (e) { - console.error('setupDatabaseRegistry: Error setting up database registry:', e); + registryUtilsLogger.error('setupDatabaseRegistry: Error setting up database registry', e); return null; } @@ -133,7 +137,7 @@ export function setupDappRegistry (payload: SignerPayloadJSON, koniState: KoniSt specVersion: metadata.specVersion }); } catch (e) { - console.error('setupDappRegistry: Error setting up DApp registry:', e); + registryUtilsLogger.error('setupDappRegistry: Error setting up DApp registry', e); resolve(null); } diff --git a/packages/extension-base/src/page/evm/index.ts b/packages/extension-base/src/page/evm/index.ts index e2aacf3caa4..f89f297ff47 100644 --- a/packages/extension-base/src/page/evm/index.ts +++ b/packages/extension-base/src/page/evm/index.ts @@ -8,6 +8,9 @@ import type { RequestArguments } from 'web3-core'; import SafeEventEmitter from '@metamask/safe-event-emitter'; import { EvmProviderError } from '@subwallet/extension-base/background/errors/EvmProviderError'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const evmPageLogger = createLogger('EvmPage'); interface SendSyncJsonRpcRequest extends JsonRpcRequest { method: 'net_version'; @@ -57,7 +60,7 @@ export function createSubWalletEvmProvider (sendMessage: SendRequest, version: s emitter.emit(finalType, payload); } else { - console.warn('Can not handle event', type, payload); + evmPageLogger.warn('Can not handle event', type, payload); } }).then(() => { subscribeFlag = true; diff --git a/packages/extension-base/src/page/substrate/Accounts.ts b/packages/extension-base/src/page/substrate/Accounts.ts index 5bcda6cc2b1..aa583726781 100644 --- a/packages/extension-base/src/page/substrate/Accounts.ts +++ b/packages/extension-base/src/page/substrate/Accounts.ts @@ -4,8 +4,11 @@ import type { InjectedAccount, InjectedAccounts, Unsubcall } from '@subwallet/extension-inject/types'; import type { SendRequest } from '../types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + // External to class, this.# is not private enough (yet) let sendRequest: SendRequest; +const substrateAccountsLogger = createLogger('SubstrateAccounts'); export default class Accounts implements InjectedAccounts { constructor (_sendRequest: SendRequest) { @@ -23,11 +26,11 @@ export default class Accounts implements InjectedAccounts { .then((subId): void => { id = subId; }) - .catch(console.error); + .catch((e) => substrateAccountsLogger.error('Error subscribing to accounts', e)); return (): void => { id && sendRequest('pub(accounts.unsubscribe)', { id }) - .catch(console.error); + .catch((e) => substrateAccountsLogger.error('Error unsubscribing from accounts', e)); }; } } diff --git a/packages/extension-base/src/page/substrate/PostMessageProvider.ts b/packages/extension-base/src/page/substrate/PostMessageProvider.ts index b7901c4e4e5..543b04389e4 100644 --- a/packages/extension-base/src/page/substrate/PostMessageProvider.ts +++ b/packages/extension-base/src/page/substrate/PostMessageProvider.ts @@ -10,7 +10,10 @@ import EventEmitter from 'eventemitter3'; import { isUndefined, logger } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + const l = logger('PostMessageProvider'); +const postMessageProviderLogger = createLogger('PostMessageProvider'); type CallbackHandler = (error?: null | Error, value?: unknown) => void; @@ -64,7 +67,7 @@ export default class PostMessageProvider implements InjectedProvider { // eslint-disable-next-line @typescript-eslint/require-await public async connect (): Promise { // FIXME This should see if the extension's state's provider can disconnect - console.error('PostMessageProvider.disconnect() is not implemented.'); + postMessageProviderLogger.error('PostMessageProvider.connect() is not implemented.'); } /** @@ -73,7 +76,7 @@ export default class PostMessageProvider implements InjectedProvider { // eslint-disable-next-line @typescript-eslint/require-await public async disconnect (): Promise { // FIXME This should see if the extension's state's provider can disconnect - console.error('PostMessageProvider.disconnect() is not implemented.'); + postMessageProviderLogger.error('PostMessageProvider.disconnect() is not implemented.'); } /** diff --git a/packages/extension-base/src/page/substrate/index.ts b/packages/extension-base/src/page/substrate/index.ts index b1418ddfb7d..e3eefd56b98 100644 --- a/packages/extension-base/src/page/substrate/index.ts +++ b/packages/extension-base/src/page/substrate/index.ts @@ -9,6 +9,10 @@ import Metadata from './Metadata'; import PostMessageProvider from './PostMessageProvider'; import Signer from './Signer'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const substratePageLogger = createLogger('SubstratePage'); + export default class implements Injected { public readonly accounts: Accounts; @@ -26,7 +30,7 @@ export default class implements Injected { setInterval((): void => { sendRequest('pub(ping)', null).catch((): void => { - console.error('Extension unavailable, ping failed'); + substratePageLogger.error('Extension unavailable, ping failed'); }); }, 5_000 + Math.floor(Math.random() * 5_000)); } diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/bitcoin.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/bitcoin.ts index 8d32a050982..f4c754fe264 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/bitcoin.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/bitcoin.ts @@ -5,9 +5,12 @@ import { _AssetType } from '@subwallet/chain-list/types'; import { AddressBalanceResult, APIItemState, BitcoinBalanceMetadata } from '@subwallet/extension-base/background/KoniTypes'; import { BITCOIN_REFRESH_BALANCE_INTERVAL } from '@subwallet/extension-base/constants'; import { _BitcoinApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BalanceItem, SusbcribeBitcoinPalletBalance } from '@subwallet/extension-base/types'; import { filterAssetsByChainAndType } from '@subwallet/extension-base/utils'; +const balanceSubscribeBitcoinLogger = createLogger('BalanceSubscribeBitcoin'); + function getDefaultBalanceResult (): AddressBalanceResult { return { balance: '0', @@ -41,7 +44,7 @@ async function getBitcoinBalance (bitcoinApi: _BitcoinApi, addresses: string[]) bitcoinBalanceMetadata: bitcoinBalanceMetadata }; } catch (error) { - console.log('Error while fetching Bitcoin balances', error); + balanceSubscribeBitcoinLogger.error('Error while fetching Bitcoin balances', error); return getDefaultBalanceResult(); } @@ -72,7 +75,7 @@ export function subscribeBitcoinBalance (params: SusbcribeBitcoinPalletBalance): }); }) .catch((e) => { - console.error('Error on get Bitcoin balance with token bitcoin', e); + balanceSubscribeBitcoinLogger.error('Error on get Bitcoin balance with token bitcoin', e); return addresses.map((address): BalanceItem => { return { @@ -87,7 +90,7 @@ export function subscribeBitcoinBalance (params: SusbcribeBitcoinPalletBalance): .then((items) => { callback(items); }) - .catch(console.error); + .catch((error) => balanceSubscribeBitcoinLogger.error('Error in Bitcoin balance subscription', error)); }; const interval = setInterval(getBalance, BITCOIN_REFRESH_BALANCE_INTERVAL); diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/index.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/index.ts index d159c0ea2a7..c4159c33c08 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/index.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/index.ts @@ -4,12 +4,15 @@ import { _AssetType } from '@subwallet/chain-list/types'; import { APIItemState } from '@subwallet/extension-base/background/KoniTypes'; import { ASTAR_REFRESH_BALANCE_INTERVAL } from '@subwallet/extension-base/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { CardanoBalanceItem } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/types'; import { getCardanoAssetId } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/utils'; import { _CardanoApi } from '@subwallet/extension-base/services/chain-service/types'; import { BalanceItem, SusbcribeCardanoPalletBalance } from '@subwallet/extension-base/types'; import { filterAssetsByChainAndType, reformatAddress } from '@subwallet/extension-base/utils'; +const balanceSubscribeCardanoIndexLogger = createLogger('BalanceSubscribeCardano'); + async function getBalanceMap (addresses: string[], cardanoApi: _CardanoApi, isTestnet: boolean): Promise> { const addressBalanceMap: Record = {}; @@ -52,7 +55,7 @@ export function subscribeCardanoBalance (params: SusbcribeCardanoPalletBalance) callback(items); }); }) - .catch((e) => console.error('Error while fetching cardano balance', e)); + .catch((e) => balanceSubscribeCardanoIndexLogger.error('Error while fetching cardano balance', e)); } const interval = setInterval(getBalance, ASTAR_REFRESH_BALANCE_INTERVAL); diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/utils.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/utils.ts index 1b6c68ff016..4b45ce1e625 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/utils.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/cardano/utils.ts @@ -4,6 +4,9 @@ import { Transaction } from '@emurgo/cardano-serialization-lib-nodejs'; import { _ChainAsset } from '@subwallet/chain-list/types'; import { CardanoTxOutput } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const balanceSubscribeCardanoLogger = createLogger('BalanceSubscribeCardano'); export function getCardanoAssetId (chainAsset: _ChainAsset): string { return chainAsset.metadata?.cardanoId as string; @@ -46,7 +49,7 @@ export async function retryCardanoTxStatus (fn: () => Promise, options: } } - console.error('Cardano transaction timeout', lastError); // throw only last error, in case no successful result from fn() + balanceSubscribeCardanoLogger.error('Cardano transaction timeout', lastError); // throw only last error, in case no successful result from fn() return false; } diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/evm.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/evm.ts index e9fe5735f63..1eb21593413 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/evm.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/evm.ts @@ -8,12 +8,15 @@ import { getERC20Contract } from '@subwallet/extension-base/koni/api/contract-ha import { _BALANCE_CHAIN_GROUP } from '@subwallet/extension-base/services/chain-service/constants'; import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BalanceItem, SubscribeEvmPalletBalance } from '@subwallet/extension-base/types'; import { filterAssetsByChainAndType } from '@subwallet/extension-base/utils'; import { Contract } from 'web3-eth-contract'; import { BN } from '@polkadot/util'; +const balanceSubscribeEvmLogger = createLogger('BalanceSubscribeEvm'); + export function subscribeERC20Interval ({ addresses, assetMap, callback, chainInfo, evmApi }: SubscribeEvmPalletBalance): () => void { const chain = chainInfo.slug; let tokenList = filterAssetsByChainAndType(assetMap, chain, [_AssetType.ERC20]); @@ -39,7 +42,7 @@ export function subscribeERC20Interval ({ addresses, assetMap, callback, chainIn // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access return await contract.methods.balanceOf(address).call(); } catch (e) { - console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, e); + balanceSubscribeEvmLogger.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, e); return '0'; } @@ -57,7 +60,7 @@ export function subscribeERC20Interval ({ addresses, assetMap, callback, chainIn callback(items); } catch (err) { - console.log(tokenInfo.slug, err); + balanceSubscribeEvmLogger.debug(tokenInfo.slug, err); } }); }; @@ -101,7 +104,7 @@ export function subscribeEVMBalance (params: SubscribeEvmPalletBalance) { }); }) .catch((e) => { - console.error(`Error on get native balance with token ${nativeTokenSlug}`, e); + balanceSubscribeEvmLogger.error(`Error on get native balance with token ${nativeTokenSlug}`, e); return addresses.map((address): BalanceItem => { return { @@ -116,7 +119,7 @@ export function subscribeEVMBalance (params: SubscribeEvmPalletBalance) { .then((items) => { callback(items); }) - .catch(console.error) + .catch((error) => balanceSubscribeEvmLogger.error('Error in EVM balance subscription', error)) ; } diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/index.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/index.ts index ce1cac164c3..f9bf0e1cba6 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/index.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/index.ts @@ -10,10 +10,13 @@ import { _isPureBitcoinChain, _isPureCardanoChain, _isPureEvmChain, _isPureTonCh import { BalanceItem } from '@subwallet/extension-base/types'; import { filterAddressByChainInfo, filterAssetsByChainAndType } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { subscribeTonBalance } from './ton/ton'; import { subscribeEVMBalance } from './evm'; import { subscribeSubstrateBalance } from './substrate'; +const balanceSubscribeLogger = createLogger('BalanceSubscribe'); + const handleUnsupportedOrPendingAddresses = ( addresses: string[], chainSlug: string, @@ -150,7 +153,7 @@ export function subscribeBalance ( unsubList.forEach((subProm) => { subProm.then((unsub) => { unsub && unsub(); - }).catch(console.error); + }).catch((error) => balanceSubscribeLogger.error('Error in balance subscription', error)); }); }; } diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/equilibrium.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/equilibrium.ts index a37295224fe..24b1c20df39 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/equilibrium.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/equilibrium.ts @@ -4,6 +4,7 @@ import { SignedBalance } from '@equilab/api/genshiro/interfaces'; import { _AssetType } from '@subwallet/chain-list/types'; import { APIItemState } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { _getTokenOnChainAssetId } from '@subwallet/extension-base/services/chain-service/utils'; import { BalanceItem, SubscribeSubstratePalletBalance } from '@subwallet/extension-base/types'; import { filterAssetsByChainAndType } from '@subwallet/extension-base/utils'; @@ -11,6 +12,8 @@ import BigN from 'bignumber.js'; import { BN, BN_ZERO } from '@polkadot/util'; +const balanceSubscribeEquilibriumLogger = createLogger('BalanceSubscribeEquilibrium'); + type EqBalanceItem = [number, { positive: number }]; type EqBalanceV0 = { v0: { @@ -100,7 +103,7 @@ export const subscribeEqBalanceAccountPallet = async ({ addresses, assetMap, cal return unsub; } catch (err) { - console.warn(err); + balanceSubscribeEquilibriumLogger.warn('Error in equilibrium balance subscription', err); const items: BalanceItem[] = addresses.map((address) => { return { @@ -122,7 +125,7 @@ export const subscribeEqBalanceAccountPallet = async ({ addresses, assetMap, cal unsubList.forEach((subProm) => { subProm.then((unsub) => { unsub && unsub(); - }).catch(console.error); + }).catch((error) => balanceSubscribeEquilibriumLogger.error('Error in equilibrium balance subscription', error)); }); }; }; diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/gear.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/gear.ts index f3ba1362948..0b380b2d1f8 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/gear.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/gear.ts @@ -5,10 +5,13 @@ import { GearApi } from '@gear-js/api'; import { _AssetType } from '@subwallet/chain-list/types'; import { APIItemState } from '@subwallet/extension-base/background/KoniTypes'; import { SUB_TOKEN_REFRESH_BALANCE_INTERVAL } from '@subwallet/extension-base/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils'; import { BalanceItem, SubscribeSubstratePalletBalance } from '@subwallet/extension-base/types'; import { filterAssetsByChainAndType, getGRC20ContractPromise, getVFTContractPromise, GRC20, VFT } from '@subwallet/extension-base/utils'; +const balanceSubscribeGearLogger = createLogger('BalanceSubscribeGear'); + import { noop, u8aToHex } from '@polkadot/util'; import { decodeAddress } from '@polkadot/util-crypto'; @@ -20,7 +23,7 @@ export const subscribeGRC20Balance = ({ addresses, const apiPromise = substrateApi.api; if (!(apiPromise instanceof GearApi)) { - console.warn('Cannot subscribe GRC20 balance without GearApi instance'); + balanceSubscribeGearLogger.warn('Cannot subscribe GRC20 balance without GearApi instance'); return noop; } @@ -50,7 +53,7 @@ export const subscribeGRC20Balance = ({ addresses, state: APIItemState.READY }; } catch (err) { - console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err); + balanceSubscribeGearLogger.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err); return { address: address, @@ -64,7 +67,7 @@ export const subscribeGRC20Balance = ({ addresses, callback(balances); } catch (err) { - console.warn(tokenInfo.slug, err); // TODO: error createType + balanceSubscribeGearLogger.warn(`Error for token ${tokenInfo.slug}`, err); // TODO: error createType } }); }; @@ -86,7 +89,7 @@ export const subscribeVftBalance = ({ addresses, const apiPromise = substrateApi.api; if (!(apiPromise instanceof GearApi)) { - console.warn('Cannot subscribe VFT balance without GearApi instance'); + balanceSubscribeGearLogger.warn('Cannot subscribe VFT balance without GearApi instance'); return noop; } @@ -116,7 +119,7 @@ export const subscribeVftBalance = ({ addresses, state: APIItemState.READY }; } catch (err) { - console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err); + balanceSubscribeGearLogger.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err); return { address: address, @@ -130,7 +133,7 @@ export const subscribeVftBalance = ({ addresses, callback(balances); } catch (err) { - console.warn(tokenInfo.slug, err); // TODO: error createType + balanceSubscribeGearLogger.warn(`Error for token ${tokenInfo.slug}`, err); // TODO: error createType } }); }; diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/index.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/index.ts index da2fb7c8b75..8a144e8942c 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/index.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/substrate/index.ts @@ -25,11 +25,14 @@ import { timer } from 'rxjs'; import { ContractPromise } from '@polkadot/api-contract'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { subscribeERC20Interval } from '../evm'; import { subscribeEquilibriumTokenBalance } from './equilibrium'; import { subscribeGRC20Balance, subscribeVftBalance } from './gear'; import { buildLockedDetails, getSpecialStakingBalances } from './utils'; +const balanceSubscribeSubstrateLogger = createLogger('BalanceSubscribeSubstrate'); + export const subscribeSubstrateBalance = async (addresses: string[], chainInfo: _ChainInfo, assetMap: Record, substrateApi: _SubstrateApi, evmApi: _EvmApi, callback: (rs: BalanceItem[]) => void, extrinsicType?: ExtrinsicType) => { let unsubNativeToken: () => void; let unsubLocalToken: () => void; @@ -108,7 +111,7 @@ export const subscribeSubstrateBalance = async (addresses: string[], chainInfo: unsubVftToken = subscribeVftBalance(substrateParams); } } catch (err) { - console.warn(err); + balanceSubscribeSubstrateLogger.warn('Error in substrate balance subscription', err); } return () => { @@ -323,7 +326,7 @@ const subscribeForeignAssetBalance = async ({ addresses, assetMap, callback, cha }); } } catch (err) { - console.warn(err); + balanceSubscribeSubstrateLogger.warn('Error in substrate balance subscription', err); } return undefined; @@ -376,7 +379,7 @@ const subscribePSP22Balance = ({ addresses, assetMap, callback, chainInfo, subst state: APIItemState.READY }; } catch (err) { - console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err); + balanceSubscribeSubstrateLogger.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, err); return { address: address, @@ -390,7 +393,7 @@ const subscribePSP22Balance = ({ addresses, assetMap, callback, chainInfo, subst callback(balances); } catch (err) { - console.warn(tokenInfo.slug, err); // TODO: error createType + balanceSubscribeSubstrateLogger.warn(`Error for token ${tokenInfo.slug}`, err); // TODO: error createType } }); }; @@ -419,7 +422,7 @@ const subscribeTokensAccountsPallet = async ({ addresses, assetMap, callback, ch callback(gigaTokenBalances); }; - getGigaTokenBalance().catch(console.error); + getGigaTokenBalance().catch((error) => balanceSubscribeSubstrateLogger.error('Error getting Giga token balance', error)); }); } @@ -452,7 +455,7 @@ const subscribeTokensAccountsPallet = async ({ addresses, assetMap, callback, ch callback(items); }); } catch (err) { - console.warn(err); + balanceSubscribeSubstrateLogger.warn('Error in substrate balance subscription', err); } return undefined; @@ -524,7 +527,7 @@ const subscribeAssetsAccountPallet = async ({ addresses, assetMap, callback, cha callback(items); }); } catch (err) { - console.warn(err); + balanceSubscribeSubstrateLogger.warn('Error in substrate balance subscription', err); } return undefined; @@ -573,7 +576,7 @@ const subscribeOrmlTokensPallet = async ({ addresses, assetMap, callback, chainI callback(items); }); } catch (err) { - console.warn(err); + balanceSubscribeSubstrateLogger.warn('Error in substrate balance subscription', err); return undefined; } @@ -635,10 +638,10 @@ const subscribeSubnetAlphaPallet = async ({ addresses, assetMap, callback, chain } }; - getTokenBalances().catch(console.error); + getTokenBalances().catch((error) => balanceSubscribeSubstrateLogger.error('Error getting token balances', error)); const interval = setInterval(() => { - getTokenBalances().catch(console.error); + getTokenBalances().catch((error) => balanceSubscribeSubstrateLogger.error('Error getting token balances', error)); }, SUB_TOKEN_REFRESH_BALANCE_INTERVAL); return () => { diff --git a/packages/extension-base/src/services/balance-service/helpers/subscribe/ton/ton.ts b/packages/extension-base/src/services/balance-service/helpers/subscribe/ton/ton.ts index 08ce13b9cb1..674994fc092 100644 --- a/packages/extension-base/src/services/balance-service/helpers/subscribe/ton/ton.ts +++ b/packages/extension-base/src/services/balance-service/helpers/subscribe/ton/ton.ts @@ -7,11 +7,14 @@ import { ASTAR_REFRESH_BALANCE_INTERVAL, SUB_TOKEN_REFRESH_BALANCE_INTERVAL } fr import { getJettonMasterContract, getJettonWalletContract } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/ton/utils'; import { _TonApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BalanceItem, SubscribeTonPalletBalance } from '@subwallet/extension-base/types'; import { filterAssetsByChainAndType } from '@subwallet/extension-base/utils'; import { Address } from '@ton/core'; import { JettonMaster, OpenedContract } from '@ton/ton'; +const balanceSubscribeTonLogger = createLogger('BalanceSubscribeTon'); + export function subscribeJettonBalanceInterval ({ addresses, assetMap, callback, chainInfo, tonApi }: SubscribeTonPalletBalance): () => void { const chain = chainInfo.slug; const tokenList = filterAssetsByChainAndType(assetMap, chain, [_AssetType.TEP74]); @@ -31,7 +34,7 @@ export function subscribeJettonBalanceInterval ({ addresses, assetMap, callback, return await jettonWalletContract.getBalance(); } catch (e) { - console.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, e); + balanceSubscribeTonLogger.error(`Error on get balance of account ${address} for token ${tokenInfo.slug}`, e); return BigInt(0); } @@ -49,7 +52,7 @@ export function subscribeJettonBalanceInterval ({ addresses, assetMap, callback, callback(items); } catch (err) { - console.log(tokenInfo.slug, err); + balanceSubscribeTonLogger.debug(tokenInfo.slug, err); } }); }; @@ -95,7 +98,7 @@ export function subscribeTonBalance (params: SubscribeTonPalletBalance) { }); }) .catch((e) => { - console.error(`Error on get native balance with token ${nativeTokenSlug}`, e); + balanceSubscribeTonLogger.error(`Error on get native balance with token ${nativeTokenSlug}`, e); return addresses.map((address): BalanceItem => { return { @@ -108,7 +111,7 @@ export function subscribeTonBalance (params: SubscribeTonPalletBalance) { }); }) .then((items) => callback(items)) - .catch(console.error); + .catch((error) => balanceSubscribeTonLogger.error('Error in TON balance subscription', error)); } getBalance(); diff --git a/packages/extension-base/src/services/balance-service/index.ts b/packages/extension-base/src/services/balance-service/index.ts index 0f47a4d4f07..3ab7c6f2588 100644 --- a/packages/extension-base/src/services/balance-service/index.ts +++ b/packages/extension-base/src/services/balance-service/index.ts @@ -22,8 +22,11 @@ import { t } from 'i18next'; import { BehaviorSubject } from 'rxjs'; import { noop } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { _BALANCE_CHAIN_GROUP } from '../chain-service/constants'; + +const balanceServiceLogger = createLogger('BalanceService'); import { CreateXcmExtrinsicProps } from './transfer/xcm'; import { _isAcrossChainBridge, getAcrossQuote } from './transfer/xcm/acrossBridge'; import { BalanceMapImpl } from './BalanceMapImpl'; @@ -178,7 +181,7 @@ export class BalanceService implements StoppableServiceInterface { if (needReload) { addLazy('reloadBalanceByEvents', () => { if (!this.isReload && this.isStarted) { - this.runSubscribeBalances().catch(console.error); + this.runSubscribeBalances().catch((error) => balanceServiceLogger.error('Error running subscribe balances', error)); } }, lazyTime, undefined, true); } @@ -424,7 +427,7 @@ export class BalanceService implements StoppableServiceInterface { * Store balance map to db * */ private updateBalanceStore (items: BalanceItem[]) { - this.state.dbService.updateBulkBalanceStore(items).catch(console.warn); + this.state.dbService.updateBulkBalanceStore(items).catch((error) => balanceServiceLogger.warn('Error updating bulk balance store', error)); } /** @@ -486,7 +489,7 @@ export class BalanceService implements StoppableServiceInterface { const chainInfoMap = this.state.chainService.getChainInfoMap(); if (!chainInfoMap[chain]) { - console.warn(`Chain ${chain} is not supported`); + balanceServiceLogger.warn(`Chain ${chain} is not supported`); return; } @@ -549,7 +552,7 @@ export class BalanceService implements StoppableServiceInterface { if (typeValid) { return this.state.subscanService.getMultiChainBalance(address) .catch((e) => { - console.error(e); + balanceServiceLogger.error('Error in balance service operation', e); return null; }); @@ -565,7 +568,7 @@ export class BalanceService implements StoppableServiceInterface { if (typeValid) { return subwalletApiSdk.balanceDetectionApi.getSwEvmTokenBalance(address) .catch((e) => { - console.error(e); + balanceServiceLogger.error('Error in balance service operation', e); return null; }); @@ -757,7 +760,7 @@ export class BalanceService implements StoppableServiceInterface { const evmPromiseList = addresses.map((address) => { return subwalletApiSdk.balanceDetectionApi.getSwEvmTokenBalance(address) .catch((e) => { - console.error(e); + balanceServiceLogger.error('Error detecting EVM balance token', e); return null; }); @@ -794,7 +797,7 @@ export class BalanceService implements StoppableServiceInterface { const promiseList = addresses.map((address) => { return this.state.subscanService.getMultiChainBalance(address) .catch((e) => { - console.error(e); + balanceServiceLogger.error('Error detecting substrate balance token', e); return null; }); @@ -906,7 +909,7 @@ export class BalanceService implements StoppableServiceInterface { this.state.chainService.setAssetSettings(updatedSettings); } catch (e) { - console.error(e); + balanceServiceLogger.error('Error updating asset settings', e); } } diff --git a/packages/extension-base/src/services/balance-service/transfer/bitcoin-transfer.ts b/packages/extension-base/src/services/balance-service/transfer/bitcoin-transfer.ts index bb540282bc3..f6bf743195e 100644 --- a/packages/extension-base/src/services/balance-service/transfer/bitcoin-transfer.ts +++ b/packages/extension-base/src/services/balance-service/transfer/bitcoin-transfer.ts @@ -4,6 +4,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { _BITCOIN_CHAIN_SLUG, _BITCOIN_NAME, _BITCOIN_TESTNET_NAME } from '@subwallet/extension-base/services/chain-service/constants'; import { _BitcoinApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BitcoinFeeInfo, BitcoinFeeRate, FeeInfo, TransactionFee } from '@subwallet/extension-base/types'; import { combineBitcoinFee, determineUtxosForSpend, determineUtxosForSpendAll, getTransferableBitcoinUtxos } from '@subwallet/extension-base/utils'; import { BitcoinAddressType } from '@subwallet/keyring/types'; @@ -12,6 +13,8 @@ import { keyring } from '@subwallet/ui-keyring'; import BigN from 'bignumber.js'; import { Network, Psbt } from 'bitcoinjs-lib'; +const bitcoinTransferLogger = createLogger('BitcoinTransfer'); + export interface TransferBitcoinProps extends TransactionFee { bitcoinApi: _BitcoinApi; chain: string; @@ -108,7 +111,7 @@ export async function createBitcoinTransaction (params: TransferBitcoinProps): P throw e; } - console.warn('Failed to create Bitcoin transaction:', e); + bitcoinTransferLogger.warn('Failed to create Bitcoin transaction', e); throw new Error(`You don’t have enough BTC (${convertChainToSymbol(chain)}) for the transaction. Lower your BTC amount and try again`); } } diff --git a/packages/extension-base/src/services/balance-service/transfer/cardano-transfer.ts b/packages/extension-base/src/services/balance-service/transfer/cardano-transfer.ts index 34a22991d4a..36e30c5e457 100644 --- a/packages/extension-base/src/services/balance-service/transfer/cardano-transfer.ts +++ b/packages/extension-base/src/services/balance-service/transfer/cardano-transfer.ts @@ -7,9 +7,12 @@ import { ErrorValidation } from '@subwallet/extension-base/background/KoniTypes' import { CardanoTxJson, CardanoTxOutput } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/types'; import { CardanoAssetMetadata, getAdaBelongUtxo, getCardanoTxFee, splitCardanoId } from '@subwallet/extension-base/services/balance-service/helpers/subscribe/cardano/utils'; import { _CardanoApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { toUnit } from '@subwallet/extension-base/utils'; import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk'; +const cardanoTransferLogger = createLogger('CardanoTransfer'); + export interface CardanoTransactionConfigProps { tokenInfo: _ChainAsset; nativeTokenInfo: _ChainAsset; @@ -86,7 +89,7 @@ export async function createCardanoTransaction (params: CardanoTransactionConfig throw new Error(`Insufficient ${nativeTokenSymbol} balance to perform transaction. Top up ${nativeTokenSymbol} and try again`); } - console.error(`Transaction is not built successfully: ${errorMessage}`); + cardanoTransferLogger.error(`Transaction is not built successfully: ${errorMessage}`); throw new Error('Unable to perform this transaction at the moment. Try again later'); } @@ -94,7 +97,7 @@ export async function createCardanoTransaction (params: CardanoTransactionConfig throw new Error('Build cardano payload failed!'); } - console.log('Build cardano payload successfully!', payload); + cardanoTransferLogger.debug('Build cardano payload successfully', payload); validatePayload(payload, params); diff --git a/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts b/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts index d437d3fcbd0..0a352b23c46 100644 --- a/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts +++ b/packages/extension-base/src/services/balance-service/transfer/smart-contract.ts @@ -7,6 +7,7 @@ import { getPSP34ContractPromise } from '@subwallet/extension-base/koni/api/cont import { getWasmContractGasLimit } from '@subwallet/extension-base/koni/api/contract-handler/wasm/utils'; import { EVM_REFORMAT_DECIMALS } from '@subwallet/extension-base/services/chain-service/constants'; import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EvmEIP1559FeeOption, EvmFeeInfo, FeeInfo, TransactionFee } from '@subwallet/extension-base/types'; import { combineEthFee } from '@subwallet/extension-base/utils'; import BigN from 'bignumber.js'; @@ -14,6 +15,8 @@ import { t } from 'i18next'; import { TransactionConfig } from 'web3-core'; import { ContractSendMethod } from 'web3-eth-contract'; +const smartContractLogger = createLogger('SmartContractTransfer'); + interface TransferEvmProps extends TransactionFee { chain: string; from: string; @@ -74,7 +77,7 @@ export async function getEVMTransactionObject (props: TransferEvmProps): Promise gasLimit = gasSettingsForEWC.gasLimit; } else { const gasEstimate = await evmApi.api.eth.estimateGas(transactionObject).catch((e: Error) => { - console.log('Cannot estimate fee with native transfer on', chain, e); + smartContractLogger.warn('Cannot estimate fee with native transfer on', chain, e); if (fallbackFee) { errorOnEstimateFee = e.message; @@ -163,7 +166,7 @@ export async function getERC20TransactionObject (props: TransferERC20Props): Pro // eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access gasLimit = await (erc20Contract.methods.transfer(to, transferValue) as ContractSendMethod).estimateGas({ from }) .catch((e: Error) => { - console.log('Cannot estimate fee with token contract', assetAddress, chain, e); + smartContractLogger.warn('Cannot estimate fee with token contract', assetAddress, chain, e); if (fallbackFee) { errorOnEstimateFee = e.message; @@ -269,7 +272,7 @@ export async function getPSP34TransferExtrinsic (substrateApi: _SubstrateApi, se // @ts-ignore return contractPromise.tx['psp34::transfer']({ gasLimit }, recipientAddress, onChainOption, {}); } catch (e) { - console.debug(e); + smartContractLogger.debug('Error in smart contract transfer', e); return null; } diff --git a/packages/extension-base/src/services/balance-service/transfer/token.ts b/packages/extension-base/src/services/balance-service/transfer/token.ts index bca483c98fe..ea301a7f19f 100644 --- a/packages/extension-base/src/services/balance-service/transfer/token.ts +++ b/packages/extension-base/src/services/balance-service/transfer/token.ts @@ -10,6 +10,7 @@ import { _TRANSFER_CHAIN_GROUP } from '@subwallet/extension-base/services/chain- import { _EvmApi, _SubstrateApi, _TonApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo, _getXcmAssetMultilocation, _isBridgedToken, _isChainEvmCompatible, _isChainTonCompatible, _isGigaToken, _isNativeToken, _isTokenGearSmartContract, _isTokenTransferredByEvm, _isTokenTransferredByTon, _isTokenWasmSmartContract } from '@subwallet/extension-base/services/chain-service/utils'; import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { combineEthFee, getGRC20ContractPromise, getVFTContractPromise } from '@subwallet/extension-base/utils'; import { keyring } from '@subwallet/ui-keyring'; import { internal } from '@ton/core'; @@ -18,6 +19,8 @@ import BigN from 'bignumber.js'; import { TransactionConfig } from 'web3-core'; import { SubmittableExtrinsic } from '@polkadot/api/promise/types'; + +const tokenTransferLogger = createLogger('TokenTransfer'); import { BN, u8aToHex } from '@polkadot/util'; import { decodeAddress } from '@polkadot/util-crypto'; @@ -182,7 +185,7 @@ export const getTransferMockTxFee = async (address: string, chainInfo: _ChainInf return estimatedFee; } catch (e) { - console.error('error mocking tx fee', e); + tokenTransferLogger.error('error mocking tx fee', e); return new BigN(0); } diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/acrossBridge/index.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/acrossBridge/index.ts index 84ac797bfbf..28be4fe4187 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/acrossBridge/index.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/acrossBridge/index.ts @@ -6,12 +6,15 @@ import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; import { _isAcrossBridgeXcm } from '@subwallet/extension-base/core/substrate/xcm-parser'; import { _getAssetDecimals, _getContractAddressOfToken, _getEvmChainId } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BasicTxErrorType } from '@subwallet/extension-base/types'; import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk'; import BigN from 'bignumber.js'; import { CreateXcmExtrinsicProps } from '..'; +const acrossBridgeLogger = createLogger('AcrossBridge'); + // Across Bridge const acrossPairsMap = new Map([ [COMMON_CHAIN_SLUGS.ETHEREUM, new Set(['optimism', 'base_mainnet', 'arbitrum_one'])], @@ -125,7 +128,7 @@ export const getAcrossSendingValue = async (originChain: _ChainInfo, originToken return sendingValue; } catch (error) { - console.error('Across Bridge error:', error); + acrossBridgeLogger.error('Across Bridge error', error); // fallback in case fetch API fail const defaultSendingAmount = isTestnet ? 0.0037 : 1; diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/availBridge.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/availBridge.ts index 824b24d5b80..4e89f931b60 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/availBridge.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/availBridge.ts @@ -8,6 +8,7 @@ import { _AVAIL_BRIDGE_GATEWAY_ABI, _AVAIL_TEST_BRIDGE_GATEWAY_ABI, getAvailBrid import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { _NotificationInfo, ClaimAvailBridgeNotificationMetadata } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import { AVAIL_BRIDGE_API } from '@subwallet/extension-base/services/inapp-notification-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EvmEIP1559FeeOption, EvmFeeInfo, FeeCustom, FeeInfo, FeeOption } from '@subwallet/extension-base/types'; import { combineEthFee } from '@subwallet/extension-base/utils'; import { decodeAddress } from '@subwallet/keyring'; @@ -17,6 +18,8 @@ import { ContractSendMethod } from 'web3-eth-contract'; import { u8aToHex } from '@polkadot/util'; +const availBridgeLogger = createLogger('AvailBridge'); + export const AvailBridgeConfig = { ASSET_ID: '0x0000000000000000000000000000000000000000000000000000000000000000', ETHEREUM_DOMAIN: 2, // todo: check if these config can change later @@ -120,7 +123,7 @@ async function getLatestEthHeadSlot (chainSlug: string) { return response.slot; } catch (e) { - console.error(e); + availBridgeLogger.error('Error in AvailBridge operation', e); throw e; } } @@ -133,7 +136,7 @@ async function getLatestBlockHash (chainSlug: string, slot: number) { return response.blockHash; } catch (e) { - console.error(e); + availBridgeLogger.error('Error in AvailBridge operation', e); throw e; } } @@ -145,7 +148,7 @@ async function getClaimProofOnAvail (chainSlug: string, blockHash: string, messa return await rawResponse.json() as { accountProof: PrefixedHexString[], storageProof: PrefixedHexString[] }; } catch (e) { - console.error(e); + availBridgeLogger.error('Error in AvailBridge operation', e); throw e; } } @@ -157,7 +160,7 @@ async function getClaimProofOnEthereum (chainSlug: string, blockHash: string, tr return await rawResponse.json() as merkleProof; } catch (e) { - console.error(e); + availBridgeLogger.error('Error in AvailBridge operation', e); throw e; } } diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts index 8cc3f8134ed..3c908310d09 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/index.ts @@ -8,6 +8,7 @@ import { _createPolygonBridgeL1toL2Extrinsic, _createPolygonBridgeL2toL1Extrinsi import { getSnowBridgeEvmTransfer } from '@subwallet/extension-base/services/balance-service/transfer/xcm/snowBridge'; import { buildXcm, dryRunPreviewXcm, dryRunXcm, estimateXcmFee, isChainNotSupportDryRun, isChainNotSupportPolkadotApi } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils'; import { _EvmApi, _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EvmEIP1559FeeOption, EvmFeeInfo, FeeInfo, TransactionFee } from '@subwallet/extension-base/types'; import { combineEthFee } from '@subwallet/extension-base/utils'; import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk'; @@ -17,6 +18,8 @@ import { SubmittableExtrinsic } from '@polkadot/api/types'; import { _createPosBridgeL1toL2Extrinsic, _createPosBridgeL2toL1Extrinsic } from './posBridge'; +const xcmTransferLogger = createLogger('XcmTransfer'); + export type CreateXcmExtrinsicProps = { destinationChain: _ChainInfo; destinationTokenInfo: _ChainAsset; @@ -128,7 +131,7 @@ export const createXcmExtrinsicV2 = async (request: CreateXcmExtrinsicProps): Pr try { return await buildXcm(request); } catch (e) { - console.log('createXcmExtrinsicV2 error: ', e); + xcmTransferLogger.error('createXcmExtrinsicV2 error', e); return undefined; } diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts index 273ee52735c..a84124d2f46 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/posBridge.ts @@ -8,11 +8,14 @@ import { _POS_BRIDGE_ABI, _POS_BRIDGE_L2_ABI, getPosL1BridgeContract, getPosL2Br import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { _NotificationInfo, ClaimPolygonBridgeNotificationMetadata } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import { fetchPolygonBridgeTransactions } from '@subwallet/extension-base/services/inapp-notification-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BasicTxErrorType, EvmEIP1559FeeOption, EvmFeeInfo, FeeCustom, FeeInfo, FeeOption } from '@subwallet/extension-base/types'; import { combineEthFee } from '@subwallet/extension-base/utils'; import { TransactionConfig } from 'web3-core'; import { ContractSendMethod } from 'web3-eth-contract'; +const posBridgeLogger = createLogger('PosBridge'); + interface inputData { error?: string message: string; @@ -113,7 +116,7 @@ export async function getClaimPosBridge (chainSlug: string, notification: _Notif throw new Error(`${inputData.message}. Please try again later.`); } } catch (err) { - console.error('Error:', err); + posBridgeLogger.error('Error in PosBridge operation', err); throw new Error(BasicTxErrorType.INTERNAL_ERROR); } @@ -151,7 +154,7 @@ export async function isClaimedPosBridge (id: string, address: string, isTestnet return !isIdClaimable; } } catch (err) { - console.error('Error:', err); + posBridgeLogger.error('Error in PosBridge operation', err); } return false; diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/snowBridge.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/snowBridge.ts index 82381cae0c7..bd40c66a95a 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/snowBridge.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/snowBridge.ts @@ -8,6 +8,7 @@ import { getWeb3Contract } from '@subwallet/extension-base/koni/api/contract-han import { _SNOWBRIDGE_GATEWAY_ABI, getSnowBridgeGatewayContract } from '@subwallet/extension-base/koni/api/contract-handler/utils'; import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken, _getSubstrateParaId, _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EvmEIP1559FeeOption, EvmFeeInfo, FeeCustom, FeeInfo, FeeOption } from '@subwallet/extension-base/types'; import { combineEthFee } from '@subwallet/extension-base/utils'; import { TransactionConfig } from 'web3-core'; @@ -15,6 +16,8 @@ import { TransactionConfig } from 'web3-core'; import { u8aToHex } from '@polkadot/util'; import { decodeAddress } from '@polkadot/util-crypto'; +const snowBridgeLogger = createLogger('SnowBridge'); + export async function getSnowBridgeEvmTransfer (tokenInfo: _ChainAsset, originChainInfo: _ChainInfo, destinationChainInfo: _ChainInfo, sender: string, recipientAddress: string, value: string, evmApi: _EvmApi, _feeInfo: FeeInfo, feeCustom?: FeeCustom, feeOption?: FeeOption): Promise { const snowBridgeContractAddress = getSnowBridgeGatewayContract(originChainInfo.slug); const snowBridgeContract = getWeb3Contract(snowBridgeContractAddress, evmApi, _SNOWBRIDGE_GATEWAY_ABI); @@ -40,7 +43,7 @@ export async function getSnowBridgeEvmTransfer (tokenInfo: _ChainAsset, originCh destinationChainParaId ); - console.log('deliveryFee', deliveryFee); + snowBridgeLogger.debug('deliveryFee', deliveryFee); totalFee = deliveryFee.totalFeeInWei.toString(); destinationFee = (deliveryFee.destinationDeliveryFeeDOT + deliveryFee.destinationExecutionFeeDOT).toString(); @@ -48,7 +51,7 @@ export async function getSnowBridgeEvmTransfer (tokenInfo: _ChainAsset, originCh // Clean up all open connections await context.destroyContext(); } catch (error) { - console.error('Cannot get snow-bridge delivery fees with error:', error); + snowBridgeLogger.error('Cannot get snow-bridge delivery fees with error', error); totalFee = '0'; destinationFee = '0'; diff --git a/packages/extension-base/src/services/balance-service/transfer/xcm/utils.ts b/packages/extension-base/src/services/balance-service/transfer/xcm/utils.ts index 13ac422d80b..37e2f71921a 100644 --- a/packages/extension-base/src/services/balance-service/transfer/xcm/utils.ts +++ b/packages/extension-base/src/services/balance-service/transfer/xcm/utils.ts @@ -4,6 +4,7 @@ import { _ChainAsset, _ChainInfo } from '@subwallet/chain-list/types'; import { fetchParaSpellChainMap } from '@subwallet/extension-base/constants/paraspell-chain-map'; import { CreateXcmExtrinsicProps } from '@subwallet/extension-base/services/balance-service/transfer/xcm/index'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment'; import { fetchFromProxyService } from '@subwallet/extension-base/utils'; import BigNumber from 'bignumber.js'; @@ -13,6 +14,8 @@ import { SubmittableExtrinsic } from '@polkadot/api/types'; import { Call, ExtrinsicPayload } from '@polkadot/types/interfaces'; import { assert, compactToU8a, isHex, u8aConcat, u8aEq } from '@polkadot/util'; +const xcmUtilsLogger = createLogger('XcmUtils'); + export type DryRunNodeFailure = { success: false, failureReason: string @@ -119,7 +122,7 @@ function txHexToSubmittableExtrinsic (api: ApiPromise, hex: string): Submittable extrinsicCall = api.createType('Call', extrinsicPayload.method.toHex()); } else { - console.error('Unable to decode data as Call, length mismatch in supplied data'); + xcmUtilsLogger.error('Unable to decode data as Call, length mismatch in supplied data'); } } catch { // final attempt, we try this as-is as a (prefixed) payload @@ -140,7 +143,7 @@ function txHexToSubmittableExtrinsic (api: ApiPromise, hex: string): Submittable return decoded; } catch (e) { - console.error('Failed to decode extrinsic hex', e); + xcmUtilsLogger.error('Failed to decode extrinsic hex', e); throw new Error('Failed to decode extrinsic hex'); } @@ -299,7 +302,7 @@ export async function estimateXcmFee (request: GetXcmFeeRequest) { const requestValue = BigNumber(value).gt(0) ? value : '1'; // avoid bug in-case estimate fee sendingValue <= 0; if (!paraSpellIdentifyV4) { - console.error('Lack of paraspell metadata'); + xcmUtilsLogger.error('Lack of paraspell metadata'); return undefined; } @@ -329,7 +332,7 @@ export async function estimateXcmFee (request: GetXcmFeeRequest) { ); if (!response.ok) { - console.error('Failed to request estimate fee'); + xcmUtilsLogger.error('Failed to request estimate fee'); return undefined; } diff --git a/packages/extension-base/src/services/buy-service/index.ts b/packages/extension-base/src/services/buy-service/index.ts index a1a91b99085..4773380b732 100644 --- a/packages/extension-base/src/services/buy-service/index.ts +++ b/packages/extension-base/src/services/buy-service/index.ts @@ -4,11 +4,14 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { ListBuyServicesResponse, ListBuyTokenResponse } from '@subwallet/extension-base/services/buy-service/types'; import { AccountChainType, BuyServiceInfo, BuyTokenInfo, OnrampAccountSupportType, SupportService } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { fetchStaticData } from '@subwallet/extension-base/utils/fetchStaticData'; import { BehaviorSubject } from 'rxjs'; import { DEFAULT_SERVICE_INFO } from './constants'; +const buyServiceLogger = createLogger('BuyService'); + const convertSupportType = (support: OnrampAccountSupportType): AccountChainType | null => { switch (support) { case 'ETHEREUM': @@ -40,13 +43,13 @@ export default class BuyService { this.fetchTokens() .catch((e) => { - console.error('Error on fetch buy tokens', e); + buyServiceLogger.error('Error on fetch buy tokens', e); this.#state.eventService.emit('buy.tokens.ready', true); }); this.fetchServices() .catch((e) => { - console.error('Error on fetch buy services', e); + buyServiceLogger.error('Error on fetch buy services', e); this.#state.eventService.emit('buy.services.ready', true); }); } diff --git a/packages/extension-base/src/services/campaign-service/helpers.ts b/packages/extension-base/src/services/campaign-service/helpers.ts index f9775561643..eeb7044a111 100644 --- a/packages/extension-base/src/services/campaign-service/helpers.ts +++ b/packages/extension-base/src/services/campaign-service/helpers.ts @@ -3,8 +3,11 @@ import { CampaignAction, CampaignNotification, NotificationType } from '@subwallet/extension-base/background/KoniTypes'; import NotificationService from '@subwallet/extension-base/services/notification-service/NotificationService'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { t } from 'i18next'; +const campaignHelpersLogger = createLogger('CampaignHelpers'); + export const runCampaign = (notificationService: NotificationService, campaign: CampaignNotification) => { const { action, message, metadata, title } = campaign.data; const { buttons } = campaign; @@ -17,7 +20,7 @@ export const runCampaign = (notificationService: NotificationService, campaign: const url = metadata.url as string | undefined; if (url) { - chrome.tabs.create({ url }).catch(console.error); + chrome.tabs.create({ url }).catch((error) => campaignHelpersLogger.error('Error opening URL', error)); } } diff --git a/packages/extension-base/src/services/campaign-service/index.ts b/packages/extension-base/src/services/campaign-service/index.ts index 992d8947032..fd228c1b250 100644 --- a/packages/extension-base/src/services/campaign-service/index.ts +++ b/packages/extension-base/src/services/campaign-service/index.ts @@ -4,12 +4,15 @@ import { CampaignData, CampaignDataType, ShowCampaignPopupRequest } from '@subwallet/extension-base/background/KoniTypes'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { ListCampaignResponse } from '@subwallet/extension-base/services/campaign-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { TARGET_ENV } from '@subwallet/extension-base/utils'; import { fetchStaticData } from '@subwallet/extension-base/utils/fetchStaticData'; import { BehaviorSubject } from 'rxjs'; import { runCampaign } from './helpers'; +const campaignServiceLogger = createLogger('CampaignService'); + const targetEnvs = ['extension', 'mobile']; export default class CampaignService { @@ -23,12 +26,12 @@ export default class CampaignService { if (targetEnvs.includes(TARGET_ENV)) { this.fetchCampaign() .catch((e) => { - console.error('Error on fetch campaigns', e); + campaignServiceLogger.error('Error on fetch campaigns', e); }); this.runCampaign() .catch((e) => { - console.error('Error on run campaigns', e); + campaignServiceLogger.error('Error on run campaigns', e); }); } } @@ -146,7 +149,7 @@ export default class CampaignService { const onComplete = () => { this.completeCampaignNotification(slug) .catch((e) => { - console.error('Error when complete campaign', slug, e); + campaignServiceLogger.error('Error when complete campaign', slug, e); }); }; @@ -162,7 +165,7 @@ export default class CampaignService { throw new Error('Missing handle campaign'); } } catch (e) { - console.error('Error on running campaigns', slug, e); + campaignServiceLogger.error('Error on running campaigns', slug, e); } }); } diff --git a/packages/extension-base/src/services/chain-online-service/index.ts b/packages/extension-base/src/services/chain-online-service/index.ts index b47467231be..3247a41b98a 100644 --- a/packages/extension-base/src/services/chain-online-service/index.ts +++ b/packages/extension-base/src/services/chain-online-service/index.ts @@ -4,6 +4,7 @@ import { AssetLogoMap, ChainLogoMap } from '@subwallet/chain-list'; import { _AssetType, _ChainAsset, _ChainInfo, _ChainStatus } from '@subwallet/chain-list/types'; import { AssetSetting } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { LATEST_CHAIN_PATCH_FETCHING_INTERVAL, md5HashChainAsset, md5HashChainInfo } from '@subwallet/extension-base/services/chain-online-service/constants'; import { ChainService, filterAssetInfoMap } from '@subwallet/extension-base/services/chain-service'; import { _ChainApiStatus, _ChainConnectionStatus, _ChainState } from '@subwallet/extension-base/services/chain-service/types'; @@ -13,6 +14,8 @@ import SettingService from '@subwallet/extension-base/services/setting-service/S import { IChain } from '@subwallet/extension-base/services/storage-service/databases'; import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService'; +const chainOnlineServiceLogger = createLogger('ChainOnlineService'); + export class ChainOnlineService { private chainService: ChainService; private settingService: SettingService; @@ -359,7 +362,7 @@ export class ChainOnlineService { } } } catch (e) { - console.error('Error fetching latest patch data'); + chainOnlineServiceLogger.error('Error fetching latest patch data'); } } @@ -379,12 +382,12 @@ export class ChainOnlineService { .then(() => this.chainService.setLockChainInfoMap(false)) .catch((e) => { this.chainService.setLockChainInfoMap(false); - console.error('Error update latest patch', e); + chainOnlineServiceLogger.error('Error update latest patch', e); }) .finally(resolve); }) .catch((e) => { - console.error('Asset fail to ready', e); + chainOnlineServiceLogger.error('Asset fail to ready', e); resolve(); }); } else { @@ -392,7 +395,7 @@ export class ChainOnlineService { } }); }).catch((e) => { - console.error('Error get latest patch or data map is locking', e); + chainOnlineServiceLogger.error('Error get latest patch or data map is locking', e); }).finally(() => { this.eventService.emit('asset.online.ready', true); }); diff --git a/packages/extension-base/src/services/chain-service/handler/CardanoApi.ts b/packages/extension-base/src/services/chain-service/handler/CardanoApi.ts index b56d99e7b54..4188881c461 100644 --- a/packages/extension-base/src/services/chain-service/handler/CardanoApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/CardanoApi.ts @@ -7,10 +7,13 @@ import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/ha import { _CardanoApi, _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types'; import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment'; import { createPromiseHandler, fetchFromProxyService, PromiseHandler } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BehaviorSubject } from 'rxjs'; import { hexAddPrefix, isHex } from '@polkadot/util'; +const cardanoApiLogger = createLogger('CardanoApi'); + // export const API_KEY = { // mainnet: process.env.BLOCKFROST_API_KEY_MAIN || '', // testnet: process.env.BLOCKFROST_API_KEY_PREP || '' @@ -116,7 +119,7 @@ export class CardanoApi implements _CardanoApi { onConnect (): void { if (!this.isApiConnected) { - console.log(`Connected to ${this.chainSlug} at ${this.apiUrl}`); + cardanoApiLogger.info(`Connected to ${this.chainSlug} at ${this.apiUrl}`); this.isApiReady = true; if (this.isApiReadyOnce) { @@ -131,7 +134,7 @@ export class CardanoApi implements _CardanoApi { this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); if (this.isApiConnected) { - console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`); + cardanoApiLogger.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`); this.isApiReady = false; this.isReadyHandler = createPromiseHandler<_CardanoApi>(); } @@ -149,7 +152,7 @@ export class CardanoApi implements _CardanoApi { return addressBalance.amount; } catch (e) { - console.error('Error on getting account balance', e); + cardanoApiLogger.error('Error on getting account balance', e); return []; } @@ -169,7 +172,7 @@ export class CardanoApi implements _CardanoApi { return utxos; } catch (e) { - console.error('Error on getting account balance', e); + cardanoApiLogger.error('Error on getting account balance', e); return []; } @@ -187,7 +190,7 @@ export class CardanoApi implements _CardanoApi { return utxo; } catch (e) { - console.error('Error on getting account balance', e); + cardanoApiLogger.error('Error on getting account balance', e); return {} as TransactionUtxosItem; } @@ -206,12 +209,12 @@ export class CardanoApi implements _CardanoApi { if (isHex(hexAddPrefix(hash))) { return hash; } else { - console.error('Error on submitting cardano tx'); + cardanoApiLogger.error('Error on submitting cardano tx'); return ''; } } catch (e) { - console.error('Error on submitting cardano tx', e); + cardanoApiLogger.error('Error on submitting cardano tx', e); return ''; } diff --git a/packages/extension-base/src/services/chain-service/handler/CardanoChainHandler.ts b/packages/extension-base/src/services/chain-service/handler/CardanoChainHandler.ts index 4544e9b9c7e..541257c7385 100644 --- a/packages/extension-base/src/services/chain-service/handler/CardanoChainHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/CardanoChainHandler.ts @@ -5,6 +5,9 @@ import { ChainService } from '@subwallet/extension-base/services/chain-service'; import { AbstractChainHandler } from '@subwallet/extension-base/services/chain-service/handler/AbstractChainHandler'; import { CardanoApi } from '@subwallet/extension-base/services/chain-service/handler/CardanoApi'; import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const cardanoChainHandlerLogger = createLogger('CardanoChainHandler'); export class CardanoChainHandler extends AbstractChainHandler { private cardanoApiMap: Record = {}; @@ -37,7 +40,7 @@ export class CardanoChainHandler extends AbstractChainHandler { existed.connect(); if (apiUrl !== existed.apiUrl) { - existed.updateApiUrl(apiUrl).catch(console.error); + existed.updateApiUrl(apiUrl).catch((error) => cardanoChainHandlerLogger.error('Error updating Cardano API URL', error)); } return existed; @@ -55,7 +58,7 @@ export class CardanoChainHandler extends AbstractChainHandler { const existed = this.getCardanoApiByChain(chain); if (existed && !existed.isApiReadyOnce) { - console.log(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); + cardanoChainHandlerLogger.info(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); return existed.recoverConnect(); } @@ -64,7 +67,7 @@ export class CardanoChainHandler extends AbstractChainHandler { destroyCardanoApi (chain: string) { const cardanoApi = this.getCardanoApiByChain(chain); - cardanoApi?.destroy().catch(console.error); + cardanoApi?.destroy().catch((error) => cardanoChainHandlerLogger.error('Error destroying Cardano API', error)); } async sleep () { @@ -72,7 +75,7 @@ export class CardanoChainHandler extends AbstractChainHandler { this.cancelAllRecover(); await Promise.all(Object.values(this.getCardanoApiMap()).map((cardanoApi) => { - return cardanoApi.disconnect().catch(console.error); + return cardanoApi.disconnect().catch((error) => cardanoChainHandlerLogger.error('Error disconnecting Cardano API', error)); })); return Promise.resolve(); diff --git a/packages/extension-base/src/services/chain-service/handler/EvmApi.ts b/packages/extension-base/src/services/chain-service/handler/EvmApi.ts index 78526c6d9b0..c0cc1f8ea62 100644 --- a/packages/extension-base/src/services/chain-service/handler/EvmApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/EvmApi.ts @@ -7,10 +7,13 @@ import { EVM_PASS_CONNECT_STATUS } from '@subwallet/extension-base/services/chai import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types'; import { _ChainConnectionStatus, _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { createPromiseHandler, PromiseHandler } from '@subwallet/extension-base/utils/promise'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BehaviorSubject } from 'rxjs'; import Web3 from 'web3'; import { HttpProvider, WebsocketProvider } from 'web3-core'; +const evmApiLogger = createLogger('EvmApi'); + export class EvmApi implements _EvmApi { chainSlug: string; api: Web3; @@ -132,7 +135,7 @@ export class EvmApi implements _EvmApi { this.isApiReady = false; this.isReadyHandler.reject(error); this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); - console.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`); + evmApiLogger.warn(`Can not connect to ${this.chainSlug} (EVM) at ${this.apiUrl}`); }); // Interval to check connecting status @@ -162,7 +165,7 @@ export class EvmApi implements _EvmApi { this.isReadyHandler.resolve(this); if (!this.isApiConnected) { - console.log(`Connected to ${this.chainSlug} at ${this.apiUrl}`); + evmApiLogger.info(`Connected to ${this.chainSlug} at ${this.apiUrl}`); this.isApiReady = true; } @@ -173,7 +176,7 @@ export class EvmApi implements _EvmApi { this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); if (this.isApiConnected) { - console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl} (EVM)`); + evmApiLogger.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl} (EVM)`); this.isApiReady = false; this.isReadyHandler = createPromiseHandler<_EvmApi>(); } diff --git a/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts b/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts index bd138a657d9..15035f1642b 100644 --- a/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/EvmChainHandler.ts @@ -13,6 +13,9 @@ import { Contract } from 'web3-eth-contract'; import { logger as createLogger } from '@polkadot/util/logger'; import { Logger } from '@polkadot/util/types'; +import { createLogger as createSubWalletLogger } from '@subwallet/extension-base/utils/logger'; + +const evmChainHandlerLogger = createSubWalletLogger('EvmChainHandler'); export class EvmChainHandler extends AbstractChainHandler { private evmApiMap: Record = {}; @@ -46,7 +49,7 @@ export class EvmChainHandler extends AbstractChainHandler { existed.connect(); if (apiUrl !== existed.apiUrl) { - existed.updateApiUrl(apiUrl).catch(console.error); + existed.updateApiUrl(apiUrl).catch((error) => evmChainHandlerLogger.error('Error updating EVM API URL', error)); } return existed; @@ -64,7 +67,7 @@ export class EvmChainHandler extends AbstractChainHandler { const existed = this.getEvmApiByChain(chainSlug); if (existed && !existed.isApiReadyOnce) { - console.log(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); + evmChainHandlerLogger.info(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); return existed.recoverConnect(); } @@ -73,7 +76,7 @@ export class EvmChainHandler extends AbstractChainHandler { destroyEvmApi (chain: string) { const evmApi = this.getEvmApiByChain(chain); - evmApi?.destroy().catch(console.error); + evmApi?.destroy().catch((error) => evmChainHandlerLogger.error('Error destroying EVM API', error)); } async sleep () { @@ -81,7 +84,7 @@ export class EvmChainHandler extends AbstractChainHandler { this.cancelAllRecover(); await Promise.all(Object.values(this.getEvmApiMap()).map((evmApi) => { - return evmApi.disconnect().catch(console.error); + return evmApi.disconnect().catch((error) => evmChainHandlerLogger.error('Error disconnecting EVM API', error)); })); return Promise.resolve(); diff --git a/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts b/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts index fb56fead7fa..b47c7fe628e 100644 --- a/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/SubstrateApi.ts @@ -14,8 +14,11 @@ import { _ChainConnectionStatus, _SubstrateAdapterQueryArgs, _SubstrateAdapterSu import { createPromiseHandler, PromiseHandler } from '@subwallet/extension-base/utils/promise'; import { goldbergRpc, goldbergTypes, spec as availSpec } from 'avail-js-sdk'; import { BehaviorSubject, combineLatest, map, Observable, Subscription } from 'rxjs'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ApiPromise, WsProvider } from '@polkadot/api'; + +const substrateApiLogger = createLogger('SubstrateApi'); import { ApiOptions } from '@polkadot/api/types'; import { typesBundle as _typesBundle } from '@polkadot/apps-config/api'; import { ProviderInterface } from '@polkadot/rpc-provider/types'; @@ -207,8 +210,8 @@ export class SubstrateApi implements _SubstrateApi { this.api.isReady.then(() => { this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED); _callbackUpdateMetadata?.(this); - }).catch(console.error); - }).catch(console.error); + }).catch((error) => substrateApiLogger.error('Error in SubstrateApi subscription', error)); + }).catch((error) => substrateApiLogger.error('Error in SubstrateApi operation', error)); } } @@ -216,7 +219,7 @@ export class SubstrateApi implements _SubstrateApi { try { await this.api.disconnect(); } catch (e) { - console.error(e); + substrateApiLogger.error('Error in SubstrateApi', e); } this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); @@ -247,7 +250,7 @@ export class SubstrateApi implements _SubstrateApi { onConnect (): void { this.updateConnectionStatus(_ChainConnectionStatus.CONNECTED); this.substrateRetry = 0; - console.log(`Connected to ${this.chainSlug || ''} at ${this.apiUrl}`); + substrateApiLogger.info(`Connected to ${this.chainSlug || ''} at ${this.apiUrl}`); if (this.isApiReadyOnce) { this.handleApiReady.resolve(this); @@ -257,7 +260,7 @@ export class SubstrateApi implements _SubstrateApi { onDisconnect (): void { this.isApiReady = false; - console.log(`Disconnected from ${this.chainSlug} at ${this.apiUrl}`); + substrateApiLogger.info(`Disconnected from ${this.chainSlug} at ${this.apiUrl}`); this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); this.handleApiReady = createPromiseHandler<_SubstrateApi>(); this.substrateRetry += 1; @@ -265,12 +268,12 @@ export class SubstrateApi implements _SubstrateApi { if (this.substrateRetry > 9) { this.disconnect().then(() => { this.updateConnectionStatus(_ChainConnectionStatus.UNSTABLE); - }).catch(console.error); + }).catch((error) => substrateApiLogger.error('Error disconnecting SubstrateApi', error)); } } onError (e: Error): void { - console.warn(`${this.chainSlug} connection got error`, e); + substrateApiLogger.warn(`${this.chainSlug} connection got error`, e); } async fillApiInfo (): Promise { diff --git a/packages/extension-base/src/services/chain-service/handler/SubstrateChainHandler.ts b/packages/extension-base/src/services/chain-service/handler/SubstrateChainHandler.ts index 9efe82202d6..59590f50149 100644 --- a/packages/extension-base/src/services/chain-service/handler/SubstrateChainHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/SubstrateChainHandler.ts @@ -17,6 +17,9 @@ import { Registry } from '@polkadot/types/types'; import { BN } from '@polkadot/util'; import { logger as createLogger } from '@polkadot/util/logger'; import { Logger } from '@polkadot/util/types'; +import { createLogger as createSubWalletLogger } from '@subwallet/extension-base/utils/logger'; + +const substrateChainHandlerLogger = createSubWalletLogger('SubstrateChainHandler'); import { _PSP22_ABI, _PSP34_ABI } from '../../../koni/api/contract-handler/utils'; @@ -78,7 +81,7 @@ export class SubstrateChainHandler extends AbstractChainHandler { this.cancelAllRecover(); await Promise.all(Object.values(this.getSubstrateApiMap()).map((substrateApi) => { - return substrateApi.disconnect().catch(console.error); + return substrateApi.disconnect().catch((error) => substrateChainHandlerLogger.error('Error disconnecting Substrate API', error)); })); } @@ -86,7 +89,7 @@ export class SubstrateChainHandler extends AbstractChainHandler { const existed = this.getSubstrateApiByChain(chainSlug); if (existed && !existed.isApiReadyOnce) { - console.log(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); + substrateChainHandlerLogger.info(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); return existed.recoverConnect(); } @@ -189,9 +192,9 @@ export class SubstrateChainHandler extends AbstractChainHandler { if (!(apiPromise instanceof GearApi)) { if (tokenType === _AssetType.GRC20) { - console.warn('Cannot subscribe GRC20 balance without GearApi instance'); + substrateChainHandlerLogger.warn('Cannot subscribe GRC20 balance without GearApi instance'); } else if (tokenType === _AssetType.VFT) { - console.warn('Cannot subscribe VFT balance without GearApi instance'); + substrateChainHandlerLogger.warn('Cannot subscribe VFT balance without GearApi instance'); } tokenSmartContract.contractError = true; @@ -302,7 +305,7 @@ export class SubstrateChainHandler extends AbstractChainHandler { public destroySubstrateApi (chainSlug: string) { const substrateAPI = this.substrateApiMap[chainSlug]; - substrateAPI?.destroy().catch(console.error); + substrateAPI?.destroy().catch((error) => substrateChainHandlerLogger.error('Error destroying Substrate API', error)); } public async initApi (chainSlug: string, apiUrl: string, { externalApiPromise, onUpdateStatus, providerName }: Omit<_ApiOptions, 'metadata'> = {}): Promise<_SubstrateApi> { diff --git a/packages/extension-base/src/services/chain-service/handler/TonApi.ts b/packages/extension-base/src/services/chain-service/handler/TonApi.ts index 009a75a0ade..1e50f00d4f9 100644 --- a/packages/extension-base/src/services/chain-service/handler/TonApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/TonApi.ts @@ -11,8 +11,11 @@ import { createPromiseHandler, PromiseHandler } from '@subwallet/extension-base/ import { TonWalletContract } from '@subwallet/keyring/types'; import { Cell } from '@ton/core'; import { Address, Contract, OpenedContract, TonClient } from '@ton/ton'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BehaviorSubject } from 'rxjs'; +const tonApiLogger = createLogger('TonApi'); + export class TonApi implements _TonApi { chainSlug: string; private api: TonClient; @@ -112,7 +115,7 @@ export class TonApi implements _TonApi { onConnect (): void { if (!this.isApiConnected) { - console.log(`Connected to ${this.chainSlug} at ${this.apiUrl}`); + tonApiLogger.info(`Connected to ${this.chainSlug} at ${this.apiUrl}`); this.isApiReady = true; if (this.isApiReadyOnce) { @@ -127,7 +130,7 @@ export class TonApi implements _TonApi { this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); if (this.isApiConnected) { - console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`); + tonApiLogger.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`); this.isApiReady = false; this.isReadyHandler = createPromiseHandler<_TonApi>(); } @@ -179,7 +182,7 @@ export class TonApi implements _TonApi { return extMsgInfo.result.hash; } catch (error) { - console.error('Failed to send transaction with boc', boc); + tonApiLogger.error('Failed to send transaction with boc', boc); throw error; } } diff --git a/packages/extension-base/src/services/chain-service/handler/TonChainHandler.ts b/packages/extension-base/src/services/chain-service/handler/TonChainHandler.ts index b5aebbf2e75..ae8a180fe63 100644 --- a/packages/extension-base/src/services/chain-service/handler/TonChainHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/TonChainHandler.ts @@ -5,6 +5,9 @@ import { ChainService } from '@subwallet/extension-base/services/chain-service'; import { AbstractChainHandler } from '@subwallet/extension-base/services/chain-service/handler/AbstractChainHandler'; import { TonApi } from '@subwallet/extension-base/services/chain-service/handler/TonApi'; import { _ApiOptions } from '@subwallet/extension-base/services/chain-service/handler/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const tonChainHandlerLogger = createLogger('TonChainHandler'); export class TonChainHandler extends AbstractChainHandler { private tonApiMap: Record = {}; @@ -37,7 +40,7 @@ export class TonChainHandler extends AbstractChainHandler { existed.connect(); if (apiUrl !== existed.apiUrl) { - existed.updateApiUrl(apiUrl).catch(console.error); + existed.updateApiUrl(apiUrl).catch((error) => tonChainHandlerLogger.error('Error updating TON API URL', error)); } return existed; @@ -55,7 +58,7 @@ export class TonChainHandler extends AbstractChainHandler { const existed = this.getTonApiByChain(chain); if (existed && !existed.isApiReadyOnce) { - console.log(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); + tonChainHandlerLogger.info(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); return existed.recoverConnect(); } @@ -64,7 +67,7 @@ export class TonChainHandler extends AbstractChainHandler { destroyTonApi (chain: string) { const tonApi = this.getTonApiByChain(chain); - tonApi?.destroy().catch(console.error); + tonApi?.destroy().catch((error) => tonChainHandlerLogger.error('Error destroying TON API', error)); } async sleep () { @@ -72,7 +75,7 @@ export class TonChainHandler extends AbstractChainHandler { this.cancelAllRecover(); await Promise.all(Object.values(this.getTonApiMap()).map((tonApi) => { - return tonApi.disconnect().catch(console.error); + return tonApi.disconnect().catch((error) => tonChainHandlerLogger.error('Error disconnecting TON API', error)); })); return Promise.resolve(); diff --git a/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinApi.ts b/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinApi.ts index 40a27967dfb..26504d0bb80 100644 --- a/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinApi.ts +++ b/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinApi.ts @@ -5,11 +5,14 @@ import { BlockStreamTestnetRequestStrategy, MempoolTestnetRequestStrategy } from import { SubWalletMainnetRequestStrategy } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet'; import { BitcoinApiStrategy } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types'; import { createPromiseHandler, PromiseHandler } from '@subwallet/extension-base/utils/promise'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BehaviorSubject } from 'rxjs'; import { _ApiOptions } from '../../handler/types'; import { _BitcoinApi, _ChainConnectionStatus } from '../../types'; +const bitcoinApiLogger = createLogger('BitcoinApi'); + // const isBlockStreamProvider = (apiUrl: string): boolean => apiUrl === 'https://blockstream-testnet.openbit.app' || apiUrl === 'https://electrs.openbit.app'; // const BLOCKSTREAM_TESTNET_API_URL = 'https://blockstream.info/testnet/api/'; // const MEMPOOL_TESTNET_V4_API_URL = 'https://mempool.space/testnet4/api/'; @@ -113,7 +116,7 @@ export class BitcoinApi implements _BitcoinApi { onConnect (): void { if (!this.isApiConnected) { - console.log(`Connected to ${this.chainSlug} at ${this.apiUrl}`); + bitcoinApiLogger.info(`Connected to ${this.chainSlug} at ${this.apiUrl}`); this.isApiReady = true; if (this.isApiReadyOnce) { @@ -128,7 +131,7 @@ export class BitcoinApi implements _BitcoinApi { this.updateConnectionStatus(_ChainConnectionStatus.DISCONNECTED); if (this.isApiConnected) { - console.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`); + bitcoinApiLogger.warn(`Disconnected from ${this.chainSlug} of ${this.apiUrl}`); this.isApiReady = false; this.isReadyHandler = createPromiseHandler<_BitcoinApi>(); } diff --git a/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinChainHandler.ts b/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinChainHandler.ts index 85da1abadfd..e948bfe00c2 100644 --- a/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinChainHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/bitcoin/BitcoinChainHandler.ts @@ -2,8 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 import { ChainService } from '@subwallet/extension-base/services/chain-service'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { AbstractChainHandler } from '../AbstractChainHandler'; + +const bitcoinChainHandlerLogger = createLogger('BitcoinChainHandler'); import { _ApiOptions } from '../types'; import { BitcoinApi } from './BitcoinApi'; @@ -34,7 +37,7 @@ export class BitcoinChainHandler extends AbstractChainHandler { existed.connect(); if (apiUrl !== existed.apiUrl) { - existed.updateApiUrl(apiUrl).catch(console.error); + existed.updateApiUrl(apiUrl).catch((error) => bitcoinChainHandlerLogger.error('Error updating Bitcoin API URL', error)); } return existed; @@ -52,7 +55,7 @@ export class BitcoinChainHandler extends AbstractChainHandler { const existed = this.getApiByChain(chainSlug); if (existed && !existed.isApiReadyOnce) { - console.log(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); + bitcoinChainHandlerLogger.info(`Reconnect ${existed.providerName || existed.chainSlug} at ${existed.apiUrl}`); return existed.recoverConnect(); } @@ -61,7 +64,7 @@ export class BitcoinChainHandler extends AbstractChainHandler { destroyApi (chain: string) { const api = this.getApiByChain(chain); - api?.destroy().catch(console.error); + api?.destroy().catch((error) => bitcoinChainHandlerLogger.error('Error destroying Bitcoin API', error)); } async sleep () { @@ -69,7 +72,7 @@ export class BitcoinChainHandler extends AbstractChainHandler { this.cancelAllRecover(); await Promise.all(Object.values(this.getApiMap()).map((evmApi) => { - return evmApi.disconnect().catch(console.error); + return evmApi.disconnect().catch((error) => bitcoinChainHandlerLogger.error('Error disconnecting Bitcoin API', error)); })); return Promise.resolve(); diff --git a/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.ts b/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.ts index 4e32b55d560..6f244718d6f 100644 --- a/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.ts +++ b/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/blockstream-testnet-strategy.ts @@ -3,6 +3,7 @@ import { SWError } from '@subwallet/extension-base/background/errors/SWError'; import { BitcoinAddressSummaryInfo, BitcoinApiStrategy, BitcoinTransactionEventMap, BlockstreamAddressResponse, BlockStreamBlock, BlockStreamFeeEstimates, BlockStreamTransactionDetail, BlockStreamTransactionStatus, BlockStreamUtxo, Inscription, InscriptionFetchedData, RunesInfoByAddress, RunesInfoByAddressFetchedData } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { HiroService } from '@subwallet/extension-base/services/hiro-service'; import { RunesService } from '@subwallet/extension-base/services/rune-service'; import { BaseApiRequestStrategy } from '@subwallet/extension-base/strategy/api-request-strategy'; @@ -12,6 +13,8 @@ import { BitcoinFeeInfo, BitcoinTx, UtxoResponseItem } from '@subwallet/extensio import BigN from 'bignumber.js'; import EventEmitter from 'eventemitter3'; +const blockstreamTestnetLogger = createLogger('BlockStreamTestnetStrategy'); + export class BlockStreamTestnetRequestStrategy extends BaseApiRequestStrategy implements BitcoinApiStrategy { private readonly baseUrl: string; private readonly isTestnet: boolean; @@ -67,7 +70,7 @@ export class BlockStreamTestnetRequestStrategy extends BaseApiRequestStrategy im this.timePerBlock = blockTime; } catch (e) { - console.error('Failed to compute block time', e); + blockstreamTestnetLogger.error('Failed to compute block time', e); blockTime = (this.isTestnet ? 5 * 60 : 10 * 60) * 1000; // Default to 10 minutes if failed } @@ -220,7 +223,7 @@ export class BlockStreamTestnetRequestStrategy extends BaseApiRequestStrategy im const response = await getRequest(this.getUrl('/fee-estimates'), undefined, this.headers); if (!response.ok) { - console.warn(`Failed to fetch fee estimates: ${response.statusText}`); + blockstreamTestnetLogger.warn(`Failed to fetch fee estimates: ${response.statusText}`); return defaultFeeInfo; } @@ -300,7 +303,7 @@ export class BlockStreamTestnetRequestStrategy extends BaseApiRequestStrategy im eventEmitter.emit('success', transactionStatus); } }) - .catch(console.error); + .catch((error) => blockstreamTestnetLogger.error('Error in blockstream testnet strategy', error)); }, 30000); }) .catch((error: Error) => { @@ -351,7 +354,7 @@ export class BlockStreamTestnetRequestStrategy extends BaseApiRequestStrategy im return runesFullList; } catch (error) { - console.error(`Failed to get ${address} balances`, error); + blockstreamTestnetLogger.error(`Failed to get ${address} balances`, error); throw error; } } diff --git a/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.ts b/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.ts index 7182a9f2eb7..f92d26f15a3 100644 --- a/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.ts +++ b/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/BlockStreamTestnet/mempool-testnet-strategy.ts @@ -3,6 +3,7 @@ import { SWError } from '@subwallet/extension-base/background/errors/SWError'; import { BitcoinAddressSummaryInfo, BitcoinApiStrategy, BitcoinTransactionEventMap, BlockstreamAddressResponse, BlockStreamBlock, BlockStreamFeeEstimates, BlockStreamTransactionDetail, BlockStreamTransactionStatus, BlockStreamUtxo, Inscription, InscriptionFetchedData, RecommendedFeeEstimates, RunesInfoByAddress, RunesInfoByAddressFetchedData } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { HiroService } from '@subwallet/extension-base/services/hiro-service'; import { RunesService } from '@subwallet/extension-base/services/rune-service'; import { BaseApiRequestStrategy } from '@subwallet/extension-base/strategy/api-request-strategy'; @@ -12,6 +13,8 @@ import { BitcoinFeeInfo, BitcoinTx, UtxoResponseItem } from '@subwallet/extensio import BigN from 'bignumber.js'; import EventEmitter from 'eventemitter3'; +const mempoolTestnetLogger = createLogger('MempoolTestnetStrategy'); + export class MempoolTestnetRequestStrategy extends BaseApiRequestStrategy implements BitcoinApiStrategy { private readonly baseUrl: string; private readonly isTestnet: boolean; @@ -67,7 +70,7 @@ export class MempoolTestnetRequestStrategy extends BaseApiRequestStrategy implem this.timePerBlock = blockTime; } catch (e) { - console.error('Failed to compute block time', e); + mempoolTestnetLogger.error('Failed to compute block time', e); blockTime = (this.isTestnet ? 5 * 60 : 10 * 60) * 1000; // Default to 10 minutes if failed } @@ -220,7 +223,7 @@ export class MempoolTestnetRequestStrategy extends BaseApiRequestStrategy implem const response = await getRequest(this.getUrl('v1/fees/recommended'), undefined, this.headers); if (!response.ok) { - console.warn(`Failed to fetch fee estimates: ${response.statusText}`); + mempoolTestnetLogger.warn(`Failed to fetch fee estimates: ${response.statusText}`); return defaultFeeInfo; } @@ -300,7 +303,7 @@ export class MempoolTestnetRequestStrategy extends BaseApiRequestStrategy implem eventEmitter.emit('success', transactionStatus); } }) - .catch(console.error); + .catch((error) => mempoolTestnetLogger.error('Error in mempool testnet strategy', error)); }, 30000); }) .catch((error: Error) => { @@ -351,7 +354,7 @@ export class MempoolTestnetRequestStrategy extends BaseApiRequestStrategy implem return runesFullList; } catch (error) { - console.error(`Failed to get ${address} balances`, error); + mempoolTestnetLogger.error(`Failed to get ${address} balances`, error); throw error; } } diff --git a/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.ts b/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.ts index 2e3805107ee..f33d5d8224d 100644 --- a/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.ts +++ b/packages/extension-base/src/services/chain-service/handler/bitcoin/strategy/SubWalletMainnet/index.ts @@ -5,6 +5,7 @@ import { SWError } from '@subwallet/extension-base/background/errors/SWError'; import { _BTC_SERVICE_TOKEN } from '@subwallet/extension-base/services/chain-service/constants'; import { BitcoinAddressSummaryInfo, BitcoinApiStrategy, BitcoinTransactionEventMap, BlockStreamBlock, BlockStreamFeeEstimates, BlockStreamTransactionDetail, BlockStreamTransactionStatus, Inscription, InscriptionFetchedData, RecommendedFeeEstimates, RunesInfoByAddress, RunesInfoByAddressFetchedData, UpdateOpenBitUtxo } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types'; import { OBResponse } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { HiroService } from '@subwallet/extension-base/services/hiro-service'; import { RunesService } from '@subwallet/extension-base/services/rune-service'; import { BaseApiRequestStrategy } from '@subwallet/extension-base/strategy/api-request-strategy'; @@ -14,6 +15,8 @@ import { BitcoinFeeInfo, BitcoinTx, UtxoResponseItem } from '@subwallet/extensio import BigN from 'bignumber.js'; import EventEmitter from 'eventemitter3'; +const subWalletMainnetLogger = createLogger('SubWalletMainnetStrategy'); + export class SubWalletMainnetRequestStrategy extends BaseApiRequestStrategy implements BitcoinApiStrategy { private readonly baseUrl: string; private readonly isTestnet: boolean; @@ -71,7 +74,7 @@ export class SubWalletMainnetRequestStrategy extends BaseApiRequestStrategy impl this.timePerBlock = blockTime; } catch (e) { - console.error('Failed to compute block time', e); + subWalletMainnetLogger.error('Failed to compute block time', e); blockTime = (this.isTestnet ? 5 * 60 : 10 * 60) * 1000; // Default to 10 minutes if failed } @@ -238,7 +241,7 @@ export class SubWalletMainnetRequestStrategy extends BaseApiRequestStrategy impl eventEmitter.emit('success', transactionStatus); } }) - .catch(console.error); + .catch((error) => subWalletMainnetLogger.error('Error in SubWalletMainnet strategy', error)); }, 30000); }) .catch((error: Error) => { @@ -288,7 +291,7 @@ export class SubWalletMainnetRequestStrategy extends BaseApiRequestStrategy impl return runesFullList; } catch (error) { - console.error(`Failed to get ${address} balances`, error); + subWalletMainnetLogger.error(`Failed to get ${address} balances`, error); throw error; } } @@ -301,7 +304,7 @@ export class SubWalletMainnetRequestStrategy extends BaseApiRequestStrategy impl return responseRuneUtxos.results; } catch (error) { - console.error(`Failed to get ${address} rune utxos`, error); + subWalletMainnetLogger.error(`Failed to get ${address} rune utxos`, error); throw error; } } @@ -333,7 +336,7 @@ export class SubWalletMainnetRequestStrategy extends BaseApiRequestStrategy impl return inscriptionsFullList; } catch (error) { - console.error(`Failed to get ${address} inscriptions`, error); + subWalletMainnetLogger.error(`Failed to get ${address} inscriptions`, error); throw error; } } diff --git a/packages/extension-base/src/services/chain-service/handler/light-client/index.ts b/packages/extension-base/src/services/chain-service/handler/light-client/index.ts index a476f723752..3319097b3ab 100644 --- a/packages/extension-base/src/services/chain-service/handler/light-client/index.ts +++ b/packages/extension-base/src/services/chain-service/handler/light-client/index.ts @@ -6,6 +6,9 @@ import { WellKnownChain } from '@substrate/connect'; import { ScProvider } from '@polkadot/rpc-provider'; import { ProviderInterface, ProviderInterfaceCallback, ProviderInterfaceEmitCb, ProviderInterfaceEmitted } from '@polkadot/rpc-provider/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const lightClientLogger = createLogger('LightClient'); export const relayChainSpecs: Record = { kusama: WellKnownChain.ksmcc3, @@ -35,7 +38,7 @@ class ProviderPlaceholder implements ProviderInterface { .then((provider) => { this.provider = provider; }) - .catch(console.error); + .catch((error) => lightClientLogger.error('Error initializing provider', error)); } get hasSubscriptions () { @@ -84,7 +87,7 @@ class ProviderPlaceholder implements ProviderInterface { if (!cancel) { unsub = provider.on(type, sub); } - }).catch(console.error); + }).catch((error) => lightClientLogger.error('Error setting up provider subscription', error)); return () => { unsub(); @@ -138,7 +141,10 @@ export function getSubstrateConnectProvider (specLink: string): ProviderInterfac scProvider = new ScProvider(Sc, spec); return scProvider; - }).catch(console.error) as Promise; + }).catch((error) => { + lightClientLogger.error('Error fetching para chain spec', error); + throw error; + }) as Promise; return new ProviderPlaceholder(scPromise); } diff --git a/packages/extension-base/src/services/chain-service/handler/manta/MantaPrivateHandler.ts b/packages/extension-base/src/services/chain-service/handler/manta/MantaPrivateHandler.ts index df237b62e51..8e361680239 100644 --- a/packages/extension-base/src/services/chain-service/handler/manta/MantaPrivateHandler.ts +++ b/packages/extension-base/src/services/chain-service/handler/manta/MantaPrivateHandler.ts @@ -3,9 +3,12 @@ import { MantaAuthorizationContext, MantaPayConfig, MantaPaySyncState } from '@subwallet/extension-base/background/KoniTypes'; import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseWallet, interfaces, MantaPayWallet } from 'manta-extension-sdk'; import { Subject } from 'rxjs'; +const mantaPrivateHandlerLogger = createLogger('MantaPrivateHandler'); + export class MantaPrivateHandler { private dbService: DatabaseService; private _privateWallet: MantaPayWallet | undefined = undefined; @@ -85,7 +88,7 @@ export class MantaPrivateHandler { ...data }); } catch (e) { - console.error('manta-pay', e); + mantaPrivateHandlerLogger.error('manta-pay error', e); return false; } @@ -102,7 +105,7 @@ export class MantaPrivateHandler { // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment result = await this.dbService.getMantaPayData(`storage_state_${palletName}_${network}${suffix}`); } catch (e) { - console.error(e); + mantaPrivateHandlerLogger.error('Error in MantaPrivateHandler', e); } // eslint-disable-next-line @typescript-eslint/no-unsafe-return @@ -167,7 +170,7 @@ export class MantaPrivateHandler { this.syncStateSubject.next(this.syncState); }) - .catch(console.error); + .catch((error) => mantaPrivateHandlerLogger.error('Error in MantaPrivateHandler operation', error)); }, 1000); return () => { diff --git a/packages/extension-base/src/services/chain-service/health-check/index.ts b/packages/extension-base/src/services/chain-service/health-check/index.ts index 0c33fe5c93f..776863bfa89 100644 --- a/packages/extension-base/src/services/chain-service/health-check/index.ts +++ b/packages/extension-base/src/services/chain-service/health-check/index.ts @@ -2,10 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { _ChainInfo } from '@subwallet/chain-list/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import Web3 from 'web3'; import { WsProvider } from '@polkadot/api'; +const healthCheckLogger = createLogger('HealthCheck'); + export async function checkSubstrateEndpoint (endpoint: string, timeout: number): Promise { const wsProvider = new WsProvider(endpoint, false, undefined, timeout); @@ -16,11 +19,11 @@ export async function checkSubstrateEndpoint (endpoint: string, timeout: number) wsProvider.on('connected', () => { wsProvider.send('system_health', []).then((systemHealth) => { resolve(true); - }).catch(console.log); + }).catch((error) => healthCheckLogger.debug('Error checking system health', error)); }); }); } catch (error) { - console.log(`${endpoint}: fail to check health`); + healthCheckLogger.warn(`${endpoint}: fail to check health`); return false; // if there is an error, return false } finally { @@ -36,7 +39,7 @@ export async function checkEvmEndpoint (endpoint: string, timeout: number): Prom return !!blockNumber; } catch (error) { - console.log(error); + healthCheckLogger.error('Error checking EVM endpoint', error); return false; } diff --git a/packages/extension-base/src/services/chain-service/health-check/utils/asset-info.ts b/packages/extension-base/src/services/chain-service/health-check/utils/asset-info.ts index a5660b6eb1a..629c956ed84 100644 --- a/packages/extension-base/src/services/chain-service/health-check/utils/asset-info.ts +++ b/packages/extension-base/src/services/chain-service/health-check/utils/asset-info.ts @@ -7,11 +7,14 @@ import { _PSP22_ABI } from '@subwallet/extension-base/koni/api/contract-handler/ import { getDefaultWeightV2 } from '@subwallet/extension-base/koni/api/contract-handler/wasm/utils'; import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getContractAddressOfToken, _getTokenOnChainAssetId, _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import BigN from 'bignumber.js'; import { ApiPromise } from '@polkadot/api'; import { ContractPromise } from '@polkadot/api-contract'; +const assetInfoLogger = createLogger('AssetInfo'); + const BN_TEN = new BigN(10); export interface AssetSpec { @@ -412,9 +415,9 @@ export const validateAsset = ( const chainlistDecimals = chainlistAsset.decimals || 0; const chainlistSymbol = chainlistAsset.symbol; - console.log(`[i] minAmount: current - ${chainlistMinAmount}, onchain - ${minAmount}`); - console.log(`[i] decimals: current - ${chainlistDecimals}, onchain - ${decimals}`); - console.log(`[i] symbol: current - ${chainlistSymbol}, onchain - ${symbol}`); + assetInfoLogger.info(`[i] minAmount: current - ${chainlistMinAmount}, onchain - ${minAmount}`); + assetInfoLogger.info(`[i] decimals: current - ${chainlistDecimals}, onchain - ${decimals}`); + assetInfoLogger.info(`[i] symbol: current - ${chainlistSymbol}, onchain - ${symbol}`); const isValidSymbol = symbol === chainlistSymbol ? true : 'zk' + symbol === chainlistSymbol; const isValidMinAmount = minAmount === chainlistMinAmount; diff --git a/packages/extension-base/src/services/chain-service/health-check/utils/provider.ts b/packages/extension-base/src/services/chain-service/health-check/utils/provider.ts index 6a12c55a764..5d3e5ceae49 100644 --- a/packages/extension-base/src/services/chain-service/health-check/utils/provider.ts +++ b/packages/extension-base/src/services/chain-service/health-check/utils/provider.ts @@ -3,17 +3,20 @@ import { EvmApi } from '@subwallet/extension-base/services/chain-service/handler/EvmApi'; import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ApiPromise, WsProvider } from '@polkadot/api'; import { noop } from '@polkadot/util'; +const providerHealthCheckLogger = createLogger('ProviderHealthCheck'); + export const failedMessage = 'Connect failed'; export const timeoutMessage = 'Connect timeout'; export const substrateHandleConnectChain = async (chain: string, key: string, provider: string, hash: string): Promise<[ApiPromise, string]> => { // eslint-disable-next-line @typescript-eslint/no-misused-promises,no-async-promise-executor return new Promise<[ApiPromise, string]>(async (resolve) => { - console.log('start', chain, key, provider); + providerHealthCheckLogger.debug('start', chain, key, provider); const _api = new ApiPromise({ provider: new WsProvider(provider) }); @@ -21,7 +24,7 @@ export const substrateHandleConnectChain = async (chain: string, key: string, pr const handlerOnFail = (e: Error) => { if (logFail) { - console.log('error', chain, key); + providerHealthCheckLogger.error('error', chain, key); resolve([_api, e?.message || failedMessage]); } @@ -29,11 +32,11 @@ export const substrateHandleConnectChain = async (chain: string, key: string, pr }; const timeout = setTimeout(() => { - console.log('timeout', chain, key); + providerHealthCheckLogger.warn('timeout', chain, key); resolve([_api, timeoutMessage]); logFail = false; - _api.disconnect().catch(console.error); + _api.disconnect().catch((error) => providerHealthCheckLogger.error('Error disconnecting API', error)); _api.off('disconnected', handlerOnFail); _api.off('error', handlerOnFail); }, 30 * 1000); @@ -64,7 +67,7 @@ export const substrateHandleConnectChain = async (chain: string, key: string, pr export const evmHandleConnectChain = async (chain: string, key: string, provider: string, chainId: number): Promise<[_EvmApi | null, string]> => { // eslint-disable-next-line @typescript-eslint/no-misused-promises,no-async-promise-executor return new Promise<[_EvmApi | null, string]>(async (resolve) => { - console.log('start', chain, key, provider); + providerHealthCheckLogger.debug('start', chain, key, provider); let api: _EvmApi | null = null; @@ -74,7 +77,7 @@ export const evmHandleConnectChain = async (chain: string, key: string, provider const handlerOnFail = (e: Error) => { if (logFail) { - console.log('error', chain, key); + providerHealthCheckLogger.error('error', chain, key); resolve([api, e?.message || failedMessage]); } @@ -82,11 +85,11 @@ export const evmHandleConnectChain = async (chain: string, key: string, provider }; const timeout = setTimeout(() => { - console.log('timeout', chain, key); + providerHealthCheckLogger.warn('timeout', chain, key); resolve([api, timeoutMessage]); logFail = false; - _api.destroy().catch(console.error); + _api.destroy().catch((error) => providerHealthCheckLogger.error('Error destroying API', error)); }, 60 * 1000); try { @@ -208,7 +211,7 @@ export const handleEvmProvider = ({ awaitDisconnect, } }; - console.log('connected', chain, key, provider); + providerHealthCheckLogger.debug('connected', chain, key, provider); clearTimeout(timeout); diff --git a/packages/extension-base/src/services/chain-service/index.ts b/packages/extension-base/src/services/chain-service/index.ts index 6dadc8cfce9..8ea97b16358 100644 --- a/packages/extension-base/src/services/chain-service/index.ts +++ b/packages/extension-base/src/services/chain-service/index.ts @@ -30,6 +30,7 @@ import { isArray } from '@polkadot/util'; import { logger as createLogger } from '@polkadot/util/logger'; import { HexString, Logger } from '@polkadot/util/types'; import { ExtraInfo } from '@polkadot-api/merkleize-metadata'; +import { createLogger as createExtensionLogger } from '@subwallet/extension-base/utils/logger'; const filterChainInfoMap = (data: Record, ignoredChains: string[]): Record => { return Object.fromEntries( @@ -39,6 +40,8 @@ const filterChainInfoMap = (data: Record, ignoredChains: str }; // .filter(([slug, info]) => !info.bitcoinInfo && !ignoredChains.includes(slug)) +const chainServiceLogger = createExtensionLogger('ChainService'); + const ignoredList = [ 'bevm', 'bevmTest', @@ -130,7 +133,7 @@ export class ChainService { this.swapRefMapSubject.next(this.swapRefMap); if (MODULE_SUPPORT.MANTA_ZK) { - console.log('Init Manta ZK'); + chainServiceLogger.info('Init Manta ZK'); this.mantaChainHandler = new MantaPrivateHandler(dbService); } @@ -614,7 +617,7 @@ export class ChainService { delete chainStateMap[slug]; delete chainInfoMap[slug]; this.deleteAssetsByChain(slug); - this.dbService.removeFromChainStore([slug]).catch(console.error); + this.dbService.removeFromChainStore([slug]).catch((error) => chainServiceLogger.error('Error removing chain from store', error)); this.updateChainSubscription(); @@ -650,7 +653,7 @@ export class ChainService { delete chainStateMap[slug]; delete chainInfoMap[slug]; this.deleteAssetsByChain(slug); - this.dbService.removeFromChainStore([slug]).catch(console.error); + this.dbService.removeFromChainStore([slug]).catch((error) => chainServiceLogger.error('Error removing chain from store', error)); this.updateChainSubscription(); @@ -812,18 +815,18 @@ export class ChainService { if (latestChainInfo && latestChainInfo.length > 0) { const { needUpdateChainApiList, storedChainInfoList } = updateLatestChainInfo(this.dataMap, latestChainInfo); - this.dbService.bulkUpdateChainStore(storedChainInfoList).catch(console.error); + this.dbService.bulkUpdateChainStore(storedChainInfoList).catch((error) => chainServiceLogger.error('Error bulk updating chain store', error)); this.updateChainSubscription(); needUpdateChainApiList.forEach((chainInfo) => { - console.log('Updating chain API for', chainInfo.slug); - this.initApiForChain(chainInfo).catch(console.error); + chainServiceLogger.info('Updating chain API for', chainInfo.slug); + this.initApiForChain(chainInfo).catch((error) => chainServiceLogger.error('Error initializing API for chain', error)); }); this.logger.log('Finished updating latest RPC providers'); } } catch (e) { - console.error('Error fetching latest chain data'); + chainServiceLogger.error('Error fetching latest chain data', e); } } @@ -918,7 +921,7 @@ export class ChainService { if (JSON.stringify(currentTokenKeys) !== JSON.stringify(newTokenKeys)) { // Check if token keys have changed this.enablePopularTokens() .then(() => this.logger.log('Popular tokens enabled due to priority tokens change')) // Log success after enabling tokens - .catch((e) => console.error('Error enabling popular tokens:', e)); // Log error if enabling fails + .catch((e) => chainServiceLogger.error('Error enabling popular tokens', e)); // Log error if enabling fails } } @@ -934,7 +937,7 @@ export class ChainService { this.lockChainInfoMap = false; }).catch((e) => { this.lockChainInfoMap = false; - console.error('Error update latest chain data', e); + chainServiceLogger.error('Error update latest chain data', e); }); // this.fetchLatestPriceIdsData().then((latestPriceIds) => { @@ -945,19 +948,19 @@ export class ChainService { .then((latestledgerGenericAllowChains) => { this.handleLatestLedgerGenericAllowChains(latestledgerGenericAllowChains); }) - .catch(console.error); + .catch((error) => chainServiceLogger.error('Error fetching latest ledger generic allow chains', error)); this.fetchLatestPriorityTokens() .then((latestPriorityTokens) => { this.handleLatestPriorityTokens(latestPriorityTokens); }) - .catch(console.error); + .catch((error) => chainServiceLogger.error('Error fetching latest priority tokens', error)); this.fetchLatestSufficientChains() .then((latestSufficientChains) => { this.handleLatestSufficientChains(latestSufficientChains); }) - .catch(console.error); + .catch((error) => chainServiceLogger.error('Error fetching latest sufficient chains', error)); } private async initApis () { @@ -970,7 +973,7 @@ export class ChainService { try { return this.initApiForChain(chainInfo); } catch (e) { - console.error(e); + chainServiceLogger.error('Error initializing API for chain', e); return Promise.resolve(); } @@ -1033,7 +1036,7 @@ export class ChainService { // eslint-disable-next-line @typescript-eslint/no-empty-function .then(() => { }) - .catch((error) => console.error('Error connecting to the report API:', error)); + .catch((error) => chainServiceLogger.error('Error connecting to the report API', error)); } this.updateChainConnectionStatus(slug, status); @@ -1120,7 +1123,7 @@ export class ChainService { active: true, currentProvider: chainStateMap[chainSlug].currentProvider, manualTurnOff: !!chainStateMap[chainSlug].manualTurnOff - }).catch(console.error); + }).catch((error) => chainServiceLogger.error('Error upserting chain info', error)); chainStateMap[chainSlug].active = true; await this.initApiForChain(chainInfo); @@ -1159,7 +1162,7 @@ export class ChainService { active: true, currentProvider: chainStateMap[chainSlug].currentProvider, manualTurnOff: !!chainStateMap[chainSlug].manualTurnOff - }).catch(console.error); + }).catch((error) => chainServiceLogger.error('Error enabling chain', error)); chainStateMap[chainSlug].active = true; @@ -1203,7 +1206,7 @@ export class ChainService { active: false, currentProvider: chainStateMap[chainSlug].currentProvider, manualTurnOff: !preventManualTurnOff - }).catch(console.error); + }).catch((error) => chainServiceLogger.error('Error disabling chain', error)); this.updateChainStateMapSubscription(); this.lockChainInfoMap = false; @@ -1943,7 +1946,7 @@ export class ChainService { return result; } catch (e) { - console.error('Error connecting to provider', e); + chainServiceLogger.error('Error connecting to provider', e); result.success = false; result.error = _CHAIN_VALIDATION_ERROR.CONNECTION_FAILURE; @@ -2088,11 +2091,11 @@ export class ChainService { } public refreshSubstrateApi (slug: string) { - this.substrateChainHandler.recoverApi(slug).catch(console.error); + this.substrateChainHandler.recoverApi(slug).catch((error) => chainServiceLogger.error('Error refreshing substrate API', error)); } public refreshEvmApi (slug: string) { - this.evmChainHandler.recoverApi(slug).catch(console.error); + this.evmChainHandler.recoverApi(slug).catch((error) => chainServiceLogger.error('Error refreshing EVM API', error)); } public async stopAllChainApis () { diff --git a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/acala.ts b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/acala.ts index 864a6ea6614..46041523106 100644 --- a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/acala.ts +++ b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/acala.ts @@ -6,12 +6,15 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State' import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants'; import { _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; import { fakeAddress } from '@subwallet/extension-base/services/earning-service/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseYieldStepDetail, EarningStatus, HandleYieldStepData, LiquidYieldPoolInfo, OptimalYieldPath, OptimalYieldPathParams, RuntimeDispatchInfo, SubmitYieldJoinData, TokenBalanceRaw, TransactionData, UnstakingInfo, UnstakingStatus, YieldPoolMethodInfo, YieldPositionInfo, YieldStepType, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { BN, BN_TEN, BN_ZERO } from '@polkadot/util'; import BaseLiquidStakingPoolHandler from './base'; +const acalaLiquidStakingLogger = createLogger('AcalaLiquidStaking'); + interface AcalaLiquidStakingMetaItem { exchangeRate: string, timestamp: string @@ -87,7 +90,7 @@ export default class AcalaLiquidStakingPoolHandler extends BaseLiquidStakingPool }) }).then((res) => { resolve(res.json()); - }).catch(console.error); + }).catch((error) => acalaLiquidStakingLogger.error('Error in acala liquid staking', error)); }); const [_toBondPool, _totalStakingBonded, _stakingMeta] = await Promise.all([ diff --git a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts index cac95530c57..7407b2c147e 100644 --- a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts +++ b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost-manta.ts @@ -5,10 +5,13 @@ import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/K import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _getAssetDecimals, _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; import { CHANNEL_ID } from '@subwallet/extension-base/services/earning-service/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseYieldStepDetail, HandleYieldStepData, LiquidYieldPoolInfo, OptimalYieldPath, SubmitYieldJoinData, TransactionData, YieldStepType } from '@subwallet/extension-base/types'; import BifrostLiquidStakingPoolHandler from './bifrost'; +const bifrostMantaLiquidStakingLogger = createLogger('BifrostMantaLiquidStaking'); + export interface BifrostLiquidStakingMeta { apy: string, apyBase: string, @@ -65,7 +68,7 @@ export default class BifrostMantaLiquidStakingPoolHandler extends BifrostLiquidS method: 'GET' }).then((res) => { resolve(res.json()); - }).catch(console.error); + }).catch((error) => bifrostMantaLiquidStakingLogger.error('Error in bifrost manta liquid staking', error)); }); const exchangeRatePromise = new Promise(function (resolve) { @@ -73,7 +76,7 @@ export default class BifrostMantaLiquidStakingPoolHandler extends BifrostLiquidS method: 'GET' }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((error) => bifrostMantaLiquidStakingLogger.error('Error in bifrost manta liquid staking', error)); }); const derivativeTokenInfo = this.state.getAssetBySlug(this.derivativeAssets[0]); diff --git a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts index 718d04fced4..97af632e810 100644 --- a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts +++ b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/bifrost.ts @@ -6,6 +6,7 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State' import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants'; import { _getAssetDecimals, _getTokenOnChainInfo } from '@subwallet/extension-base/services/chain-service/utils'; import { CHANNEL_ID, fakeAddress } from '@subwallet/extension-base/services/earning-service/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseYieldStepDetail, EarningStatus, HandleYieldStepData, LiquidYieldPoolInfo, LiquidYieldPositionInfo, OptimalYieldPath, OptimalYieldPathParams, RuntimeDispatchInfo, SubmitYieldJoinData, TokenBalanceRaw, TransactionData, UnstakingInfo, UnstakingStatus, YieldPoolMethodInfo, YieldPositionInfo, YieldStepType, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { reformatAddress } from '@subwallet/extension-base/utils'; import BigNumber from 'bignumber.js'; @@ -14,6 +15,8 @@ import { BN, BN_ZERO } from '@polkadot/util'; import BaseLiquidStakingPoolHandler from './base'; +const bifrostLiquidStakingLogger = createLogger('BifrostLiquidStaking'); + export interface BifrostLiquidStakingMeta { apy: string, apyBase: string, @@ -97,7 +100,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo method: 'GET' }).then((res) => { resolve(res.json()); - }).catch(console.error); + }).catch((error) => bifrostLiquidStakingLogger.error('Error in bifrost liquid staking', error)); }); const exchangeRatePromise = new Promise(function (resolve) { @@ -111,7 +114,7 @@ export default class BifrostLiquidStakingPoolHandler extends BaseLiquidStakingPo }) }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((error) => bifrostLiquidStakingLogger.error('Error in bifrost liquid staking', error)); }); const derivativeTokenInfo = this.state.getAssetBySlug(this.derivativeAssets[0]); diff --git a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/stella-swap.ts b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/stella-swap.ts index b4332bda255..f834f58a548 100644 --- a/packages/extension-base/src/services/earning-service/handlers/liquid-staking/stella-swap.ts +++ b/packages/extension-base/src/services/earning-service/handlers/liquid-staking/stella-swap.ts @@ -8,6 +8,7 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State' import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getAssetDecimals, _getContractAddressOfToken } from '@subwallet/extension-base/services/chain-service/utils'; import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ApproveStepMetadata, BaseYieldStepDetail, BasicTxErrorType, EarningStatus, HandleYieldStepData, LiquidYieldPoolInfo, OptimalYieldPath, OptimalYieldPathParams, SubmitYieldJoinData, TokenSpendingApprovalParams, TransactionData, UnstakingInfo, UnstakingStatus, YieldPoolMethodInfo, YieldPositionInfo, YieldStepType, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { combineEthFee } from '@subwallet/extension-base/utils'; import { TransactionConfig } from 'web3-core'; @@ -18,6 +19,8 @@ import { BN, BN_TEN, BN_ZERO } from '@polkadot/util'; import { ST_LIQUID_TOKEN_ABI } from '../../constants'; import BaseLiquidStakingPoolHandler from './base'; +const stellaSwapLiquidStakingLogger = createLogger('StellaSwapLiquidStaking'); + export const getStellaswapLiquidStakingContract = (networkKey: string, assetAddress: string, evmApi: _EvmApi, options = {}): Contract => { // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access @@ -85,7 +88,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin method: 'GET' }).then((res) => { resolve(res.json()); - }).catch(console.error); + }).catch((error) => stellaSwapLiquidStakingLogger.error('Error in stella swap liquid staking', error)); }); const sampleTokenShare = 10 ** _getAssetDecimals(derivativeTokenInfo); @@ -298,7 +301,7 @@ export default class StellaSwapLiquidStakingPoolHandler extends BaseLiquidStakin break; } catch (e) { - console.error(e); + stellaSwapLiquidStakingLogger.error('Error in stella swap liquid staking', e); } } diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/astar.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/astar.ts index 3173cd8aad7..dc4136cd491 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/astar.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/astar.ts @@ -7,6 +7,7 @@ import { ExtrinsicType, NominationInfo, UnstakingInfo } from '@subwallet/extensi import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; import { _STAKING_ERA_LENGTH_MAP } from '@subwallet/extension-base/services/chain-service/constants'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseYieldPositionInfo, BasicTxErrorType, EarningStatus, NativeYieldPoolInfo, PalletDappsStakingAccountLedger, PalletDappsStakingDappInfo, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, TransactionData, UnstakingStatus, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPositionInfo, YieldStepBaseInfo, YieldStepType, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { balanceFormatter, formatNumber, isUrl, parseRawNumber, reformatAddress } from '@subwallet/extension-base/utils'; @@ -18,6 +19,8 @@ import { isEthereumAddress } from '@polkadot/util-crypto'; import BaseParaNativeStakingPoolHandler from './base-para'; +const astarStakingLogger = createLogger('AstarStaking'); + const convertAddress = (address: string) => { return isEthereumAddress(address) ? address.toLowerCase() : address; }; @@ -94,7 +97,7 @@ export default class AstarNativeStakingPoolHandler extends BaseParaNativeStaking }).then((resp) => { resolve(resp.json()); }).catch((e) => { - console.error(e); + astarStakingLogger.error('Error in astar staking', e); resolve(null); }); }); @@ -188,7 +191,7 @@ export default class AstarNativeStakingPoolHandler extends BaseParaNativeStaking method: 'GET' }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((error) => astarStakingLogger.error('Error in astar staking', error)); }); const [_allDapps, _era, _stakerInfo] = await Promise.all([ @@ -386,7 +389,7 @@ export default class AstarNativeStakingPoolHandler extends BaseParaNativeStaking method: 'GET' }).then((resp) => { resolve(resp.json()); - }).catch(console.error); + }).catch((error) => astarStakingLogger.error('Error in astar staking', error)); }); const [_era, _allDapps] = await Promise.all([ diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts index 9c5869da5b2..37a57041f94 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/base.ts @@ -5,12 +5,15 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { STAKING_IDENTITY_API_SLUG } from '@subwallet/extension-base/services/earning-service/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BasicTxErrorType, EarningRewardHistoryItem, EarningRewardItem, HandleYieldStepData, OptimalYieldPath, OptimalYieldPathParams, RequestBondingSubmit, SubmitChangeValidatorStaking, SubmitJoinNativeStaking, SubmitYieldJoinData, TransactionData, ValidatorInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldStepBaseInfo, YieldStepType, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { noop } from '@polkadot/util'; import BasePoolHandler from '../base'; +const baseNativeStakingLogger = createLogger('BaseNativeStaking'); + export default abstract class BaseNativeStakingPoolHandler extends BasePoolHandler { public readonly type = YieldPoolType.NATIVE_STAKING; protected readonly name: string; @@ -105,14 +108,14 @@ export default abstract class BaseNativeStakingPoolHandler extends BasePoolHandl } } }) - .catch(console.error); + .catch((error) => baseNativeStakingLogger.error('Error in base native staking', error)); } }) - .catch(console.error); + .catch((error) => baseNativeStakingLogger.error('Error in base native staking', error)); } return Promise.resolve(() => { - console.log('Cancel get pool reward history', requestGroupId); + baseNativeStakingLogger.debug('Cancel get pool reward history', requestGroupId); cancel = false; this.state.subscanService.cancelGroupRequest(requestGroupId); }); diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/dtao.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/dtao.ts index f4f65f59afb..91858efd9ff 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/dtao.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/dtao.ts @@ -11,9 +11,12 @@ import { reformatAddress } from '@subwallet/extension-base/utils'; import BigN from 'bignumber.js'; import { BN, BN_ZERO } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import TaoNativeStakingPoolHandler, { DEFAULT_DTAO_MINBOND, RateSubnetData, TaoStakeInfo, TaoStakingStakeOption } from './tao'; +const dtaoStakingLogger = createLogger('DtaoStaking'); + export interface SubnetData { netuid: number; name: string; @@ -239,7 +242,7 @@ export default class SubnetTaoStakingPoolHandler extends TaoNativeStakingPoolHan this.isInit = true; } } catch (err) { - console.error(err); + dtaoStakingLogger.error('Error in dtao staking', err); this.isInit = false; } } @@ -304,12 +307,12 @@ export default class SubnetTaoStakingPoolHandler extends TaoNativeStakingPoolHan callback(data); } } catch (error) { - console.error('Error updating staking info:', error); + dtaoStakingLogger.error('Error updating staking info:', error); } }; const subscribeStakingMetadataInterval = () => { - updateStakingInfo().catch(console.error); + updateStakingInfo().catch((error) => dtaoStakingLogger.error('Error updating staking info', error)); }; subscribeStakingMetadataInterval(); @@ -412,7 +415,7 @@ export default class SubnetTaoStakingPoolHandler extends TaoNativeStakingPoolHan } }); }) - .catch(console.error); + .catch((error) => dtaoStakingLogger.error('Error in dtao staking', error)); } else { rsCallback({ ...defaultInfo, @@ -447,10 +450,10 @@ export default class SubnetTaoStakingPoolHandler extends TaoNativeStakingPoolHan await getPoolPosition(); }; - getStakingPositionInterval().catch(console.error); + getStakingPositionInterval().catch((error) => dtaoStakingLogger.error('Error in getStakingPositionInterval', error)); const intervalId = setInterval(() => { - getStakingPositionInterval().catch(console.error); + getStakingPositionInterval().catch((error) => dtaoStakingLogger.error('Error in getStakingPositionInterval', error)); }, BITTENSOR_REFRESH_STAKE_INFO); return () => { diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/tanssi.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/tanssi.ts index 443c456eccf..0e220bbf004 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/tanssi.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/tanssi.ts @@ -5,6 +5,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr import { APIItemState, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; import { _getAssetDecimals } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BasicTxErrorType, EarningRewardItem, EarningStatus, NativeYieldPoolInfo, NominationInfo, StakeCancelWithdrawalParams, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolTarget, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; import { formatNumber } from '@subwallet/extension-base/utils'; import BigN from 'bignumber.js'; @@ -15,6 +16,8 @@ import { AnyJson } from '@polkadot/types/types'; import { parseIdentity } from '../../utils'; import BaseParaNativeStakingPoolHandler from './base-para'; +const tanssiStakingLogger = createLogger('TanssiStaking'); + interface SortedEligibleCandidate { candidate: string; stake: string; @@ -373,10 +376,10 @@ export default class TanssiNativeStakingPoolHandler extends BaseParaNativeStakin }); }; - fetchAndUpdate().catch(console.error); + fetchAndUpdate().catch((error) => tanssiStakingLogger.error('Error in fetchAndUpdate', error)); const intervalId = setInterval(() => { - fetchAndUpdate().catch(console.error); + fetchAndUpdate().catch((error) => tanssiStakingLogger.error('Error in fetchAndUpdate', error)); }, 30000); intervalIds.push(intervalId); diff --git a/packages/extension-base/src/services/earning-service/handlers/native-staking/tao.ts b/packages/extension-base/src/services/earning-service/handlers/native-staking/tao.ts index c9dd4fc4df7..427127a26b4 100644 --- a/packages/extension-base/src/services/earning-service/handlers/native-staking/tao.ts +++ b/packages/extension-base/src/services/earning-service/handlers/native-staking/tao.ts @@ -1,819 +1,822 @@ -// Copyright 2019-2022 @subwallet/extension-base -// SPDX-License-Identifier: Apache-2.0 - -import { _ChainInfo } from '@subwallet/chain-list/types'; -import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; -import { ExtrinsicType, NominationInfo } from '@subwallet/extension-base/background/KoniTypes'; -import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subwallet/extension-base/constants'; -import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; -import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; -import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; -import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils'; -import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para'; -import { BaseYieldPositionInfo, BasicTxErrorType, EarningStatus, NativeYieldPoolInfo, OptimalYieldPath, StakeCancelWithdrawalParams, StakingTxErrorType, SubmitBittensorChangeValidatorStaking, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; -import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment'; -import { fetchFromProxyService, formatNumber, reformatAddress } from '@subwallet/extension-base/utils'; -import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache'; -import BigN from 'bignumber.js'; -import { t } from 'i18next'; -import { BehaviorSubject, combineLatest } from 'rxjs'; - -import { BN, BN_ZERO } from '@polkadot/util'; - -import { fetchPoolsData } from '../../service'; - -type Nominators = [Array<[number, number]>] - -export interface TestnetBittensorDelegateInfo { - delegateSs58: string; - take: number; - nominators: Nominators; - returnPer1000: number -} - -export interface TaoStakeInfo { - hotkey: string; - stake: string; - netuid: number; -} - -export interface TaoStakingStakeOption { - owner: string; - amount: string; - rate?: BigN; - identity?: string -} - -export interface RawDelegateState { - data: Array<{ - hotkey_name: string; - hotkey: { - ss58: string; - }; - stake: string; - }>; -} - -interface ValidatorResponse { - data: Validator[]; -} - -interface Validator { - hotkey: { - ss58: string; - }; - name: string; - global_nominators: number; - validator_return_per_day: string; - nominator_return_per_day: string; - stake: string; - validator_stake: string; - take: string; - root_stake: string; - global_weighted_stake: string; - weighted_root_stake: string; - global_alpha_stake_as_tao: string; -} - -interface ValidatorAprResponse { - data: ValidatorApr[]; -} - -interface ValidatorApr { - hotkey: { - ss58: string; - }, - name: string; - netuid: number; - thirty_day_apy: string; -} - -export interface RateSubnetData { - netuid: number; - taoIn: string; - alphaIn: string; - alphaOut: string; -} - -interface SubnetRateFeeResponse { - data: SubnetFeeRate[]; -} - -interface SubnetFeeRate { - netuid: number; - fee_rate: string; -} - -const DEFAULT_BITTENSOR_SLIPPAGE = 0.005; - -export const DEFAULT_DTAO_MINBOND = '21000000'; -/* Fetch data */ -export class BittensorCache { - private static instance: BittensorCache | null = null; - private cache: ValidatorResponse | null = null; - private cacheTimeout: NodeJS.Timeout | null = null; - private promise: Promise | null = null; - - // eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function - private constructor () {} - - public static getInstance (): BittensorCache { - if (!BittensorCache.instance) { - BittensorCache.instance = new BittensorCache(); - } - - return BittensorCache.instance; - } - - public async get (): Promise { - if (this.cache) { - return this.cache; - } - - if (this.promise) { - return this.promise; - } - - this.promise = this.fetchData(); - - return this.promise; - } - - private async fetchData (): Promise { - try { - const fetchData = await fetchStaticCache<{ data: Record }>( - 'earning/dtao/validator.json', - { data: {} } - ); - - const validators = Object.values(fetchData.data); - - const data = { - data: validators.filter((validator) => parseFloat(validator.root_stake) > 0) - }; - - this.cache = data; - this.promise = null; - - if (this.cacheTimeout) { - clearTimeout(this.cacheTimeout); - } - - this.cacheTimeout = setTimeout(() => { - this.fetchData() - .then((newData) => { - if (newData.data.length > 0) { - this.cache = newData; - } - }) - .catch(console.error); - }, 60 * 1000); // Cache 1 minute - - return data; - } catch (error) { - console.error(error); - this.promise = null; - - return this.cache || { data: [] }; - } - } - - public async fetchApr (netuid: number): Promise { - try { - const resp = await fetchFromProxyService(ProxyServiceRoute.BITTENSOR, `/dtao/validator/yield/latest/v1?netuid=${netuid}&limit=100&order=thirty_day_apy_desc`, { - method: 'GET', - headers: { 'Content-Type': 'application/json' } - }); - - const rawData = await resp.json() as ValidatorAprResponse; - - // Some subnets not return data, ensure the structure is consistent by returning an empty array - return Array.isArray(rawData.data) ? rawData : { data: [] }; - } catch (error) { - console.error(error); - - return { data: [] }; - } - } - - public async fetchSubnetFeeRate (netuid: number): Promise { - try { - const resp = await fetchFromProxyService( - ProxyServiceRoute.BITTENSOR, - '/subnet/latest/v1', - { - method: 'GET', - headers: { 'Content-Type': 'application/json' } - } - ); - - const rawData = await resp.json() as SubnetRateFeeResponse; - - const subnet = rawData.data.find((item) => item.netuid === netuid); - - return subnet?.fee_rate ?? '0.0005'; - } catch (error) { - console.error(error); - - return '0.0005'; // Default fee rate if fetch fails - } - } -} - -// export async function fetchTaoDelegateState (address: string): Promise { -// const apiKey = bittensorApiKey(); - -// return new Promise(function (resolve) { -// fetch(`https://api.taostats.io/api/stake_balance/latest/v1?coldkey=${address}`, { -// method: 'GET', -// headers: { -// 'Content-Type': 'application/json', -// Authorization: `${apiKey}` -// } -// }).then((resp) => { -// resolve(resp.json()); -// }).catch(console.error); -// }); -// } - -/* Fetch data */ - -// const testnetDelegate = { -// '5G6wdAdS7hpBuH1tjuZDhpzrGw9Wf71WEVakDCxHDm1cxEQ2': { -// name: '0x436c6f776e4e616d65f09fa4a1', -// url: 'https://example.com ', -// image: 'https://example.com/image.png', -// discord: '0xe28094446973636f7264', -// description: 'This is an example identity.', -// additional: '' -// } -// }; - -export const getAlphaToTaoRate = async (substrateApi: _SubstrateApi, netuid: number): Promise => { - const subnetInfo = (await substrateApi.api.call.subnetInfoRuntimeApi.getDynamicInfo(netuid)).toJSON() as RateSubnetData | undefined; - - if (!subnetInfo) { - return '1'; - } - - const taoIn = subnetInfo.taoIn ? new BigN(subnetInfo.taoIn) : new BigN(0); - const alphaIn = subnetInfo.alphaIn ? new BigN(subnetInfo.alphaIn) : new BigN(0); - - return netuid === 0 || alphaIn.lte(0) ? '1' : taoIn.dividedBy(alphaIn).toString(); -}; - -export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler { - override readonly availableMethod: YieldPoolMethodInfo = { - join: true, - defaultUnstake: true, - fastUnstake: false, - cancelUnstake: false, - withdraw: false, - claimReward: false, - changeValidator: true - }; - - protected bittensorCache: BittensorCache; - - protected async getMinBond (netuid?: number): Promise { - // @ts-ignore - if (this.type === YieldPoolType.SUBNET_STAKING) { - if (!netuid) { - return new BigN(DEFAULT_DTAO_MINBOND); - } - - const subnetSlug = `${this.slug}__subnet_${netuid.toString().padStart(2, '0')}`; - - const cachedPool = await this.getPoolInfo(subnetSlug); - - if (cachedPool?.metadata?.minValidate) { - return new BigN(cachedPool.metadata.minValidate); - } - - // If can't get from cached -> get data online - const onlineData = await fetchPoolsData(); - const onlinePool = onlineData[subnetSlug]; - - return new BigN(onlinePool?.metadata?.minValidate || DEFAULT_DTAO_MINBOND); - } - - const cachedPool = await this.getPoolInfo(this.slug); - - if (cachedPool?.metadata?.minValidate || cachedPool?.statistic?.earningThreshold?.join) { - return new BigN(cachedPool.metadata?.minValidate || cachedPool.statistic?.earningThreshold?.join || 0); - } - - // If can get from cached -> get data online - const onlineData = await fetchPoolsData(); - const onlinePool = onlineData[this.slug]; - - return new BigN(onlinePool?.metadata?.minValidate || onlinePool?.statistic?.earningThreshold?.join || 0); - } - - constructor (state: KoniState, chain: string) { - super(state, chain); - this.bittensorCache = BittensorCache.getInstance(); - } - - /* Unimplemented function */ - public override handleYieldWithdraw (address: string, unstakingInfo: UnstakingInfo): Promise { - return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED)); - } - - public override handleYieldCancelUnstake (params: StakeCancelWithdrawalParams): Promise { - return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED)); - } - /* Unimplemented function */ - - public override get maintainBalance (): string { - const ed = new BigN(this.nativeToken.minAmount || '0'); - const calculateMaintainBalance = new BigN(15).multipliedBy(ed).dividedBy(10); - - const maintainBalance = calculateMaintainBalance; - - return maintainBalance.toString(); - } - - /* Subscribe pool info */ - - async subscribePoolInfo (callback: (data: YieldPoolInfo) => void): Promise { - let cancel = false; - const substrateApi = await this.substrateApi.isReady; - - const aprSubject = new BehaviorSubject(0); - - const fetchAPR = async () => { - try { - const _topValidator = await this.bittensorCache.fetchApr(0); - const validators = _topValidator.data; - const highestApr = validators?.[0]; - - const apr = this.chain === 'bittensor' ? Number(highestApr?.thirty_day_apy || 0) * 100 : 0; - - aprSubject.next(apr); - } catch (e) { - console.error('Fetch APR error:', e); - } - }; - - await fetchAPR(); - - const interval = setInterval(() => { - fetchAPR().catch(console.error); - }, BITTENSOR_REFRESH_STAKE_APY); - - const rxSubnetTAO = substrateApi.api.rx.query.subtensorModule.subnetTAO(0); - const rxMinDelegatorStake = substrateApi.api.rx.query.subtensorModule.nominatorMinRequiredStake(); - const rxMaxValidators = substrateApi.api.rx.query.subtensorModule.maxAllowedValidators(0); - - const subscription = combineLatest([rxMinDelegatorStake, rxMaxValidators, rxSubnetTAO, aprSubject]).subscribe({ - next: ([minDelegatorStake, maxValidators, taoIn, apr]) => { - if (cancel) { - return; - } - - try { - const bnTaoIn = new BigN(taoIn.toString()); - const bnMinStake = new BigN(minDelegatorStake.toString()); - const minStake = bnMinStake.toString(); - const data: NativeYieldPoolInfo = { - ...this.baseInfo, - type: this.type, - metadata: { - ...this.metadataInfo, - description: this.getDescription(formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))), - minValidate: minStake - }, - statistic: { - assetEarning: [{ slug: this.nativeToken.slug }], - maxCandidatePerFarmer: Number(maxValidators.toString()), - maxWithdrawalRequestPerFarmer: 1, - earningThreshold: { - join: minStake, - defaultUnstake: '0', - fastUnstake: '0' - }, - eraTime: 24, - era: 0, - unstakingPeriod: 1.2, - tvl: bnTaoIn.toString(), - totalApy: apr - } - }; - - callback(data); - } catch (err) { - console.error(err); - } - } - }); - - return () => { - cancel = true; - aprSubject.complete(); - subscription.unsubscribe(); - clearInterval(interval); - }; - } - - /* Subscribe pool position */ - - protected parseNominatorMetadataBase (chainInfo: _ChainInfo, delegatorState: TaoStakingStakeOption[], minBond: string, applyRate = false): Omit { - const nominationList: NominationInfo[] = []; - let allActiveStake = BN_ZERO; - - for (const delegate of delegatorState) { - const stake = new BigN(delegate.amount); - const originActiveStake = applyRate ? stake.multipliedBy(delegate.rate || 1).toFixed(0) : stake.toFixed(0); - const bnActiveStake = new BN(originActiveStake); - - if (bnActiveStake.gt(BN_ZERO)) { - allActiveStake = allActiveStake.add(bnActiveStake); - - nominationList.push({ - status: EarningStatus.EARNING_REWARD, - chain: chainInfo.slug, - validatorAddress: delegate.owner, - activeStake: delegate.amount, - validatorMinStake: minBond, - validatorIdentity: delegate.identity, - ...(applyRate ? { originActiveStake } : {}) - }); - } - } - - const stakingStatus = getEarningStatusByNominations(allActiveStake, nominationList); - - return { - status: stakingStatus, - balanceToken: this.nativeToken.slug, - totalStake: allActiveStake.toString(), - activeStake: allActiveStake.toString(), - unstakeBalance: '0', - isBondedBefore: true, - nominations: nominationList, - unstakings: [] - } as unknown as YieldPositionInfo; - } - - async parseNominatorMetadata (chainInfo: _ChainInfo, delegatorState: TaoStakingStakeOption[]): Promise> { - const bnMinBond = await this.getMinBond(); - - return this.parseNominatorMetadataBase(chainInfo, delegatorState, bnMinBond.toString()); - } - - override async subscribePoolPosition (useAddresses: string[], rsCallback: (rs: YieldPositionInfo) => void): Promise { - let cancel = false; - const substrateApi = await this.substrateApi.isReady; - const defaultInfo = this.baseInfo; - const chainInfo = this.chainInfo; - const _delegateInfo = await this.bittensorCache.get(); - - const getPoolPosition = async () => { - const rawDelegateStateInfos = await Promise.all( - useAddresses.map(async (address) => (await substrateApi.api.call.stakeInfoRuntimeApi.getStakeInfoForColdkey(address)).toJSON()) - ); - - if (rawDelegateStateInfos && rawDelegateStateInfos.length > 0) { - rawDelegateStateInfos.forEach((rawDelegateStateInfo, i) => { - const owner = reformatAddress(useAddresses[i], 42); - const delegatorState: TaoStakingStakeOption[] = []; - let bnTotalBalance = BN_ZERO; - - const delegateStateInfo = rawDelegateStateInfo as unknown as TaoStakeInfo[]; - - const totalDelegate: Record = {}; - - for (const delegate of delegateStateInfo) { - const hotkey = delegate.hotkey; - const netuid = delegate.netuid; - const stake = new BigN(delegate.stake); - - if (netuid === 0) { - const taoStake = stake.toFixed(0); - - if (totalDelegate[hotkey]) { - totalDelegate[hotkey] = new BigN(totalDelegate[hotkey]).plus(taoStake).toFixed(); - } else { - totalDelegate[hotkey] = taoStake; - } - } - } - - for (const hotkey in totalDelegate) { - bnTotalBalance = bnTotalBalance.add(new BN(totalDelegate[hotkey])); - let identity = ''; - - if (_delegateInfo) { - const delegateInfo = _delegateInfo.data.find((info) => info.hotkey.ss58 === hotkey); - - identity = delegateInfo ? delegateInfo.name : ''; - } - - delegatorState.push({ - owner: hotkey, - amount: totalDelegate[hotkey], - identity: identity - }); - } - - if (delegateStateInfo && delegateStateInfo.length > 0) { - this.parseNominatorMetadata(chainInfo, delegatorState) - .then((nominatorMetadata) => { - rsCallback({ - ...defaultInfo, - ...nominatorMetadata, - address: owner, - type: this.type - }); - }) - .catch(console.error); - } else { - rsCallback({ - ...defaultInfo, - type: this.type, - address: owner, - balanceToken: this.nativeToken.slug, - totalStake: '0', - activeStake: '0', - unstakeBalance: '0', - status: EarningStatus.NOT_STAKING, - isBondedBefore: false, - nominations: [], - unstakings: [] - }); - } - }); - } - }; - - const getStakingPositionInterval = async () => { - if (cancel) { - return; - } - - await getPoolPosition(); - }; - - getStakingPositionInterval().catch(console.error); - - const intervalId = setInterval(() => { - getStakingPositionInterval().catch(console.error); - }, BITTENSOR_REFRESH_STAKE_INFO); - - return () => { - cancel = true; - clearInterval(intervalId); - }; - } - - // Because not have subscan api - override async checkAccountHaveStake (useAddresses: string[]): Promise { - return Promise.resolve([]); - } - - /* Subscribe pool position */ - - /* Get pool targets */ - // eslint-disable-next-line @typescript-eslint/require-await - private async getDevnetPoolTargets (netuid?: number): Promise { - const testnetDelegate = (await this.substrateApi.api.call.delegateInfoRuntimeApi.getDelegates()).toJSON() as unknown as TestnetBittensorDelegateInfo[]; - const bnMinBond = await this.getMinBond(netuid); - - const filteredDelegates = testnetDelegate.filter((delegate) => { - return delegate.returnPer1000 !== 0; - }); - - return filteredDelegates.map((delegate) => ({ - address: delegate.delegateSs58, - totalStake: '0', - ownStake: '0', - otherStake: '0', - minBond: bnMinBond.toString(), - nominatorCount: delegate.nominators.length, - commission: delegate.take / 1000, - blocked: false, - isVerified: false, - chain: this.chain, - isCrowded: false - }) as unknown as ValidatorInfo); - } - - private async getMainnetPoolTargets (netuid: number): Promise { - const _topValidator = await this.bittensorCache.get(); - - const topValidator = _topValidator; - const bnMinBond = await this.getMinBond(); - const validatorList = topValidator.data; - - const aprResponse = await this.bittensorCache.fetchApr(netuid); - const aprMap: Record = {}; - - aprResponse.data.forEach((item) => { - aprMap[item.hotkey.ss58] = item.thirty_day_apy; - }); - - const results = await Promise.all( - validatorList.map((validator) => { - const address = validator.hotkey.ss58; - // With bittensor we use total weight, root weight and alpha staked insted of total stake, own stake and other stake - const bnTotalWeightStake = new BigN(validator.global_weighted_stake); - const bnRootWeightStake = new BigN(validator.weighted_root_stake); - const bnAlphaStake = new BigN(validator.global_alpha_stake_as_tao); - - const nominatorCount = validator.global_nominators; - const commission = validator.take; - const roundedCommission = (parseFloat(commission) * 100).toFixed(0); - - const apr = aprMap[address]; - const expectedReturn = apr ? new BigN(apr).multipliedBy(100).toFixed(2) : '0'; - - const name = validator.name || address; - - return { - address: address, - totalStake: bnTotalWeightStake.toString(), - ownStake: bnRootWeightStake.toString(), - otherStake: bnAlphaStake.toString(), - minBond: bnMinBond.toString(), - nominatorCount: nominatorCount, - commission: roundedCommission, - expectedReturn: expectedReturn, - blocked: false, - isVerified: false, - chain: this.chain, - isCrowded: false, - identity: name - } as unknown as ValidatorInfo; - }) - ); - - return results; - } - - async getPoolTargets (netuid?: number): Promise { - if (this.chain === 'bittensor') { - return this.getMainnetPoolTargets(netuid ?? 0); - } else { - return this.getDevnetPoolTargets(netuid); - } - } - - /* Get pool targets */ - - /* Join pool action */ - - override async createJoinExtrinsic ( - data: SubmitJoinNativeStaking, - positionInfo?: YieldPositionInfo, - bondDest = 'Staked' - ): Promise<[TransactionData, YieldTokenBaseInfo]> { - const { amount, selectedValidators: targetValidators, subnetData } = data; - - const chainApi = await this.substrateApi.isReady; - const binaryAmount = new BigN(amount); - const selectedValidatorInfo = targetValidators[0]; - const hotkey = selectedValidatorInfo.address; - - const netuid = subnetData?.netuid ?? 0; - const slippage = subnetData?.slippage ?? DEFAULT_BITTENSOR_SLIPPAGE; - - const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid)); - const limitPrice = alphaToTaoPrice - .multipliedBy(10 ** _getAssetDecimals(this.nativeToken)) - .multipliedBy(1 + slippage); - - const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed()); - - const extrinsic = chainApi.api.tx.subtensorModule.addStakeLimit( - hotkey, - netuid, - binaryAmount.toFixed(), - BNlimitPrice.toFixed(), - false - ); - - return [extrinsic, { slug: this.nativeToken.slug, amount: '0' }]; - } - - // Validate for case stake more - public override async validateYieldJoin (data: SubmitJoinNativeStaking, path: OptimalYieldPath): Promise { - const baseErrors = await super.validateYieldJoin(data, path); - - if (baseErrors.length > 0) { - return baseErrors; - } - - const { amount, subnetData } = data; - - const bnMinStake = await this.getMinBond(subnetData?.netuid); - - if (new BigN(amount).lt(bnMinStake)) { - return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.insufficientStakeToEarn', { replace: { bnMinStake: formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken)), symbol: _getAssetSymbol(this.nativeToken) } }))]; - } - - return baseErrors; - } - - /* Join pool action */ - - /* Leave pool action */ - - override async handleYieldUnstake (amount: string, address: string, selectedTarget?: string, netuid = 0, slippage: number = DEFAULT_BITTENSOR_SLIPPAGE): Promise<[ExtrinsicType, TransactionData]> { - const apiPromise = await this.substrateApi.isReady; - - if (!selectedTarget) { - return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS)); - } - - const binaryAmount = new BigN(amount); - - const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid)); - const limitPrice = alphaToTaoPrice - .multipliedBy(10 ** _getAssetDecimals(this.nativeToken)) - .multipliedBy(1 - slippage); - - const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed()); - - const extrinsic = apiPromise.api.tx.subtensorModule.removeStakeLimit( - selectedTarget, - netuid, - binaryAmount.toFixed(), - BNlimitPrice.toFixed(), - false - ); - - return [ExtrinsicType.STAKING_UNBOND, extrinsic]; - } - - public override async validateYieldLeave (amount: string, address: string, fastLeave: boolean, selectedTarget?: string, slug?: string, poolInfo?: YieldPoolInfo): Promise { - const baseErrors = await super.validateYieldLeave(amount, address, fastLeave, selectedTarget, slug); - - if (baseErrors.length > 0) { - return baseErrors; - } - - if (!poolInfo) { - return [new TransactionError(BasicTxErrorType.INVALID_PARAMS)]; - } - - const netuid = poolInfo.metadata.subnetData?.netuid; - const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid || 0)); - - const minDelegatorStake = await this.getMinBond(netuid); - - const minUnstake = minDelegatorStake.dividedBy(alphaToTaoPrice); - - if (new BigN(amount).lt(minUnstake)) { - return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.unstakeAmountTooLow', { replace: { bnMinUnstake: formatNumber(minUnstake, _getAssetDecimals(this.nativeToken)), symbol: poolInfo.metadata.subnetData?.subnetSymbol || _getAssetSymbol(this.nativeToken) } }))]; - } - - return baseErrors; - } - - /* Leave pool action */ - - /* Change validator */ - override async handleChangeEarningValidator (data: SubmitBittensorChangeValidatorStaking): Promise { - const chainApi = await this.substrateApi.isReady; - const { amount, maxAmount, metadata, originValidator, selectedValidators: targetValidators, subnetData } = data; - - if (!originValidator) { - return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS)); - } - - const netuid = subnetData?.netuid || 0; - const selectedValidatorInfo = targetValidators[0]; - const destValidator = selectedValidatorInfo.address; - - if (new BigN(amount).lte(0)) { - return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.amountMustBeGreaterThanZero'))); - } - - if (originValidator === destValidator) { - return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.fromValidatorSameAsTo'))); - } - - const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid)); - const bnMinStake = await this.getMinBond(netuid); - const minUnstake = bnMinStake.dividedBy(alphaToTaoPrice); - - const formattedMinUnstake = minUnstake.dividedBy(1000000).integerValue(BigN.ROUND_CEIL).dividedBy(1000); - - const bnMinMoveStake = formattedMinUnstake.multipliedBy(10 ** _getAssetDecimals(this.nativeToken)); - - if (new BigN(amount).lt(bnMinMoveStake)) { - return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.moveStakeAmountTooLow', { replace: { bnMinMoveStake: formattedMinUnstake.toString(), symbol: metadata?.subnetSymbol || '' } }))); - } - - // Avoid remaining amount too low -> can't do anything with that amount - if (!(maxAmount === amount) && new BigN(maxAmount).minus(new BigN(amount)).lt(bnMinMoveStake)) { - return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, - t('bg.EARNING.services.service.earning.nativeStaking.tao.remainingStakeBelowMinimumWarning', { replace: { maxAmount: formatNumber(maxAmount, _getAssetDecimals(this.nativeToken)), subnetSymbol: metadata?.subnetSymbol || _getAssetSymbol(this.nativeToken) } }))); - } - - const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator, netuid, netuid, amount); - - return extrinsic; - } -} +// Copyright 2019-2022 @subwallet/extension-base +// SPDX-License-Identifier: Apache-2.0 + +import { _ChainInfo } from '@subwallet/chain-list/types'; +import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError'; +import { ExtrinsicType, NominationInfo } from '@subwallet/extension-base/background/KoniTypes'; +import { BITTENSOR_REFRESH_STAKE_APY, BITTENSOR_REFRESH_STAKE_INFO } from '@subwallet/extension-base/constants'; +import { getEarningStatusByNominations } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; +import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; +import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/types'; +import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils'; +import BaseParaStakingPoolHandler from '@subwallet/extension-base/services/earning-service/handlers/native-staking/base-para'; +import { BaseYieldPositionInfo, BasicTxErrorType, EarningStatus, NativeYieldPoolInfo, OptimalYieldPath, StakeCancelWithdrawalParams, StakingTxErrorType, SubmitBittensorChangeValidatorStaking, SubmitJoinNativeStaking, TransactionData, UnstakingInfo, ValidatorInfo, YieldPoolInfo, YieldPoolMethodInfo, YieldPoolType, YieldPositionInfo, YieldTokenBaseInfo } from '@subwallet/extension-base/types'; +import { ProxyServiceRoute } from '@subwallet/extension-base/types/environment'; +import { fetchFromProxyService, formatNumber, reformatAddress } from '@subwallet/extension-base/utils'; +import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache'; +import BigN from 'bignumber.js'; +import { t } from 'i18next'; +import { BehaviorSubject, combineLatest } from 'rxjs'; + +import { BN, BN_ZERO } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +import { fetchPoolsData } from '../../service'; + +const taoStakingLogger = createLogger('TaoStaking'); + +type Nominators = [Array<[number, number]>] + +export interface TestnetBittensorDelegateInfo { + delegateSs58: string; + take: number; + nominators: Nominators; + returnPer1000: number +} + +export interface TaoStakeInfo { + hotkey: string; + stake: string; + netuid: number; +} + +export interface TaoStakingStakeOption { + owner: string; + amount: string; + rate?: BigN; + identity?: string +} + +export interface RawDelegateState { + data: Array<{ + hotkey_name: string; + hotkey: { + ss58: string; + }; + stake: string; + }>; +} + +interface ValidatorResponse { + data: Validator[]; +} + +interface Validator { + hotkey: { + ss58: string; + }; + name: string; + global_nominators: number; + validator_return_per_day: string; + nominator_return_per_day: string; + stake: string; + validator_stake: string; + take: string; + root_stake: string; + global_weighted_stake: string; + weighted_root_stake: string; + global_alpha_stake_as_tao: string; +} + +interface ValidatorAprResponse { + data: ValidatorApr[]; +} + +interface ValidatorApr { + hotkey: { + ss58: string; + }, + name: string; + netuid: number; + thirty_day_apy: string; +} + +export interface RateSubnetData { + netuid: number; + taoIn: string; + alphaIn: string; + alphaOut: string; +} + +interface SubnetRateFeeResponse { + data: SubnetFeeRate[]; +} + +interface SubnetFeeRate { + netuid: number; + fee_rate: string; +} + +const DEFAULT_BITTENSOR_SLIPPAGE = 0.005; + +export const DEFAULT_DTAO_MINBOND = '21000000'; +/* Fetch data */ +export class BittensorCache { + private static instance: BittensorCache | null = null; + private cache: ValidatorResponse | null = null; + private cacheTimeout: NodeJS.Timeout | null = null; + private promise: Promise | null = null; + + // eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function + private constructor () {} + + public static getInstance (): BittensorCache { + if (!BittensorCache.instance) { + BittensorCache.instance = new BittensorCache(); + } + + return BittensorCache.instance; + } + + public async get (): Promise { + if (this.cache) { + return this.cache; + } + + if (this.promise) { + return this.promise; + } + + this.promise = this.fetchData(); + + return this.promise; + } + + private async fetchData (): Promise { + try { + const fetchData = await fetchStaticCache<{ data: Record }>( + 'earning/dtao/validator.json', + { data: {} } + ); + + const validators = Object.values(fetchData.data); + + const data = { + data: validators.filter((validator) => parseFloat(validator.root_stake) > 0) + }; + + this.cache = data; + this.promise = null; + + if (this.cacheTimeout) { + clearTimeout(this.cacheTimeout); + } + + this.cacheTimeout = setTimeout(() => { + this.fetchData() + .then((newData) => { + if (newData.data.length > 0) { + this.cache = newData; + } + }) + .catch((error) => taoStakingLogger.error('Error fetching delegate state', error)); + }, 60 * 1000); // Cache 1 minute + + return data; + } catch (error) { + taoStakingLogger.error('Error fetching delegate state', error); + this.promise = null; + + return this.cache || { data: [] }; + } + } + + public async fetchApr (netuid: number): Promise { + try { + const resp = await fetchFromProxyService(ProxyServiceRoute.BITTENSOR, `/dtao/validator/yield/latest/v1?netuid=${netuid}&limit=100&order=thirty_day_apy_desc`, { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + + const rawData = await resp.json() as ValidatorAprResponse; + + // Some subnets not return data, ensure the structure is consistent by returning an empty array + return Array.isArray(rawData.data) ? rawData : { data: [] }; + } catch (error) { + taoStakingLogger.error('Error fetching delegate state by subnet', error); + + return { data: [] }; + } + } + + public async fetchSubnetFeeRate (netuid: number): Promise { + try { + const resp = await fetchFromProxyService( + ProxyServiceRoute.BITTENSOR, + '/subnet/latest/v1', + { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + } + ); + + const rawData = await resp.json() as SubnetRateFeeResponse; + + const subnet = rawData.data.find((item) => item.netuid === netuid); + + return subnet?.fee_rate ?? '0.0005'; + } catch (error) { + taoStakingLogger.error('Error fetching subnet fee rate', error); + + return '0.0005'; // Default fee rate if fetch fails + } + } +} + +// export async function fetchTaoDelegateState (address: string): Promise { +// const apiKey = bittensorApiKey(); + +// return new Promise(function (resolve) { +// fetch(`https://api.taostats.io/api/stake_balance/latest/v1?coldkey=${address}`, { +// method: 'GET', +// headers: { +// 'Content-Type': 'application/json', +// Authorization: `${apiKey}` +// } +// }).then((resp) => { +// resolve(resp.json()); +// }).catch(console.error); +// }); +// } + +/* Fetch data */ + +// const testnetDelegate = { +// '5G6wdAdS7hpBuH1tjuZDhpzrGw9Wf71WEVakDCxHDm1cxEQ2': { +// name: '0x436c6f776e4e616d65f09fa4a1', +// url: 'https://example.com ', +// image: 'https://example.com/image.png', +// discord: '0xe28094446973636f7264', +// description: 'This is an example identity.', +// additional: '' +// } +// }; + +export const getAlphaToTaoRate = async (substrateApi: _SubstrateApi, netuid: number): Promise => { + const subnetInfo = (await substrateApi.api.call.subnetInfoRuntimeApi.getDynamicInfo(netuid)).toJSON() as RateSubnetData | undefined; + + if (!subnetInfo) { + return '1'; + } + + const taoIn = subnetInfo.taoIn ? new BigN(subnetInfo.taoIn) : new BigN(0); + const alphaIn = subnetInfo.alphaIn ? new BigN(subnetInfo.alphaIn) : new BigN(0); + + return netuid === 0 || alphaIn.lte(0) ? '1' : taoIn.dividedBy(alphaIn).toString(); +}; + +export default class TaoNativeStakingPoolHandler extends BaseParaStakingPoolHandler { + override readonly availableMethod: YieldPoolMethodInfo = { + join: true, + defaultUnstake: true, + fastUnstake: false, + cancelUnstake: false, + withdraw: false, + claimReward: false, + changeValidator: true + }; + + protected bittensorCache: BittensorCache; + + protected async getMinBond (netuid?: number): Promise { + // @ts-ignore + if (this.type === YieldPoolType.SUBNET_STAKING) { + if (!netuid) { + return new BigN(DEFAULT_DTAO_MINBOND); + } + + const subnetSlug = `${this.slug}__subnet_${netuid.toString().padStart(2, '0')}`; + + const cachedPool = await this.getPoolInfo(subnetSlug); + + if (cachedPool?.metadata?.minValidate) { + return new BigN(cachedPool.metadata.minValidate); + } + + // If can't get from cached -> get data online + const onlineData = await fetchPoolsData(); + const onlinePool = onlineData[subnetSlug]; + + return new BigN(onlinePool?.metadata?.minValidate || DEFAULT_DTAO_MINBOND); + } + + const cachedPool = await this.getPoolInfo(this.slug); + + if (cachedPool?.metadata?.minValidate || cachedPool?.statistic?.earningThreshold?.join) { + return new BigN(cachedPool.metadata?.minValidate || cachedPool.statistic?.earningThreshold?.join || 0); + } + + // If can get from cached -> get data online + const onlineData = await fetchPoolsData(); + const onlinePool = onlineData[this.slug]; + + return new BigN(onlinePool?.metadata?.minValidate || onlinePool?.statistic?.earningThreshold?.join || 0); + } + + constructor (state: KoniState, chain: string) { + super(state, chain); + this.bittensorCache = BittensorCache.getInstance(); + } + + /* Unimplemented function */ + public override handleYieldWithdraw (address: string, unstakingInfo: UnstakingInfo): Promise { + return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED)); + } + + public override handleYieldCancelUnstake (params: StakeCancelWithdrawalParams): Promise { + return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED)); + } + /* Unimplemented function */ + + public override get maintainBalance (): string { + const ed = new BigN(this.nativeToken.minAmount || '0'); + const calculateMaintainBalance = new BigN(15).multipliedBy(ed).dividedBy(10); + + const maintainBalance = calculateMaintainBalance; + + return maintainBalance.toString(); + } + + /* Subscribe pool info */ + + async subscribePoolInfo (callback: (data: YieldPoolInfo) => void): Promise { + let cancel = false; + const substrateApi = await this.substrateApi.isReady; + + const aprSubject = new BehaviorSubject(0); + + const fetchAPR = async () => { + try { + const _topValidator = await this.bittensorCache.fetchApr(0); + const validators = _topValidator.data; + const highestApr = validators?.[0]; + + const apr = this.chain === 'bittensor' ? Number(highestApr?.thirty_day_apy || 0) * 100 : 0; + + aprSubject.next(apr); + } catch (e) { + taoStakingLogger.error('Fetch APR error:', e); + } + }; + + await fetchAPR(); + + const interval = setInterval(() => { + fetchAPR().catch((error) => taoStakingLogger.error('Error fetching APR', error)); + }, BITTENSOR_REFRESH_STAKE_APY); + + const rxSubnetTAO = substrateApi.api.rx.query.subtensorModule.subnetTAO(0); + const rxMinDelegatorStake = substrateApi.api.rx.query.subtensorModule.nominatorMinRequiredStake(); + const rxMaxValidators = substrateApi.api.rx.query.subtensorModule.maxAllowedValidators(0); + + const subscription = combineLatest([rxMinDelegatorStake, rxMaxValidators, rxSubnetTAO, aprSubject]).subscribe({ + next: ([minDelegatorStake, maxValidators, taoIn, apr]) => { + if (cancel) { + return; + } + + try { + const bnTaoIn = new BigN(taoIn.toString()); + const bnMinStake = new BigN(minDelegatorStake.toString()); + const minStake = bnMinStake.toString(); + const data: NativeYieldPoolInfo = { + ...this.baseInfo, + type: this.type, + metadata: { + ...this.metadataInfo, + description: this.getDescription(formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken))), + minValidate: minStake + }, + statistic: { + assetEarning: [{ slug: this.nativeToken.slug }], + maxCandidatePerFarmer: Number(maxValidators.toString()), + maxWithdrawalRequestPerFarmer: 1, + earningThreshold: { + join: minStake, + defaultUnstake: '0', + fastUnstake: '0' + }, + eraTime: 24, + era: 0, + unstakingPeriod: 1.2, + tvl: bnTaoIn.toString(), + totalApy: apr + } + }; + + callback(data); + } catch (err) { + taoStakingLogger.error('Error in getStakingPositionInterval', err); + } + } + }); + + return () => { + cancel = true; + aprSubject.complete(); + subscription.unsubscribe(); + clearInterval(interval); + }; + } + + /* Subscribe pool position */ + + protected parseNominatorMetadataBase (chainInfo: _ChainInfo, delegatorState: TaoStakingStakeOption[], minBond: string, applyRate = false): Omit { + const nominationList: NominationInfo[] = []; + let allActiveStake = BN_ZERO; + + for (const delegate of delegatorState) { + const stake = new BigN(delegate.amount); + const originActiveStake = applyRate ? stake.multipliedBy(delegate.rate || 1).toFixed(0) : stake.toFixed(0); + const bnActiveStake = new BN(originActiveStake); + + if (bnActiveStake.gt(BN_ZERO)) { + allActiveStake = allActiveStake.add(bnActiveStake); + + nominationList.push({ + status: EarningStatus.EARNING_REWARD, + chain: chainInfo.slug, + validatorAddress: delegate.owner, + activeStake: delegate.amount, + validatorMinStake: minBond, + validatorIdentity: delegate.identity, + ...(applyRate ? { originActiveStake } : {}) + }); + } + } + + const stakingStatus = getEarningStatusByNominations(allActiveStake, nominationList); + + return { + status: stakingStatus, + balanceToken: this.nativeToken.slug, + totalStake: allActiveStake.toString(), + activeStake: allActiveStake.toString(), + unstakeBalance: '0', + isBondedBefore: true, + nominations: nominationList, + unstakings: [] + } as unknown as YieldPositionInfo; + } + + async parseNominatorMetadata (chainInfo: _ChainInfo, delegatorState: TaoStakingStakeOption[]): Promise> { + const bnMinBond = await this.getMinBond(); + + return this.parseNominatorMetadataBase(chainInfo, delegatorState, bnMinBond.toString()); + } + + override async subscribePoolPosition (useAddresses: string[], rsCallback: (rs: YieldPositionInfo) => void): Promise { + let cancel = false; + const substrateApi = await this.substrateApi.isReady; + const defaultInfo = this.baseInfo; + const chainInfo = this.chainInfo; + const _delegateInfo = await this.bittensorCache.get(); + + const getPoolPosition = async () => { + const rawDelegateStateInfos = await Promise.all( + useAddresses.map(async (address) => (await substrateApi.api.call.stakeInfoRuntimeApi.getStakeInfoForColdkey(address)).toJSON()) + ); + + if (rawDelegateStateInfos && rawDelegateStateInfos.length > 0) { + rawDelegateStateInfos.forEach((rawDelegateStateInfo, i) => { + const owner = reformatAddress(useAddresses[i], 42); + const delegatorState: TaoStakingStakeOption[] = []; + let bnTotalBalance = BN_ZERO; + + const delegateStateInfo = rawDelegateStateInfo as unknown as TaoStakeInfo[]; + + const totalDelegate: Record = {}; + + for (const delegate of delegateStateInfo) { + const hotkey = delegate.hotkey; + const netuid = delegate.netuid; + const stake = new BigN(delegate.stake); + + if (netuid === 0) { + const taoStake = stake.toFixed(0); + + if (totalDelegate[hotkey]) { + totalDelegate[hotkey] = new BigN(totalDelegate[hotkey]).plus(taoStake).toFixed(); + } else { + totalDelegate[hotkey] = taoStake; + } + } + } + + for (const hotkey in totalDelegate) { + bnTotalBalance = bnTotalBalance.add(new BN(totalDelegate[hotkey])); + let identity = ''; + + if (_delegateInfo) { + const delegateInfo = _delegateInfo.data.find((info) => info.hotkey.ss58 === hotkey); + + identity = delegateInfo ? delegateInfo.name : ''; + } + + delegatorState.push({ + owner: hotkey, + amount: totalDelegate[hotkey], + identity: identity + }); + } + + if (delegateStateInfo && delegateStateInfo.length > 0) { + this.parseNominatorMetadata(chainInfo, delegatorState) + .then((nominatorMetadata) => { + rsCallback({ + ...defaultInfo, + ...nominatorMetadata, + address: owner, + type: this.type + }); + }) + .catch((error) => taoStakingLogger.error('Error fetching nominator metadata', error)); + } else { + rsCallback({ + ...defaultInfo, + type: this.type, + address: owner, + balanceToken: this.nativeToken.slug, + totalStake: '0', + activeStake: '0', + unstakeBalance: '0', + status: EarningStatus.NOT_STAKING, + isBondedBefore: false, + nominations: [], + unstakings: [] + }); + } + }); + } + }; + + const getStakingPositionInterval = async () => { + if (cancel) { + return; + } + + await getPoolPosition(); + }; + + getStakingPositionInterval().catch((error) => taoStakingLogger.error('Error in getStakingPositionInterval', error)); + + const intervalId = setInterval(() => { + getStakingPositionInterval().catch((error) => taoStakingLogger.error('Error in getStakingPositionInterval', error)); + }, BITTENSOR_REFRESH_STAKE_INFO); + + return () => { + cancel = true; + clearInterval(intervalId); + }; + } + + // Because not have subscan api + override async checkAccountHaveStake (useAddresses: string[]): Promise { + return Promise.resolve([]); + } + + /* Subscribe pool position */ + + /* Get pool targets */ + // eslint-disable-next-line @typescript-eslint/require-await + private async getDevnetPoolTargets (netuid?: number): Promise { + const testnetDelegate = (await this.substrateApi.api.call.delegateInfoRuntimeApi.getDelegates()).toJSON() as unknown as TestnetBittensorDelegateInfo[]; + const bnMinBond = await this.getMinBond(netuid); + + const filteredDelegates = testnetDelegate.filter((delegate) => { + return delegate.returnPer1000 !== 0; + }); + + return filteredDelegates.map((delegate) => ({ + address: delegate.delegateSs58, + totalStake: '0', + ownStake: '0', + otherStake: '0', + minBond: bnMinBond.toString(), + nominatorCount: delegate.nominators.length, + commission: delegate.take / 1000, + blocked: false, + isVerified: false, + chain: this.chain, + isCrowded: false + }) as unknown as ValidatorInfo); + } + + private async getMainnetPoolTargets (netuid: number): Promise { + const _topValidator = await this.bittensorCache.get(); + + const topValidator = _topValidator; + const bnMinBond = await this.getMinBond(); + const validatorList = topValidator.data; + + const aprResponse = await this.bittensorCache.fetchApr(netuid); + const aprMap: Record = {}; + + aprResponse.data.forEach((item) => { + aprMap[item.hotkey.ss58] = item.thirty_day_apy; + }); + + const results = await Promise.all( + validatorList.map((validator) => { + const address = validator.hotkey.ss58; + // With bittensor we use total weight, root weight and alpha staked insted of total stake, own stake and other stake + const bnTotalWeightStake = new BigN(validator.global_weighted_stake); + const bnRootWeightStake = new BigN(validator.weighted_root_stake); + const bnAlphaStake = new BigN(validator.global_alpha_stake_as_tao); + + const nominatorCount = validator.global_nominators; + const commission = validator.take; + const roundedCommission = (parseFloat(commission) * 100).toFixed(0); + + const apr = aprMap[address]; + const expectedReturn = apr ? new BigN(apr).multipliedBy(100).toFixed(2) : '0'; + + const name = validator.name || address; + + return { + address: address, + totalStake: bnTotalWeightStake.toString(), + ownStake: bnRootWeightStake.toString(), + otherStake: bnAlphaStake.toString(), + minBond: bnMinBond.toString(), + nominatorCount: nominatorCount, + commission: roundedCommission, + expectedReturn: expectedReturn, + blocked: false, + isVerified: false, + chain: this.chain, + isCrowded: false, + identity: name + } as unknown as ValidatorInfo; + }) + ); + + return results; + } + + async getPoolTargets (netuid?: number): Promise { + if (this.chain === 'bittensor') { + return this.getMainnetPoolTargets(netuid ?? 0); + } else { + return this.getDevnetPoolTargets(netuid); + } + } + + /* Get pool targets */ + + /* Join pool action */ + + override async createJoinExtrinsic ( + data: SubmitJoinNativeStaking, + positionInfo?: YieldPositionInfo, + bondDest = 'Staked' + ): Promise<[TransactionData, YieldTokenBaseInfo]> { + const { amount, selectedValidators: targetValidators, subnetData } = data; + + const chainApi = await this.substrateApi.isReady; + const binaryAmount = new BigN(amount); + const selectedValidatorInfo = targetValidators[0]; + const hotkey = selectedValidatorInfo.address; + + const netuid = subnetData?.netuid ?? 0; + const slippage = subnetData?.slippage ?? DEFAULT_BITTENSOR_SLIPPAGE; + + const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid)); + const limitPrice = alphaToTaoPrice + .multipliedBy(10 ** _getAssetDecimals(this.nativeToken)) + .multipliedBy(1 + slippage); + + const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed()); + + const extrinsic = chainApi.api.tx.subtensorModule.addStakeLimit( + hotkey, + netuid, + binaryAmount.toFixed(), + BNlimitPrice.toFixed(), + false + ); + + return [extrinsic, { slug: this.nativeToken.slug, amount: '0' }]; + } + + // Validate for case stake more + public override async validateYieldJoin (data: SubmitJoinNativeStaking, path: OptimalYieldPath): Promise { + const baseErrors = await super.validateYieldJoin(data, path); + + if (baseErrors.length > 0) { + return baseErrors; + } + + const { amount, subnetData } = data; + + const bnMinStake = await this.getMinBond(subnetData?.netuid); + + if (new BigN(amount).lt(bnMinStake)) { + return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.insufficientStakeToEarn', { replace: { bnMinStake: formatNumber(bnMinStake, _getAssetDecimals(this.nativeToken)), symbol: _getAssetSymbol(this.nativeToken) } }))]; + } + + return baseErrors; + } + + /* Join pool action */ + + /* Leave pool action */ + + override async handleYieldUnstake (amount: string, address: string, selectedTarget?: string, netuid = 0, slippage: number = DEFAULT_BITTENSOR_SLIPPAGE): Promise<[ExtrinsicType, TransactionData]> { + const apiPromise = await this.substrateApi.isReady; + + if (!selectedTarget) { + return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS)); + } + + const binaryAmount = new BigN(amount); + + const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid)); + const limitPrice = alphaToTaoPrice + .multipliedBy(10 ** _getAssetDecimals(this.nativeToken)) + .multipliedBy(1 - slippage); + + const BNlimitPrice = new BigN(limitPrice.integerValue(BigN.ROUND_CEIL).toFixed()); + + const extrinsic = apiPromise.api.tx.subtensorModule.removeStakeLimit( + selectedTarget, + netuid, + binaryAmount.toFixed(), + BNlimitPrice.toFixed(), + false + ); + + return [ExtrinsicType.STAKING_UNBOND, extrinsic]; + } + + public override async validateYieldLeave (amount: string, address: string, fastLeave: boolean, selectedTarget?: string, slug?: string, poolInfo?: YieldPoolInfo): Promise { + const baseErrors = await super.validateYieldLeave(amount, address, fastLeave, selectedTarget, slug); + + if (baseErrors.length > 0) { + return baseErrors; + } + + if (!poolInfo) { + return [new TransactionError(BasicTxErrorType.INVALID_PARAMS)]; + } + + const netuid = poolInfo.metadata.subnetData?.netuid; + const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid || 0)); + + const minDelegatorStake = await this.getMinBond(netuid); + + const minUnstake = minDelegatorStake.dividedBy(alphaToTaoPrice); + + if (new BigN(amount).lt(minUnstake)) { + return [new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.unstakeAmountTooLow', { replace: { bnMinUnstake: formatNumber(minUnstake, _getAssetDecimals(this.nativeToken)), symbol: poolInfo.metadata.subnetData?.subnetSymbol || _getAssetSymbol(this.nativeToken) } }))]; + } + + return baseErrors; + } + + /* Leave pool action */ + + /* Change validator */ + override async handleChangeEarningValidator (data: SubmitBittensorChangeValidatorStaking): Promise { + const chainApi = await this.substrateApi.isReady; + const { amount, maxAmount, metadata, originValidator, selectedValidators: targetValidators, subnetData } = data; + + if (!originValidator) { + return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS)); + } + + const netuid = subnetData?.netuid || 0; + const selectedValidatorInfo = targetValidators[0]; + const destValidator = selectedValidatorInfo.address; + + if (new BigN(amount).lte(0)) { + return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.amountMustBeGreaterThanZero'))); + } + + if (originValidator === destValidator) { + return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.fromValidatorSameAsTo'))); + } + + const alphaToTaoPrice = new BigN(await getAlphaToTaoRate(this.substrateApi, netuid)); + const bnMinStake = await this.getMinBond(netuid); + const minUnstake = bnMinStake.dividedBy(alphaToTaoPrice); + + const formattedMinUnstake = minUnstake.dividedBy(1000000).integerValue(BigN.ROUND_CEIL).dividedBy(1000); + + const bnMinMoveStake = formattedMinUnstake.multipliedBy(10 ** _getAssetDecimals(this.nativeToken)); + + if (new BigN(amount).lt(bnMinMoveStake)) { + return Promise.reject(new TransactionError(BasicTxErrorType.INVALID_PARAMS, t('bg.EARNING.services.service.earning.nativeStaking.tao.moveStakeAmountTooLow', { replace: { bnMinMoveStake: formattedMinUnstake.toString(), symbol: metadata?.subnetSymbol || '' } }))); + } + + // Avoid remaining amount too low -> can't do anything with that amount + if (!(maxAmount === amount) && new BigN(maxAmount).minus(new BigN(amount)).lt(bnMinMoveStake)) { + return Promise.reject(new TransactionError(StakingTxErrorType.REMAINING_AMOUNT_TOO_LOW, + t('bg.EARNING.services.service.earning.nativeStaking.tao.remainingStakeBelowMinimumWarning', { replace: { maxAmount: formatNumber(maxAmount, _getAssetDecimals(this.nativeToken)), subnetSymbol: metadata?.subnetSymbol || _getAssetSymbol(this.nativeToken) } }))); + } + + const extrinsic = chainApi.api.tx.subtensorModule.moveStake(originValidator, destValidator, netuid, netuid, amount); + + return extrinsic; + } +} diff --git a/packages/extension-base/src/services/earning-service/handlers/special.ts b/packages/extension-base/src/services/earning-service/handlers/special.ts index 37b15d8da45..11f82c88a4c 100644 --- a/packages/extension-base/src/services/earning-service/handlers/special.ts +++ b/packages/extension-base/src/services/earning-service/handlers/special.ts @@ -9,6 +9,7 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State' import { createXcmExtrinsicV2 } from '@subwallet/extension-base/services/balance-service/transfer/xcm'; import { estimateXcmFee } from '@subwallet/extension-base/services/balance-service/transfer/xcm/utils'; import { _getAssetDecimals, _getAssetExistentialDeposit, _getAssetName, _getAssetSymbol, _getChainNativeTokenSlug, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BaseYieldStepDetail, BasicTxErrorType, HandleYieldStepData, OptimalYieldPath, OptimalYieldPathParams, RequestCrossChainTransfer, RequestEarlyValidateYield, ResponseEarlyValidateYield, SpecialYieldPoolInfo, SpecialYieldPoolMetadata, SubmitChangeValidatorStaking, SubmitYieldJoinData, SubmitYieldStepData, TransactionData, UnstakingInfo, YieldPoolInfo, YieldPoolTarget, YieldPoolType, YieldProcessValidation, YieldStepBaseInfo, YieldStepType, YieldTokenBaseInfo, YieldValidationStatus } from '@subwallet/extension-base/types'; import { createPromiseHandler, formatNumber, PromiseHandler } from '@subwallet/extension-base/utils'; import { getId } from '@subwallet/extension-base/utils/getId'; @@ -19,6 +20,8 @@ import { BN, BN_TEN, BN_ZERO, noop } from '@polkadot/util'; import BasePoolHandler from './base'; +const specialEarningLogger = createLogger('SpecialEarning'); + export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHandler { protected abstract altInputAsset: string; protected abstract derivativeAssets: string[]; @@ -194,7 +197,7 @@ export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHand const getStatInterval = () => { if (!this.isActive) { - defaultCallback().catch(console.error); + defaultCallback().catch((error) => specialEarningLogger.error('Error in default callback', error)); } else { defaultCallback() .then(() => { @@ -203,7 +206,7 @@ export default abstract class BaseSpecialStakingPoolHandler extends BasePoolHand .then((rs) => { _callback(rs); }) - .catch(console.error); + .catch((error) => specialEarningLogger.error('Error in special earning handler', error)); } }; diff --git a/packages/extension-base/src/services/earning-service/service.ts b/packages/extension-base/src/services/earning-service/service.ts index b75e6f9cab1..b73d9a044c3 100644 --- a/packages/extension-base/src/services/earning-service/service.ts +++ b/packages/extension-base/src/services/earning-service/service.ts @@ -15,9 +15,12 @@ import DatabaseService from '@subwallet/extension-base/services/storage-service/ import { SWTransactionBase } from '@subwallet/extension-base/services/transaction-service/types'; import { BasicTxErrorType, EarningRewardHistoryItem, EarningRewardItem, EarningRewardJson, HandleYieldStepData, HandleYieldStepParams, OptimalYieldPath, OptimalYieldPathParams, RequestEarlyValidateYield, RequestEarningImpact, RequestStakeCancelWithdrawal, RequestStakeClaimReward, RequestYieldLeave, RequestYieldWithdrawal, ResponseEarlyValidateYield, SubmitChangeValidatorStaking, TransactionData, ValidateYieldProcessParams, ValidatorInfo, YieldPoolInfo, YieldPoolTarget, YieldPoolType, YieldPositionInfo } from '@subwallet/extension-base/types'; import { addLazy, createPromiseHandler, filterAddressByChainInfo, PromiseHandler, removeLazy } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { fetchStaticCache } from '@subwallet/extension-base/utils/fetchStaticCache'; import { BehaviorSubject, combineLatest } from 'rxjs'; +const earningServiceLogger = createLogger('EarningService'); + import { EarningImpactResult } from './handlers/native-staking/dtao'; import TanssiNativeStakingPoolHandler from './handlers/native-staking/tanssi'; import { AcalaLiquidStakingPoolHandler, AmplitudeNativeStakingPoolHandler, AstarNativeStakingPoolHandler, BasePoolHandler, BifrostLiquidStakingPoolHandler, BifrostMantaLiquidStakingPoolHandler, EnergyNativeStakingPoolHandler, InterlayLendingPoolHandler, NominationPoolHandler, ParallelLiquidStakingPoolHandler, ParaNativeStakingPoolHandler, RelayNativeStakingPoolHandler, StellaSwapLiquidStakingPoolHandler, SubnetTaoStakingPoolHandler, TaoNativeStakingPoolHandler } from './handlers'; @@ -296,7 +299,7 @@ export default class EarningService implements StoppableServiceInterface, Persis if (eventTypes.includes('account.updateCurrent') || eventTypes.includes('account.remove') || eventTypes.includes('chain.updateState') || delayReload) { if (delayReload) { this.delayReloadTimeout = setTimeout(() => { - this.reloadEarning().catch(console.error); // Timeout is removed inside reloadEarning > runUnsubscribePoolsPosition + this.reloadEarning().catch((error) => earningServiceLogger.error('Error reloading earning', error)); // Timeout is removed inside reloadEarning > runUnsubscribePoolsPosition }, 3000); } else { this.delayReloadTimeout && clearTimeout(this.delayReloadTimeout); @@ -304,7 +307,7 @@ export default class EarningService implements StoppableServiceInterface, Persis await this.reloadEarning(); } } - })().catch(console.error); + })().catch((error) => earningServiceLogger.error('Error in earning service operation', error)); }); } @@ -343,7 +346,7 @@ export default class EarningService implements StoppableServiceInterface, Persis // cache identities of validators in native staking if (this.useOnlineCacheOnly && !this.validatorInfoCachingInterval) { - this.runIntervalGetPoolTargets().catch(console.error); + this.runIntervalGetPoolTargets().catch((error) => earningServiceLogger.error('Error running interval get pool targets', error)); } // Update promise handler @@ -464,7 +467,7 @@ export default class EarningService implements StoppableServiceInterface, Persis unsub(); } }) - .catch(console.error); + .catch((error) => earningServiceLogger.error('Error in earning service', error)); } } @@ -524,7 +527,7 @@ export default class EarningService implements StoppableServiceInterface, Persis this.yieldPoolInfoSubject.next(yieldPoolInfo); // Persist data - this.dbService.updateYieldPoolsStore(queue).catch(console.warn); + this.dbService.updateYieldPoolsStore(queue).catch((error) => earningServiceLogger.warn('Error updating yield pools store', error)); }, 300, 900); } @@ -564,7 +567,7 @@ export default class EarningService implements StoppableServiceInterface, Persis const onlineData = await this.fetchingPoolsInfoOnline(); const interval = setInterval(() => { - this.fetchingPoolsInfoOnline().catch(console.error); + this.fetchingPoolsInfoOnline().catch((error) => earningServiceLogger.error('Error fetching pools info online', error)); }, CRON_REFRESH_CHAIN_STAKING_METADATA); // Fetching from chains @@ -576,7 +579,7 @@ export default class EarningService implements StoppableServiceInterface, Persis rs(); clearInterval(interval); }; - }).catch(console.error); + }).catch((error) => earningServiceLogger.error('Error in earning service operation', error)); } runUnsubscribePoolsInfo () { @@ -612,7 +615,7 @@ export default class EarningService implements StoppableServiceInterface, Persis unsubList.push(unsub); } }) - .catch(console.error); + .catch((error) => earningServiceLogger.error('Error in earning service', error)); } } @@ -709,7 +712,7 @@ export default class EarningService implements StoppableServiceInterface, Persis this.yieldPositionSubject.next(yieldPositionInfo); // Persist data - this.dbService.updateYieldPositions(queue).catch(console.warn); + this.dbService.updateYieldPositions(queue).catch((error) => earningServiceLogger.warn('Error updating yield positions', error)); }, 300, 900); } @@ -738,7 +741,7 @@ export default class EarningService implements StoppableServiceInterface, Persis this.updateYieldPosition(data); }).then((rs) => { this.yieldPositionUnsub = rs; - }).catch(console.error); + }).catch((error) => earningServiceLogger.error('Error in earning service operation', error)); } runUnsubscribePoolsPosition () { @@ -796,7 +799,7 @@ export default class EarningService implements StoppableServiceInterface, Persis unsubList.push(unsub); } }) - .catch(console.error); + .catch((error) => earningServiceLogger.error('Error in earning service', error)); } } @@ -832,12 +835,12 @@ export default class EarningService implements StoppableServiceInterface, Persis this.getPoolReward(addresses, (result: EarningRewardItem) => { this.updateEarningReward(result); - }).catch(console.error); + }).catch((error) => earningServiceLogger.error('Error in earning service operation', error)); this.earningsRewardInterval = setInterval(() => { this.getPoolReward(addresses, (result: EarningRewardItem) => { this.updateEarningReward(result); - }).catch(console.error); + }).catch((error) => earningServiceLogger.error('Error in earning service operation', error)); }, CRON_REFRESH_STAKING_REWARD_FAST_INTERVAL); } @@ -866,7 +869,7 @@ export default class EarningService implements StoppableServiceInterface, Persis unsubList.push(unsub); } }) - .catch(console.error); + .catch((error) => earningServiceLogger.error('Error in earning service', error)); } } @@ -942,7 +945,7 @@ export default class EarningService implements StoppableServiceInterface, Persis unsub = _unsub; } }) - .catch(console.error); + .catch((error) => earningServiceLogger.error('Error fetching earning reward history', error)); }; if (!cancel) { @@ -1009,7 +1012,7 @@ export default class EarningService implements StoppableServiceInterface, Persis return { ...newData }; } } catch (e) { - console.error(e); + earningServiceLogger.error('Error in earning service', e); } const prevValueCached = this.poolTargetsFetchingCached.getValue(); @@ -1024,7 +1027,7 @@ export default class EarningService implements StoppableServiceInterface, Persis try { poolInfosSubjectValue = await fetchPoolsData(); } catch (e) { - console.log('Error fetching pools data:', e); + earningServiceLogger.error('Error fetching pools data', e); } } @@ -1050,7 +1053,7 @@ export default class EarningService implements StoppableServiceInterface, Persis }); this.poolTargetsFetchingCached.next(poolTargetsFetchingCached); - }).catch(console.error); + }).catch((error) => earningServiceLogger.error('Error in earning service operation', error)); }; updatePoolTarget(); diff --git a/packages/extension-base/src/services/event-service/index.ts b/packages/extension-base/src/services/event-service/index.ts index b6d32c611fb..fb4b9c6bd41 100644 --- a/packages/extension-base/src/services/event-service/index.ts +++ b/packages/extension-base/src/services/event-service/index.ts @@ -2,10 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 // Stateless service handle runtime event on background +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EventItem, EventRegistry, EventType } from '@subwallet/extension-base/services/event-service/types'; import { TARGET_ENV } from '@subwallet/extension-base/utils'; import EventEmitter from 'eventemitter3'; +const eventServiceLogger = createLogger('EventService'); + const DEFAULT_LAZY_TIME = 300; const LONG_LAZY_TIME = 900; const LONG_LAZY_EVENTS: EventType[] = [ @@ -90,7 +93,7 @@ export class EventService extends EventEmitter { try { this.lazyEmitter.emit('lazy', this.pendingEvents, this.pendingEvents.map((e) => e.type)); } catch (e) { - console.error('Get error in some listener of lazy event', e); + eventServiceLogger.error('Get error in some listener of lazy event', e); } this.pendingEvents = []; @@ -110,7 +113,7 @@ export class EventService extends EventEmitter { } public override emit (eventType: T, ...args: EventEmitter.EventArgs): boolean { - console.debug('Emit event: ', eventType, ...args); + eventServiceLogger.debug('Emit event', eventType, ...args); this.pendingEvents.push({ type: eventType, data: args as EventRegistry[T] }); this.setLazyTimeout(eventType); diff --git a/packages/extension-base/src/services/fee-service/service.ts b/packages/extension-base/src/services/fee-service/service.ts index 6ac6609ce85..c2bf530d132 100644 --- a/packages/extension-base/src/services/fee-service/service.ts +++ b/packages/extension-base/src/services/fee-service/service.ts @@ -4,9 +4,12 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils'; import { calculateGasFeeParams } from '@subwallet/extension-base/services/fee-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EvmFeeInfo, FeeChainType, FeeInfo, FeeSubscription } from '@subwallet/extension-base/types'; import { BehaviorSubject } from 'rxjs'; +const feeServiceLogger = createLogger('FeeService'); + export default class FeeService { protected readonly state: KoniState; @@ -143,7 +146,7 @@ export default class FeeService { observer.next(info); }) .catch((e) => { - console.warn(`Cannot get fee param for ${chain}`, e); + feeServiceLogger.warn(`Cannot get fee param for ${chain}`, e); observer.next({ type: 'evm', gasPrice: '0', @@ -152,7 +155,7 @@ export default class FeeService { } as EvmFeeInfo); }); } else { - console.warn(`Cannot get fee param for ${chain}`, 'Cannot get api'); + feeServiceLogger.warn(`Cannot get fee param for ${chain}`, 'Cannot get api'); observer.next({ type: 'evm', @@ -168,7 +171,7 @@ export default class FeeService { .then((info) => { observer.next(info); }) - .catch(console.error); + .catch((error) => feeServiceLogger.error('Error in fee service operation', error)); } else { observer.next({ type, diff --git a/packages/extension-base/src/services/fee-service/utils/index.ts b/packages/extension-base/src/services/fee-service/utils/index.ts index 22f71cb65d0..8280bd0ff51 100644 --- a/packages/extension-base/src/services/fee-service/utils/index.ts +++ b/packages/extension-base/src/services/fee-service/utils/index.ts @@ -5,6 +5,7 @@ import { _ChainAsset } from '@subwallet/chain-list/types'; import { GAS_PRICE_RATIO, NETWORK_MULTI_GAS_FEE } from '@subwallet/extension-base/constants'; import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; import { estimateTokensForPool, getReserveForPool } from '@subwallet/extension-base/services/swap-service/handler/asset-hub/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EvmEIP1559FeeOption, EvmFeeInfo, EvmFeeInfoCache, InfuraFeeInfo, InfuraThresholdInfo } from '@subwallet/extension-base/types'; import { BN_WEI, BN_ZERO } from '@subwallet/extension-base/utils'; import BigN from 'bignumber.js'; @@ -13,6 +14,8 @@ import { ApiPromise } from '@polkadot/api'; import { gasStation, POLYGON_GAS_INDEXER } from '../../balance-service/transfer/xcm/polygonBridge'; +const feeServiceUtilsLogger = createLogger('FeeServiceUtils'); + const INFURA_API_KEY = process.env.INFURA_API_KEY || ''; const INFURA_API_KEY_SECRET = process.env.INFURA_API_KEY_SECRET || ''; const INFURA_AUTH = 'Basic ' + Buffer.from(INFURA_API_KEY + ':' + INFURA_API_KEY_SECRET).toString('base64'); @@ -79,7 +82,7 @@ export const fetchInfuraFeeData = async (chainId: number, infuraAuth?: string): return parseInfuraFee(feeInfo, thresholdInfo); } catch (e) { - console.warn(e); + feeServiceUtilsLogger.warn('Error in fee service utils', e); return null; } @@ -102,7 +105,7 @@ export const fetchSubWalletFeeData = async (chainId: number, networkKey: string) resolve(info); }) .catch((e) => { - console.warn(e); + feeServiceUtilsLogger.warn('Error in fee service utils', e); resolve(null); }); }); @@ -117,7 +120,7 @@ export const fetchOnlineFeeData = async (chainId: number, networkKey: string, us resolve(info); }) .catch((e) => { - console.warn(e); + feeServiceUtilsLogger.warn('Error in fee service utils', e); resolve(null); }); }); diff --git a/packages/extension-base/src/services/fee-service/utils/tokenPayFee.ts b/packages/extension-base/src/services/fee-service/utils/tokenPayFee.ts index 79e5058ea82..6738e36aab4 100644 --- a/packages/extension-base/src/services/fee-service/utils/tokenPayFee.ts +++ b/packages/extension-base/src/services/fee-service/utils/tokenPayFee.ts @@ -6,11 +6,14 @@ import { _SubstrateApi } from '@subwallet/extension-base/services/chain-service/ import { _getAssetDecimals, _getAssetPriceId, _getTokenOnChainAssetId } from '@subwallet/extension-base/services/chain-service/utils'; import { RequestAssetHubTokensCanPayFee, RequestHydrationTokensCanPayFee, TokenHasBalanceInfo } from '@subwallet/extension-base/services/fee-service/interfaces'; import { checkLiquidityForPool, estimateTokensForPool, getReserveForPool } from '@subwallet/extension-base/services/swap-service/handler/asset-hub/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk'; import BigN from 'bignumber.js'; import { SubmittableExtrinsic } from '@polkadot/api/promise/types'; +const tokenPayFeeLogger = createLogger('TokenPayFee'); + export async function getAssetHubTokensCanPayFee (request: RequestAssetHubTokensCanPayFee): Promise { const { chainService, feeAmount, nativeBalanceInfo, nativeTokenInfo, substrateApi, tokensHasBalanceInfoMap } = request; const tokensList: TokenHasBalanceInfo[] = [nativeBalanceInfo]; @@ -26,7 +29,7 @@ export async function getAssetHubTokensCanPayFee (request: RequestAssetHubTokens const token = chainService.getAssetBySlug(tokenSlug); if (!token) { - console.error(`[getAssetHubTokensCanPayFee] Token not found for slug: ${tokenSlug}`); + tokenPayFeeLogger.error(`[getAssetHubTokensCanPayFee] Token not found for slug: ${tokenSlug}`); } return token; @@ -71,7 +74,7 @@ export async function getAssetHubTokensCanPayFee (request: RequestAssetHubTokens } } } catch (e) { - console.error('error when fetching pool with token', tokenInfo.slug, e); + tokenPayFeeLogger.error('error when fetching pool with token', tokenInfo.slug, e); } })); @@ -100,7 +103,7 @@ export async function getHydrationTokensCanPayFee (request: RequestHydrationToke const token = chainService.getAssetBySlug(tokenSlug); if (!token) { - console.error(`[getHydrationTokensCanPayFee] Token not found for slug: ${tokenSlug}`); + tokenPayFeeLogger.error(`[getHydrationTokensCanPayFee] Token not found for slug: ${tokenSlug}`); } return token; @@ -201,7 +204,7 @@ export async function getHydrationRate (address: string, hdx: _ChainAsset, desTo quoteRate = quote.rate; } catch (error) { - console.error(`Failed to fetch swap quote: ${(error as Error).message}`); + tokenPayFeeLogger.error(`Failed to fetch swap quote: ${(error as Error).message}`); } if (quoteRate) { diff --git a/packages/extension-base/src/services/hiro-service/utils/index.ts b/packages/extension-base/src/services/hiro-service/utils/index.ts index 082218c411a..062125e3981 100644 --- a/packages/extension-base/src/services/hiro-service/utils/index.ts +++ b/packages/extension-base/src/services/hiro-service/utils/index.ts @@ -2,8 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 import { Brc20Metadata, InscriptionFetchedData } from '@subwallet/extension-base/services/chain-service/handler/bitcoin/strategy/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { HiroService } from '@subwallet/extension-base/services/hiro-service'; +const hiroServiceLogger = createLogger('HiroService'); + // todo: handle inscription testnet export async function getBrc20Metadata (isTestnet = false, ticker: string) { const hiroService = HiroService.getInstance(isTestnet); @@ -25,7 +28,7 @@ export async function getBrc20Metadata (isTestnet = false, ticker: string) { return defaultMetadata; } catch (error) { - console.log(`Error on request brc20 metadata with ticker ${ticker}`); + hiroServiceLogger.debug(`Error on request brc20 metadata with ticker ${ticker}`); return defaultMetadata; } @@ -37,7 +40,7 @@ export async function getInscriptionContent (isTestnet: boolean, inscriptionId: try { return await hiroService.getInscriptionContent(inscriptionId); } catch (error) { - console.log(`Error on request inscription ${inscriptionId} content`); + hiroServiceLogger.debug(`Error on request inscription ${inscriptionId} content`); return {}; } @@ -56,7 +59,7 @@ export async function getAddressInscriptions (address: string, isTestnet: boolea return response.results; } catch (error) { - console.error(`Failed to get ${address} inscriptions with offset ${offset} and limit ${limit}`, error); + hiroServiceLogger.error(`Failed to get ${address} inscriptions with offset ${offset} and limit ${limit}`, error); throw error; } } @@ -67,7 +70,7 @@ export function getPreviewUrl (inscriptionId: string) { try { return hiroService.getPreviewUrl(inscriptionId); } catch (error) { - console.error(`Failed to get inscription ${inscriptionId} preview url`, error); + hiroServiceLogger.error(`Failed to get inscription ${inscriptionId} preview url`, error); throw error; } } diff --git a/packages/extension-base/src/services/history-service/helpers/recoverHistoryStatus.ts b/packages/extension-base/src/services/history-service/helpers/recoverHistoryStatus.ts index d94900db829..895adba8bb6 100644 --- a/packages/extension-base/src/services/history-service/helpers/recoverHistoryStatus.ts +++ b/packages/extension-base/src/services/history-service/helpers/recoverHistoryStatus.ts @@ -4,12 +4,15 @@ import { TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes'; import { ChainService } from '@subwallet/extension-base/services/chain-service'; import { _EvmApi } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isSameAddress } from '@subwallet/extension-base/utils'; import { Vec } from '@polkadot/types'; import { EventRecord } from '@polkadot/types/interfaces'; import { isHex } from '@polkadot/util'; +const recoverHistoryStatusLogger = createLogger('RecoverHistoryStatus'); + export enum HistoryRecoverStatus { SUCCESS = 'SUCCESS', FAILED = 'FAILED', @@ -45,7 +48,7 @@ const substrateRecover = async (history: TransactionHistoryItem, chainService: C if (!blockHash) { if (nonce === undefined || startBlock === undefined) { - console.log(`Fail to find extrinsic for ${address} on ${chain}: With nonce ${nonce || 'undefined'} from block ${startBlock || 'undefined'}`); + recoverHistoryStatusLogger.debug(`Fail to find extrinsic for ${address} on ${chain}: With nonce ${nonce || 'undefined'} from block ${startBlock || 'undefined'}`); return { status: HistoryRecoverStatus.LACK_INFO }; } @@ -103,7 +106,7 @@ const substrateRecover = async (history: TransactionHistoryItem, chainService: C } if (index === undefined) { - console.log(`Fail to find extrinsic ${extrinsicHash} on ${chain}`); + recoverHistoryStatusLogger.debug(`Fail to find extrinsic ${extrinsicHash} on ${chain}`); return { status: HistoryRecoverStatus.FAIL_DETECT }; } @@ -125,12 +128,12 @@ const substrateRecover = async (history: TransactionHistoryItem, chainService: C return { status: HistoryRecoverStatus.FAIL_DETECT }; } else { - console.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`); + recoverHistoryStatusLogger.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`); return { status: HistoryRecoverStatus.API_INACTIVE }; } } catch (e) { - console.error(`Fail to update history ${chain}-${extrinsicHash}:`, (e as Error).message); + recoverHistoryStatusLogger.error(`Fail to update history ${chain}-${extrinsicHash}:`, (e as Error).message); return { status: HistoryRecoverStatus.UNKNOWN }; } @@ -174,7 +177,7 @@ const evmRecover = async (history: TransactionHistoryItem, chainService: ChainSe return { ...result, status: transactionReceipt.status ? HistoryRecoverStatus.SUCCESS : HistoryRecoverStatus.FAILED }; } else { if (nonce === undefined || startBlock === undefined) { - console.log(`Fail to find extrinsic for ${address} on ${chain}: With nonce ${nonce || 'undefined'} from block ${startBlock || 'undefined'}`); + recoverHistoryStatusLogger.debug(`Fail to find extrinsic for ${address} on ${chain}: With nonce ${nonce || 'undefined'} from block ${startBlock || 'undefined'}`); return { ...result, status: HistoryRecoverStatus.LACK_INFO }; } @@ -204,12 +207,12 @@ const evmRecover = async (history: TransactionHistoryItem, chainService: ChainSe return { status: HistoryRecoverStatus.FAIL_DETECT }; } else { - console.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`); + recoverHistoryStatusLogger.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`); return { status: HistoryRecoverStatus.API_INACTIVE }; } } catch (e) { - console.error(`Fail to update history ${chain}-${extrinsicHash}:`, (e as Error).message); + recoverHistoryStatusLogger.error(`Fail to update history ${chain}-${extrinsicHash}:`, (e as Error).message); return { status: HistoryRecoverStatus.UNKNOWN }; } @@ -265,12 +268,12 @@ const bitcoinRecover = async (history: TransactionHistoryItem, chainService: Cha return { status: HistoryRecoverStatus.FAIL_DETECT }; } else { - console.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`); + recoverHistoryStatusLogger.error(`Fail to update history ${chain}-${extrinsicHash}: Api not active`); return { status: HistoryRecoverStatus.API_INACTIVE }; } } catch (e) { - console.error(`Fail to update history ${chain}-${extrinsicHash}:`, (e as Error).message); + recoverHistoryStatusLogger.error(`Fail to update history ${chain}-${extrinsicHash}:`, (e as Error).message); return { status: HistoryRecoverStatus.UNKNOWN }; } @@ -295,7 +298,7 @@ export const historyRecover = async (history: TransactionHistoryItem, chainServi const checkFunction = recoverFunctions[chainType]; if (!checkFunction) { - console.warn(`Chain type ${chainType} is not supported for recoverHistory`); + recoverHistoryStatusLogger.warn(`Chain type ${chainType} is not supported for recoverHistory`); return { status: HistoryRecoverStatus.UNKNOWN }; } @@ -303,7 +306,7 @@ export const historyRecover = async (history: TransactionHistoryItem, chainServi try { return await checkFunction(history, chainService); } catch (error) { - console.error(`Failed to recover history for chain type ${chainType}:`, error); + recoverHistoryStatusLogger.error(`Failed to recover history for chain type ${chainType}:`, error); return { status: HistoryRecoverStatus.FAILED }; } diff --git a/packages/extension-base/src/services/history-service/index.ts b/packages/extension-base/src/services/history-service/index.ts index e248b258f58..4bfd29517c5 100644 --- a/packages/extension-base/src/services/history-service/index.ts +++ b/packages/extension-base/src/services/history-service/index.ts @@ -15,10 +15,13 @@ import { KeyringService } from '@subwallet/extension-base/services/keyring-servi import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService'; import { SubscanService } from '@subwallet/extension-base/services/subscan-service'; import { getAddressesByChainType } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { createPromiseHandler } from '@subwallet/extension-base/utils/promise'; import { keyring } from '@subwallet/ui-keyring'; import { BehaviorSubject } from 'rxjs'; +const historyServiceLogger = createLogger('HistoryService'); + function filterHistoryItemByAddressAndChain (chain: string, addresses: string[]) { return (item: TransactionHistoryItem) => { return item.chain === chain && addresses.includes(item.address); @@ -36,7 +39,7 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer private keyringService: KeyringService, private subscanService: SubscanService ) { - this.init().catch(console.error); + this.init().catch((error) => historyServiceLogger.error('Error initializing history service', error)); } private fetchPromise: Promise | null = null; @@ -123,7 +126,7 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer }); this.addHistoryItems(result).catch((e) => { - console.log('addHistoryItems in fetchAllPossibleExtrinsicItems error', e); + historyServiceLogger.error('addHistoryItems in fetchAllPossibleExtrinsicItems error', e); }); }).then((extrinsicItems) => { const excludeTransferExtrinsicHash: string[] = []; @@ -149,13 +152,13 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer }); this.addHistoryItems(result).catch((e) => { - console.log('addHistoryItems in fetchAllPossibleTransferItems-sent error', e); + historyServiceLogger.error('addHistoryItems in fetchAllPossibleTransferItems-sent error', e); }); }).catch((e) => { - console.log('fetchAllPossibleTransferItems-sent error', e); + historyServiceLogger.error('fetchAllPossibleTransferItems-sent error', e); }); }).catch((e) => { - console.log('fetchAllPossibleExtrinsicItems error', e); + historyServiceLogger.error('fetchAllPossibleExtrinsicItems error', e); }); this.subscanService.fetchAllPossibleTransferItems(groupId, chain, address, 'received').then((rsMap) => { @@ -173,10 +176,10 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer }); this.addHistoryItems(result).catch((e) => { - console.log('addHistoryItems in fetchAllPossibleTransferItems-receive error', e); + historyServiceLogger.error('addHistoryItems in fetchAllPossibleTransferItems-receive error', e); }); }).catch((e) => { - console.log('fetchAllPossibleTransferItems-receive error', e); + historyServiceLogger.error('fetchAllPossibleTransferItems-receive error', e); }); } @@ -232,7 +235,7 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer } } else if (_isChainBitcoinCompatible(chainInfo)) { this.fetchBitcoinTransactionHistory(chain, bitcoinAddresses).catch((e) => { - console.log('fetchBitcoinTransactionHistory Error', e); + historyServiceLogger.error('fetchBitcoinTransactionHistory Error', e); }); } @@ -306,7 +309,7 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer await this.recoverHistories(); this.recoverInterval = setInterval(() => { - this.recoverHistories().catch(console.error); + this.recoverHistories().catch((error) => historyServiceLogger.error('Error recovering histories', error)); }, CRON_RECOVER_HISTORY_INTERVAL); } @@ -352,11 +355,11 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer case HistoryRecoverStatus.FAILED: case HistoryRecoverStatus.SUCCESS: updateData.status = recoverResult.status === HistoryRecoverStatus.SUCCESS ? ExtrinsicStatus.SUCCESS : ExtrinsicStatus.FAIL; - this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData, true).catch(console.error); + this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData, true).catch((error) => historyServiceLogger.error('Error updating history by extrinsic hash', error)); delete this.#needRecoveryHistories[currentExtrinsicHash]; break; default: - this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData, true).catch(console.error); + this.updateHistoryByExtrinsicHash(currentExtrinsicHash, updateData, true).catch((error) => historyServiceLogger.error('Error updating history by extrinsic hash', error)); delete this.#needRecoveryHistories[currentExtrinsicHash]; } }); @@ -371,16 +374,16 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer async init (): Promise { this.status = ServiceStatus.INITIALIZING; await this.eventService.waitCryptoReady; - this.restoreProcessTransaction().catch(console.error); + this.restoreProcessTransaction().catch((error) => historyServiceLogger.error('Error restoring process transaction', error)); await this.loadData(); Promise.all([this.eventService.waitKeyringReady, this.eventService.waitChainReady]).then(() => { - this.getHistories().catch(console.log); - this.recoverProcessingHistory().catch(console.error); + this.getHistories().catch((error) => historyServiceLogger.error('Error getting histories', error)); + this.recoverProcessingHistory().catch((error) => historyServiceLogger.error('Error recovering processing history', error)); this.eventService.on('account.remove', (address) => { - this.removeHistoryByAddress(address).catch(console.error); + this.removeHistoryByAddress(address).catch((error) => historyServiceLogger.error('Error removing history by address', error)); }); - }).catch(console.error); + }).catch((error) => historyServiceLogger.error('Error in history service operation', error)); this.status = ServiceStatus.INITIALIZED; } @@ -419,10 +422,10 @@ export class HistoryService implements StoppableServiceInterface, PersistDataSer const recoverNumber = Object.keys(this.#needRecoveryHistories).length; if (recoverNumber > 0) { - console.log(`Recover ${recoverNumber} processing history`); + historyServiceLogger.info(`Recover ${recoverNumber} processing history`); } - this.startRecoverHistories().catch(console.error); + this.startRecoverHistories().catch((error) => historyServiceLogger.error('Error starting recover histories', error)); } async start (): Promise { diff --git a/packages/extension-base/src/services/history-service/subscan-history.ts b/packages/extension-base/src/services/history-service/subscan-history.ts index 1b5e885d7d8..3f92749a106 100644 --- a/packages/extension-base/src/services/history-service/subscan-history.ts +++ b/packages/extension-base/src/services/history-service/subscan-history.ts @@ -6,8 +6,11 @@ import { ChainType, ExtrinsicStatus, ExtrinsicType, TransactionDirection, Transa import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils'; import { getExtrinsicParserKey, subscanExtrinsicParserMap, supportedExtrinsicParser } from '@subwallet/extension-base/services/history-service/helpers/subscan-extrinsic-parser-helper'; import { ExtrinsicItem, TransferItem } from '@subwallet/extension-base/services/subscan-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isSameAddress } from '@subwallet/extension-base/utils'; +const subscanHistoryLogger = createLogger('SubscanHistory'); + export function parseSubscanExtrinsicData (address: string, extrinsicItem: ExtrinsicItem, chainInfo: _ChainInfo): TransactionHistoryItem | null { const extrinsicParserKey = getExtrinsicParserKey(extrinsicItem); @@ -54,7 +57,7 @@ export function parseSubscanExtrinsicData (address: string, extrinsicItem: Extri try { return subscanExtrinsicParserMap[extrinsicParserKey](initData); } catch (e) { - console.log('parseSubscanExtrinsicData error:', e, initData); + subscanHistoryLogger.error('parseSubscanExtrinsicData error:', e, initData); return null; } diff --git a/packages/extension-base/src/services/history-service/subsquid-multi-chain-history.ts b/packages/extension-base/src/services/history-service/subsquid-multi-chain-history.ts index b2c6d994f1c..04a42d36aff 100644 --- a/packages/extension-base/src/services/history-service/subsquid-multi-chain-history.ts +++ b/packages/extension-base/src/services/history-service/subsquid-multi-chain-history.ts @@ -4,11 +4,14 @@ import { ApolloClient, createHttpLink, gql, InMemoryCache } from '@apollo/client'; import { _ChainInfo } from '@subwallet/chain-list/types'; import { ChainType, ExtrinsicStatus, ExtrinsicType, TransactionDirection, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { MAX_FETCH_PAGE_PER_SESSION, MIN__NUM_HISTORY_PER_ACCOUNT } from '@subwallet/extension-base/services/history-service/constants'; import { isArray } from '@polkadot/util'; import { decodeAddress, encodeAddress, isEthereumAddress } from '@polkadot/util-crypto'; +const subsquidMultiChainHistoryLogger = createLogger('SubsquidMultiChainHistory'); + const MULTI_CHAIN_URL = 'https://squid.subsquid.io/multi-chain-tx/v/v1/graphql'; const MultiChainTxClient = new ApolloClient({ @@ -394,7 +397,7 @@ export async function fetchMultiChainHistories (addresses: string[], chainMap: R const chainInfo = chainMap[chainId]; if (chainInfo === undefined) { - console.debug(`Not found chain info for chain id: ${chainId}`); // TODO: resolve conflicting chainId + subsquidMultiChainHistoryLogger.debug(`Not found chain info for chain id: ${chainId}`); // TODO: resolve conflicting chainId return; } @@ -411,7 +414,7 @@ export async function fetchMultiChainHistories (addresses: string[], chainMap: R histories.push(transactionData); } catch (e) { - console.debug('Parse transaction data failed', address, e); + subsquidMultiChainHistoryLogger.debug('Parse transaction data failed', address, e); } }); }); diff --git a/packages/extension-base/src/services/inapp-notification-service/index.ts b/packages/extension-base/src/services/inapp-notification-service/index.ts index a95833a2795..1dfcdfe1f5b 100644 --- a/packages/extension-base/src/services/inapp-notification-service/index.ts +++ b/packages/extension-base/src/services/inapp-notification-service/index.ts @@ -18,9 +18,12 @@ import DatabaseService from '@subwallet/extension-base/services/storage-service/ import { getTokenPairFromStep } from '@subwallet/extension-base/services/swap-service/utils'; import { ProcessTransactionData, ProcessType, SummaryEarningProcessData, SwapBaseTxData, YieldPoolType } from '@subwallet/extension-base/types'; import { GetNotificationParams, RequestSwitchStatusParams } from '@subwallet/extension-base/types/notification'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { formatNumber, getAddressesByChainType, reformatAddress } from '@subwallet/extension-base/utils'; import { isSubstrateAddress } from '@subwallet/keyring'; +const inappNotificationServiceLogger = createLogger('InappNotificationService'); + export class InappNotificationService implements CronServiceInterface { status: ServiceStatus; private refeshAvailBridgeClaimTimeOut: NodeJS.Timeout | undefined; @@ -210,7 +213,7 @@ export class InappNotificationService implements CronServiceInterface { this.createAvailBridgeClaimNotification(); this.createPolygonClaimableTransactions().catch((err) => { - console.error('Error:', err); + inappNotificationServiceLogger.error('Error creating polygon claimable transactions', err); }); this.refeshAvailBridgeClaimTimeOut = setTimeout(this.cronCreateBridgeClaimNotification.bind(this), CRON_LISTEN_AVAIL_BRIDGE_CLAIM); @@ -261,21 +264,21 @@ export class InappNotificationService implements CronServiceInterface { substrateAddresses.forEach((address) => { fetchAllAvailBridgeClaimable(address, AvailBridgeSourceChain.ETHEREUM, true) .then(async (transactions) => await this.processWriteAvailBridgeClaim(address, transactions, chainAssetMap[ASSET_TYPE.TEST_SUBSTRATE])) - .catch(console.error); + .catch((error) => inappNotificationServiceLogger.error('Error fetching Avail bridge claimable', error)); fetchAllAvailBridgeClaimable(address, AvailBridgeSourceChain.ETHEREUM, false) .then(async (transactions) => await this.processWriteAvailBridgeClaim(address, transactions, chainAssetMap[ASSET_TYPE.MAIN_SUBSTRATE])) - .catch(console.error); + .catch((error) => inappNotificationServiceLogger.error('Error fetching Avail bridge claimable', error)); }); evmAddresses.forEach((address) => { fetchAllAvailBridgeClaimable(address, AvailBridgeSourceChain.AVAIL, true) .then(async (transactions) => await this.processWriteAvailBridgeClaim(address, transactions, chainAssetMap[ASSET_TYPE.TEST_EVM])) - .catch(console.error); + .catch((error) => inappNotificationServiceLogger.error('Error fetching Avail bridge claimable', error)); fetchAllAvailBridgeClaimable(address, AvailBridgeSourceChain.AVAIL, false) .then(async (transactions) => await this.processWriteAvailBridgeClaim(address, transactions, chainAssetMap[ASSET_TYPE.MAIN_EVM])) - .catch(console.error); + .catch((error) => inappNotificationServiceLogger.error('Error fetching Avail bridge claimable', error)); }); } @@ -494,7 +497,7 @@ export class InappNotificationService implements CronServiceInterface { async startCron (): Promise { this.cleanUpOldNotifications() - .catch(console.error); + .catch((error) => inappNotificationServiceLogger.error('Error cleaning up old notifications', error)); this.cronCreateBridgeClaimNotification(); return Promise.resolve(); @@ -521,7 +524,7 @@ export class InappNotificationService implements CronServiceInterface { } removeAccountNotifications (proxyId: string) { - this.dbService.removeAccountNotifications(proxyId).catch(console.error); + this.dbService.removeAccountNotifications(proxyId).catch((error) => inappNotificationServiceLogger.error('Error removing account notifications', error)); } migrateNotificationProxyId (proxyIds: string[], newProxyId: string, newName: string) { diff --git a/packages/extension-base/src/services/inapp-notification-service/utils/avail.ts b/packages/extension-base/src/services/inapp-notification-service/utils/avail.ts index 1c04b9a67ef..89ef5172774 100644 --- a/packages/extension-base/src/services/inapp-notification-service/utils/avail.ts +++ b/packages/extension-base/src/services/inapp-notification-service/utils/avail.ts @@ -1,8 +1,11 @@ // Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BridgeTransactionStatus } from '../interfaces'; +const availBridgeUtilsLogger = createLogger('AvailBridgeUtils'); + /* Description */ export function getAvailBridgeClaimDescription (amount: string, symbol: string) { return `${amount} ${symbol} ready to claim from ${symbol} cross-chain transfer. Click to claim now!`; @@ -96,14 +99,14 @@ export async function fetchAvailBridgeTransactions (userAddress: string, sourceC ); if (!rawResponse.ok) { - console.error('Error fetching claimable bridge transactions'); + availBridgeUtilsLogger.error('Error fetching claimable bridge transactions'); return undefined; } return await rawResponse.json() as AvailBridgeTransactionsResponse; } catch (e) { - console.error(e); + availBridgeUtilsLogger.error('Error fetching Avail bridge transactions', e); return undefined; } diff --git a/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts b/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts index d904789d65a..1f0ebb579d5 100644 --- a/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts +++ b/packages/extension-base/src/services/inapp-notification-service/utils/polygon.ts @@ -1,8 +1,11 @@ // Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BridgeTransactionStatus } from '../interfaces'; +const polygonBridgeUtilsLogger = createLogger('PolygonBridgeUtils'); + export const POLYGON_BRIDGE_INDEXER = { MAINNET: 'https://api-gateway.polygon.technology/api/v3/transactions/mainnet', TESTNET: 'https://api-gateway.polygon.technology/api/v3/transactions/testnet' @@ -111,14 +114,14 @@ export async function fetchPolygonBridgeTransactions (userAddress: string, isTes ); if (!rawResponse.ok) { - console.error('Error fetching claimable bridge transactions'); + polygonBridgeUtilsLogger.error('Error fetching claimable bridge transactions'); return undefined; } return await rawResponse.json() as PolygonTransactionResponse; } catch (e) { - console.error(e); + polygonBridgeUtilsLogger.error('Error fetching Polygon bridge transactions', e); return undefined; } diff --git a/packages/extension-base/src/services/keyring-service/context/handlers/Derive.ts b/packages/extension-base/src/services/keyring-service/context/handlers/Derive.ts index 10045b143da..9b06b239df1 100644 --- a/packages/extension-base/src/services/keyring-service/context/handlers/Derive.ts +++ b/packages/extension-base/src/services/keyring-service/context/handlers/Derive.ts @@ -3,6 +3,7 @@ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; import { AccountJson, AccountProxyData, CommonAccountErrorType, CreateDeriveAccountInfo, DeriveAccountInfo, DeriveErrorType, NextDerivePair, RequestDeriveCreateMultiple, RequestDeriveCreateV3, RequestDeriveValidateV2, RequestGetDeriveAccounts, RequestGetDeriveSuggestion, ResponseDeriveValidateV2, ResponseGetDeriveAccounts, ResponseGetDeriveSuggestion, SWCommonAccountError, SWDeriveError } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { createAccountProxyId, derivePair, findSoloNextDerive, findUnifiedNextDerive, getSoloDerivationInfo, parseUnifiedSuriToDerivationPath, validateDerivationPath } from '@subwallet/extension-base/utils'; import { BitcoinKeypairTypes, EthereumKeypairTypes, KeypairType, KeyringPair, KeyringPair$Meta, SubstrateKeypairTypes } from '@subwallet/keyring/types'; import { keyring } from '@subwallet/ui-keyring'; @@ -12,6 +13,8 @@ import { assert } from '@polkadot/util'; import { AccountBaseHandler } from './Base'; +const accountDeriveHandlerLogger = createLogger('AccountDeriveHandler'); + const validDeriveKeypairTypes: KeypairType[] = [...SubstrateKeypairTypes, ...EthereumKeypairTypes, 'ton', 'cardano', ...BitcoinKeypairTypes]; /** @@ -81,7 +84,7 @@ export class AccountDeriveHandler extends AccountBaseHandler { this.state._addAddressToAuthList(address, isAllowed); result.push(childPair); } catch (e) { - console.log(e); + accountDeriveHandlerLogger.warn('Error creating derived account', e); } } diff --git a/packages/extension-base/src/services/keyring-service/context/handlers/Json.ts b/packages/extension-base/src/services/keyring-service/context/handlers/Json.ts index f01fdefd12f..71eb849424c 100644 --- a/packages/extension-base/src/services/keyring-service/context/handlers/Json.ts +++ b/packages/extension-base/src/services/keyring-service/context/handlers/Json.ts @@ -3,6 +3,7 @@ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; import { AccountProxyExtra, AccountProxyStoreData, AccountProxyType, KeyringPairs$JsonV2, ModifyPairStoreData, RequestAccountBatchExportV2, RequestBatchJsonGetAccountInfo, RequestBatchRestoreV2, RequestJsonGetAccountInfo, RequestJsonRestoreV2, ResponseAccountBatchExportV2, ResponseBatchJsonGetAccountInfo, ResponseJsonGetAccountInfo } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { combineAccountsWithKeyPair, convertAccountProxyType, createPromiseHandler, transformAccount } from '@subwallet/extension-base/utils'; import { generateRandomString } from '@subwallet/extension-base/utils/getId'; import { createPair } from '@subwallet/keyring'; @@ -16,6 +17,8 @@ import { EncryptedJson, Prefix } from '@polkadot/util-crypto/types'; import { AccountBaseHandler } from './Base'; +const accountJsonHandlerLogger = createLogger('AccountJsonHandler'); + /** * @class AccountJsonHandler * @extends AccountBaseHandler @@ -48,7 +51,7 @@ export class AccountJsonHandler extends AccountBaseHandler { return true; } catch (e) { - console.error(e); + accountJsonHandlerLogger.error('Error validating password', e); return false; } @@ -85,7 +88,7 @@ export class AccountJsonHandler extends AccountBaseHandler { accountProxy: proxy }; } catch (e) { - console.error(e); + accountJsonHandlerLogger.error('Error parsing single JSON account info', e); throw new Error((e as Error).message); } } else { @@ -154,7 +157,7 @@ export class AccountJsonHandler extends AccountBaseHandler { try { rs.push(keyring.createFromJson(pair)); } catch (e) { - console.error(e); + accountJsonHandlerLogger.error('Error creating pair from JSON', e); } return rs; @@ -187,7 +190,7 @@ export class AccountJsonHandler extends AccountBaseHandler { accountProxies: result }; } catch (e) { - console.error(e); + accountJsonHandlerLogger.error('Error parsing multi JSON account info', e); throw new Error((e as Error).message); } } else { @@ -213,7 +216,7 @@ export class AccountJsonHandler extends AccountBaseHandler { rs.push(pair); } catch (e) { - console.error(e); + accountJsonHandlerLogger.error('Error creating pair from JSON', e); } return rs; @@ -317,7 +320,7 @@ export class AccountJsonHandler extends AccountBaseHandler { rs.push(address); } } catch (error) { - console.log(error); + accountJsonHandlerLogger.warn('Error getting pair during batch restore', error); } return rs; diff --git a/packages/extension-base/src/services/keyring-service/context/handlers/Migration.ts b/packages/extension-base/src/services/keyring-service/context/handlers/Migration.ts index 05795c25bc7..f58a890bbf0 100644 --- a/packages/extension-base/src/services/keyring-service/context/handlers/Migration.ts +++ b/packages/extension-base/src/services/keyring-service/context/handlers/Migration.ts @@ -3,11 +3,14 @@ import { RequestMigrateSoloAccount, RequestMigrateUnifiedAndFetchEligibleSoloAccounts, RequestPingSession, ResponseMigrateSoloAccount, ResponseMigrateUnifiedAndFetchEligibleSoloAccounts, SoloAccountToBeMigrated } from '@subwallet/extension-base/background/KoniTypes'; import { AccountBaseHandler } from '@subwallet/extension-base/services/keyring-service/context/handlers/Base'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { AccountChainType, AccountProxy, SUPPORTED_ACCOUNT_CHAIN_TYPES } from '@subwallet/extension-base/types'; import { createAccountProxyId, getDefaultKeypairTypeFromAccountChainType, getSuri } from '@subwallet/extension-base/utils'; import { generateRandomString } from '@subwallet/extension-base/utils/getId'; import { keyring } from '@subwallet/ui-keyring'; +const accountMigrationHandlerLogger = createLogger('AccountMigrationHandler'); + import { keyExtractSuri } from '@polkadot/util-crypto'; export const SESSION_TIMEOUT = 10000; @@ -132,7 +135,7 @@ export class AccountMigrationHandler extends AccountBaseHandler { unifiedAccountIds.push(unifiedAccount.id); } } catch (error) { - console.error('Migration unified account failed with error:', error); + accountMigrationHandlerLogger.error('Migration unified account failed with error', error); } finally { keyring.lockAll(false); this.parentService.updateKeyringState(); @@ -256,7 +259,7 @@ export class AccountMigrationHandler extends AccountBaseHandler { this.state.saveCurrentAccountProxyId(upcomingProxyId); } } catch (error) { - console.error('Migration solo account failed with error', error); + accountMigrationHandlerLogger.error('Migration solo account failed with error', error); } finally { keyring.lockAll(false); this.parentService.updateKeyringState(); diff --git a/packages/extension-base/src/services/keyring-service/context/handlers/Modify.ts b/packages/extension-base/src/services/keyring-service/context/handlers/Modify.ts index 8332b0ba0c1..fa2f39ac87e 100644 --- a/packages/extension-base/src/services/keyring-service/context/handlers/Modify.ts +++ b/packages/extension-base/src/services/keyring-service/context/handlers/Modify.ts @@ -4,6 +4,7 @@ import { RequestChangeMasterPassword, RequestMigratePassword, ResponseChangeMasterPassword, ResponseMigratePassword } from '@subwallet/extension-base/background/KoniTypes'; import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; import { AccountChainType, CommonAccountErrorType, RequestAccountProxyEdit, RequestAccountProxyForget, RequestChangeTonWalletContractVersion, RequestGetAllTonWalletContractVersion, ResponseGetAllTonWalletContractVersion, SWCommonAccountError } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { KeyringPair$Meta, TonKeypairTypes, TonWalletContractVersion } from '@subwallet/keyring/types'; import { keyring } from '@subwallet/ui-keyring'; import { t } from 'i18next'; @@ -12,6 +13,8 @@ import { assert } from '@polkadot/util'; import { AccountBaseHandler } from './Base'; +const accountModifyHandlerLogger = createLogger('AccountModifyHandler'); + /** * @class AccountModifyHandler * @extends AccountBaseHandler @@ -47,7 +50,7 @@ export class AccountModifyHandler extends AccountBaseHandler { keyring.changeMasterPassword(newPassword, oldPassword); } catch (e) { - console.error(e); + accountModifyHandlerLogger.error('Error changing master password', e); return { errors: [t((e as Error).message)], @@ -73,7 +76,7 @@ export class AccountModifyHandler extends AccountBaseHandler { callback(); } catch (e) { - console.error(e); + accountModifyHandlerLogger.error('Error migrating master password', e); return { errors: [(e as Error).message], diff --git a/packages/extension-base/src/services/keyring-service/context/handlers/Secret.ts b/packages/extension-base/src/services/keyring-service/context/handlers/Secret.ts index f80b091d34d..654a7697fd9 100644 --- a/packages/extension-base/src/services/keyring-service/context/handlers/Secret.ts +++ b/packages/extension-base/src/services/keyring-service/context/handlers/Secret.ts @@ -3,6 +3,7 @@ import { AccountExternalError, AccountExternalErrorCode, RequestAccountCreateExternalV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey } from '@subwallet/extension-base/background/KoniTypes'; import { AccountChainType, CommonAccountErrorType, RequestCheckPublicAndSecretKey, RequestPrivateKeyValidateV2, ResponseCheckPublicAndSecretKey, ResponsePrivateKeyValidateV2, SWCommonAccountError } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { getKeypairTypeByAddress } from '@subwallet/keyring'; import { decodePair } from '@subwallet/keyring/pair/decode'; import { BitcoinKeypairTypes, CardanoKeypairTypes, KeypairType, KeyringPair, KeyringPair$Meta, TonKeypairTypes } from '@subwallet/keyring/types'; @@ -14,6 +15,8 @@ import { base64Decode, keyExtractSuri } from '@polkadot/util-crypto'; import { AccountBaseHandler } from './Base'; +const accountSecretHandlerLogger = createLogger('AccountSecretHandler'); + /** * @class AccountSecretHandler * @extends AccountBaseHandler @@ -248,7 +251,7 @@ export class AccountSecretHandler extends AccountBaseHandler { }; } } catch (e) { - console.error(e); + accountSecretHandlerLogger.error('Error checking public and secret key', e); return { address: '', diff --git a/packages/extension-base/src/services/keyring-service/context/state.ts b/packages/extension-base/src/services/keyring-service/context/state.ts index a11fdb2b8fa..af3b86fed31 100644 --- a/packages/extension-base/src/services/keyring-service/context/state.ts +++ b/packages/extension-base/src/services/keyring-service/context/state.ts @@ -6,6 +6,7 @@ import { ALL_ACCOUNT_KEY, UPGRADE_DUPLICATE_ACCOUNT_NAME } from '@subwallet/exte import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { AccountProxyStoreSubject, CurrentAccountStoreSubject, ModifyPairStoreSubject } from '@subwallet/extension-base/services/keyring-service/context/stores'; import { AuthUrls } from '@subwallet/extension-base/services/request-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { SWStorage } from '@subwallet/extension-base/storage'; import { AccountRefStore } from '@subwallet/extension-base/stores'; import { AccountMetadataData, AccountProxy, AccountProxyData, AccountProxyMap, AccountProxyStoreData, AccountProxyType, CurrentAccountInfo, ModifyPairStoreData } from '@subwallet/extension-base/types'; @@ -16,6 +17,8 @@ import { keyring } from '@subwallet/ui-keyring'; import { SubjectInfo } from '@subwallet/ui-keyring/observable/types'; import { BehaviorSubject, combineLatest, filter, first } from 'rxjs'; +const accountStateLogger = createLogger('AccountState'); + interface ExistsAccount { address: string; name: string; @@ -55,9 +58,9 @@ export class AccountState { this._modifyPair.init(); // Load account proxies this._accountProxy.init(); - this.subscribeAccounts().catch(console.error); + this.subscribeAccounts().catch((error) => accountStateLogger.error('Error subscribing accounts', error)); }) - .catch(console.error); + .catch((error) => accountStateLogger.error('Error initializing account state', error)); } private async subscribeAccounts () { @@ -120,7 +123,7 @@ export class AccountState { const accountNameDuplicates = this.getDuplicateAccountNames(transformedAccounts); if (accountNameDuplicates.length > 0) { - SWStorage.instance.setItem(UPGRADE_DUPLICATE_ACCOUNT_NAME, 'true').catch(console.error); + SWStorage.instance.setItem(UPGRADE_DUPLICATE_ACCOUNT_NAME, 'true').catch((error) => accountStateLogger.error('Error setting upgrade duplicate account name', error)); for (const accountProxy of transformedAccounts) { if (accountNameDuplicates.includes(accountProxy.name)) { @@ -706,11 +709,11 @@ export class AccountState { } public enableChain (slug: string) { - this.koniState.enableChain(slug, true).catch(console.error); + this.koniState.enableChain(slug, true).catch((error) => accountStateLogger.error('Error enabling chain', error)); } public enableChainWithPriorityAssets (slug: string) { - this.koniState.enableChainWithPriorityAssets(slug, true).catch(console.error); + this.koniState.enableChainWithPriorityAssets(slug, true).catch((error) => accountStateLogger.error('Error enabling chain with priority assets', error)); } /* Others */ diff --git a/packages/extension-base/src/services/keyring-service/index.ts b/packages/extension-base/src/services/keyring-service/index.ts index 9309d33998d..6a41d1a2636 100644 --- a/packages/extension-base/src/services/keyring-service/index.ts +++ b/packages/extension-base/src/services/keyring-service/index.ts @@ -3,11 +3,14 @@ import { KeyringState } from '@subwallet/extension-base/background/KoniTypes'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { keyring } from '@subwallet/ui-keyring'; import { BehaviorSubject } from 'rxjs'; import { AccountContext } from './context/account-context'; +const keyringServiceLogger = createLogger('KeyringService'); + export class KeyringService { private readonly stateSubject = new BehaviorSubject({ isReady: false, @@ -44,7 +47,7 @@ export class KeyringService { this.state.eventService.emit('keyring.ready', true); this.state.eventService.emit('account.ready', true); }) - .catch(console.error); + .catch((error) => keyringServiceLogger.error('Error waiting for crypto ready', error)); } this.stateSubject.next({ diff --git a/packages/extension-base/src/services/migration-service/Base.ts b/packages/extension-base/src/services/migration-service/Base.ts index 15b7d995d8b..43b71e3ee63 100644 --- a/packages/extension-base/src/services/migration-service/Base.ts +++ b/packages/extension-base/src/services/migration-service/Base.ts @@ -16,6 +16,6 @@ export default class BaseMigrationJob { } public run (): Promise { - return Promise.resolve(console.warn('Need to override function run from base.')); + return Promise.resolve(this.logger.warn('Need to override function run from base.')); } } diff --git a/packages/extension-base/src/services/migration-service/scripts/DeleteChain.ts b/packages/extension-base/src/services/migration-service/scripts/DeleteChain.ts index 78e6522303d..d1b171029f8 100644 --- a/packages/extension-base/src/services/migration-service/scripts/DeleteChain.ts +++ b/packages/extension-base/src/services/migration-service/scripts/DeleteChain.ts @@ -10,6 +10,6 @@ export default class DeleteChain extends BaseMigrationJob { this.state.forceRemoveChain(chain); }); - console.log('done job'); + this.logger.log('done job'); } } diff --git a/packages/extension-base/src/services/migration-service/scripts/DeleteChainStaking.ts b/packages/extension-base/src/services/migration-service/scripts/DeleteChainStaking.ts index 1238883560b..e760db3c014 100644 --- a/packages/extension-base/src/services/migration-service/scripts/DeleteChainStaking.ts +++ b/packages/extension-base/src/services/migration-service/scripts/DeleteChainStaking.ts @@ -8,7 +8,7 @@ export default class DeleteChainStaking extends BaseMigrationJob { try { await this.state.dbService.stores.yieldPoolInfo.table.where({ slug: 'CAPS___native_staking___ternoa_alphanet' }).delete(); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData.ts b/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData.ts index 03f79f25141..8dcc324fd9a 100644 --- a/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData.ts +++ b/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData.ts @@ -8,7 +8,7 @@ export default class DeleteEarningData extends BaseMigrationJob { try { await this.state.dbService.deleteYieldPoolInfo(['KILT___native_staking___kilt', 'PILT___native_staking___kilt_peregrine']); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251010.ts b/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251010.ts index c8d7e5880af..1d27ed14bbc 100644 --- a/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251010.ts +++ b/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251010.ts @@ -8,7 +8,7 @@ export default class DeleteEarningData20251010 extends BaseMigrationJob { try { await this.state.dbService.deleteYieldPoolInfo(['KSM___native_staking___kusama', 'KSM___nomination_pool___kusama']); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251105.ts b/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251105.ts index d5658f22dce..d950d00afd9 100644 --- a/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251105.ts +++ b/packages/extension-base/src/services/migration-service/scripts/DeleteEarningData20251105.ts @@ -8,7 +8,7 @@ export default class DeleteEarningData20251105 extends BaseMigrationJob { try { await this.state.dbService.deleteYieldPoolInfo(['DOT___native_staking___polkadot', 'DOT___nomination_pool___polkadot']); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/DisableZeroBalanceTokens.ts b/packages/extension-base/src/services/migration-service/scripts/DisableZeroBalanceTokens.ts index b7394506e0d..20567862d6c 100644 --- a/packages/extension-base/src/services/migration-service/scripts/DisableZeroBalanceTokens.ts +++ b/packages/extension-base/src/services/migration-service/scripts/DisableZeroBalanceTokens.ts @@ -60,7 +60,7 @@ export default class DisableZeroBalanceTokens extends BaseMigrationJob { state.chainService.setAssetSettings(updatedSettings); } catch (error) { - console.error(error); + this.logger.error(error); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/EnableEarningChains.ts b/packages/extension-base/src/services/migration-service/scripts/EnableEarningChains.ts index a7d49c5a2c8..5fd6c9cb20c 100644 --- a/packages/extension-base/src/services/migration-service/scripts/EnableEarningChains.ts +++ b/packages/extension-base/src/services/migration-service/scripts/EnableEarningChains.ts @@ -8,7 +8,7 @@ export default class EnableEarningChains extends BaseMigrationJob { try { await this.state.chainService.enableChains(['moonbeam', 'acala', 'bifrost_dot', 'interlay', 'parallel']); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateAuthUrls.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateAuthUrls.ts index 25ace3c2f8e..06175f8a83e 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateAuthUrls.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateAuthUrls.ts @@ -28,7 +28,7 @@ export default class MigrateSettings extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateAutoLock.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateAutoLock.ts index d2574ee306d..fd14082a451 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateAutoLock.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateAutoLock.ts @@ -18,7 +18,7 @@ export default class MigrateAutoLock extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateChainPatrol.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateChainPatrol.ts index 9b4b4d183ec..ee6fcee6ff0 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateChainPatrol.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateChainPatrol.ts @@ -18,7 +18,7 @@ export default class MigrateChainPatrol extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateImportedToken.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateImportedToken.ts index fe4505525ba..85e80490dd1 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateImportedToken.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateImportedToken.ts @@ -18,6 +18,7 @@ export default class MigrateImportedToken extends BaseMigrationJob { const state = this.state; return new Promise((resolve, reject) => { + const self = this; chrome.storage.local.get('EvmToken', function (items) { if (items && items.EvmToken) { const tokenMap = items.EvmToken as Record; @@ -42,7 +43,7 @@ export default class MigrateImportedToken extends BaseMigrationJob { icon: '' }); } catch (e) { - console.log(e); + self.logger.warn('Error migrating imported token', e); } }); }); diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateNewUnifiedAccount.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateNewUnifiedAccount.ts index 5e7a1777428..195c348e594 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateNewUnifiedAccount.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateNewUnifiedAccount.ts @@ -17,7 +17,7 @@ export default class MigrateNewUnifiedAccount extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateSettings.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateSettings.ts index b4a9c736d2f..bb3821a10e9 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateSettings.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateSettings.ts @@ -21,7 +21,7 @@ export default class MigrateSettings extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/MigrateWalletReference.ts b/packages/extension-base/src/services/migration-service/scripts/MigrateWalletReference.ts index f0aff318bdf..0732340d34d 100644 --- a/packages/extension-base/src/services/migration-service/scripts/MigrateWalletReference.ts +++ b/packages/extension-base/src/services/migration-service/scripts/MigrateWalletReference.ts @@ -20,7 +20,7 @@ export default class MigrateWalletReference extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/AutoEnableSomeTokens.ts b/packages/extension-base/src/services/migration-service/scripts/databases/AutoEnableSomeTokens.ts index d440ccec83c..ddd6d47a5ce 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/AutoEnableSomeTokens.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/AutoEnableSomeTokens.ts @@ -17,7 +17,7 @@ export default class AutoEnableSomeTokens extends BaseMigrationJob { await this.state.chainService.updateAssetSetting(slug, { visible: true }, true); } } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting.ts b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting.ts index 39b344adc69..7ad9de05a50 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting.ts @@ -28,7 +28,7 @@ export default class MigrateAssetSetting extends BaseMigrationJob { ...migratedAssetSetting }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251027.ts b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251027.ts index 6ff6dccead9..b7637b938e2 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251027.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251027.ts @@ -28,7 +28,7 @@ export default class MigrateAssetSetting20251027 extends BaseMigrationJob { ...migratedAssetSetting }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251107.ts b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251107.ts index 2af09b84ef5..3cc71492c78 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251107.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateAssetSetting20251107.ts @@ -28,7 +28,7 @@ export default class MigrateAssetSetting20251107 extends BaseMigrationJob { ...migratedAssetSetting }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningHistory.ts b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningHistory.ts index 5727adca2d5..c2f4b0c93e1 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningHistory.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningHistory.ts @@ -8,7 +8,7 @@ export default class MigrateEarningHistory extends BaseMigrationJob { try { await this.state.dbService.removeOldEarningData(); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningVersion.ts b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningVersion.ts index 9ec5aaa39eb..14d34818a58 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningVersion.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/MigrateEarningVersion.ts @@ -8,7 +8,7 @@ export default class MigrateEarningVersion extends BaseMigrationJob { try { await this.state.dbService.removeOldEarningData(); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/databases/ReloadMetadata.ts b/packages/extension-base/src/services/migration-service/scripts/databases/ReloadMetadata.ts index 5307b426b7d..d1dfbebcbf4 100644 --- a/packages/extension-base/src/services/migration-service/scripts/databases/ReloadMetadata.ts +++ b/packages/extension-base/src/services/migration-service/scripts/databases/ReloadMetadata.ts @@ -22,7 +22,7 @@ export default class ReloadMetadata extends BaseMigrationJob { this.state.chainService.disableChain(chain); setTimeout(() => { - this.state.chainService.enableChain(chain).catch(console.error); + this.state.chainService.enableChain(chain).catch((error) => this.logger.error('Error enabling chain', error)); }, 500); } } diff --git a/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccount.ts b/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccount.ts index f6531fdceff..8cf6e4d8232 100644 --- a/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccount.ts +++ b/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccount.ts @@ -31,7 +31,7 @@ export default class MigrateLedgerAccount extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccountV2.ts b/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccountV2.ts index 1480385acf8..f4fbf912519 100644 --- a/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccountV2.ts +++ b/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateLedgerAccountV2.ts @@ -43,7 +43,7 @@ export default class MigrateLedgerAccountV2 extends BaseMigrationJob { }); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/keyring/MigratePairData.ts b/packages/extension-base/src/services/migration-service/scripts/keyring/MigratePairData.ts index 78eb6c03185..09652b74f94 100644 --- a/packages/extension-base/src/services/migration-service/scripts/keyring/MigratePairData.ts +++ b/packages/extension-base/src/services/migration-service/scripts/keyring/MigratePairData.ts @@ -10,13 +10,13 @@ export default class MigratePairData extends BaseMigrationJob { try { this.state.keyringService.context.updateMetadataForPair(); } catch (e) { - console.error(e); + this.logger.error(e); } resolve(); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateRemoveGenesisHash.ts b/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateRemoveGenesisHash.ts index 5753866a13f..08cbc01bb6d 100644 --- a/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateRemoveGenesisHash.ts +++ b/packages/extension-base/src/services/migration-service/scripts/keyring/MigrateRemoveGenesisHash.ts @@ -10,13 +10,13 @@ export default class MigrateRemoveGenesisHash extends BaseMigrationJob { try { this.state.keyringService.context.removeNoneHardwareGenesisHash(); } catch (e) { - console.error(e); + this.logger.error(e); } resolve(); }); } catch (e) { - console.error(e); + this.logger.error(e); } } } diff --git a/packages/extension-base/src/services/mkt-campaign-service/index.ts b/packages/extension-base/src/services/mkt-campaign-service/index.ts index 544b44c1748..ba76d0a2160 100644 --- a/packages/extension-base/src/services/mkt-campaign-service/index.ts +++ b/packages/extension-base/src/services/mkt-campaign-service/index.ts @@ -4,11 +4,14 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _getAssetDecimals, _getChainNativeTokenBasicInfo } from '@subwallet/extension-base/services/chain-service/utils'; import { AppBannerData, AppBasicInfoData, AppCommonData, AppConfirmationData, AppPopupData, ConditionBalanceType, ConditionCrowdloanType, ConditionEarningType, ConditionHasMoneyType, ConditionNftType, ConditionType, MktCampaignCondition, MktCampaignConditionTypeValue } from '@subwallet/extension-base/services/mkt-campaign-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { fetchStaticData, TARGET_ENV, wait } from '@subwallet/extension-base/utils'; import { keyring } from '@subwallet/ui-keyring'; import BigN from 'bignumber.js'; import { BehaviorSubject } from 'rxjs'; +const mktCampaignServiceLogger = createLogger('MktCampaignService'); + export default class MktCampaignService { readonly #state: KoniState; @@ -23,30 +26,30 @@ export default class MktCampaignService { this.appConfirmationSubject.next([]); this.fetchPopupData().catch((e) => { - console.error('Error on fetch popup', e); + mktCampaignServiceLogger.error('Error on fetch popup', e); }); this.fetchBannerData().catch((e) => { - console.error('Error on fetch banner', e); + mktCampaignServiceLogger.error('Error on fetch banner', e); }); this.fetchConfirmationData().catch((e) => { - console.error('Error on fetch confirmation', e); + mktCampaignServiceLogger.error('Error on fetch confirmation', e); }); } fetchMktCampaignData (timeout = 10000) { wait(timeout) .finally(() => { - this.fetchPopupData().catch(console.error); - this.fetchBannerData().catch(console.error); - this.fetchConfirmationData().catch(console.error); + this.fetchPopupData().catch((error) => mktCampaignServiceLogger.error('Error fetching popup data', error)); + this.fetchBannerData().catch((error) => mktCampaignServiceLogger.error('Error fetching banner data', error)); + this.fetchConfirmationData().catch((error) => mktCampaignServiceLogger.error('Error fetching confirmation data', error)); }); } public init () { this.fetchMktCampaignData(); - console.log('Mkt campaign service ready'); + mktCampaignServiceLogger.info('Mkt campaign service ready'); } public async fetchPopupData () { diff --git a/packages/extension-base/src/services/nft-service/index.ts b/packages/extension-base/src/services/nft-service/index.ts index e7699fe513b..1fb3a33e649 100644 --- a/packages/extension-base/src/services/nft-service/index.ts +++ b/packages/extension-base/src/services/nft-service/index.ts @@ -5,12 +5,15 @@ import { _AssetType } from '@subwallet/chain-list/types'; import { NftCollection, NftFullListRequest, NftItem } from '@subwallet/extension-base/background/KoniTypes'; import KoniState from '@subwallet/extension-base/koni/background/handlers/State'; import { _getEvmChainId } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { baseParseIPFSUrl } from '@subwallet/extension-base/utils'; import { getKeypairTypeByAddress } from '@subwallet/keyring'; import { EthereumKeypairTypes } from '@subwallet/keyring/types'; import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk'; import { BlockscoutNftInstanceRaw } from '@subwallet-monorepos/subwallet-services-sdk/services/blockscout/types'; +const nftServiceLogger = createLogger('NftService'); + /** * NFT detection service * Responsible for managing NFT detection jobs per address @@ -137,7 +140,7 @@ export default class NftService { if (typeValid) { if (this.inProgress.has(address)) { - console.log(`[NftService] ${address} already running`); + nftServiceLogger.debug(`${address} already running`); continue; } @@ -148,7 +151,7 @@ export default class NftService { const nftDetectionApi = subwalletApiSdk.nftDetectionApi; if (!nftDetectionApi?.getEvmNftCollectionsByAddress) { - console.warn('[NftService] NftDetectionApi not available'); + nftServiceLogger.warn('NftDetectionApi not available'); continue; } @@ -181,7 +184,7 @@ export default class NftService { await this.state.handleDetectedNftCollections(allCollections); await this.state.handleDetectedNfts(address, allItems); } catch (err) { - console.warn(`[NftService] detect error for ${address}`, err); + nftServiceLogger.warn(`detect error for ${address}`, err); } finally { this.inProgress.delete(address); } @@ -194,7 +197,7 @@ export default class NftService { const chainId = _getEvmChainId(chainInfo); if (!contractAddress || !owners || !chainId) { - console.warn('[NftService] missing params for getFullNftInstancesByCollection'); + nftServiceLogger.warn('missing params for getFullNftInstancesByCollection'); return false; } @@ -203,7 +206,7 @@ export default class NftService { const nftDetectionApi = subwalletApiSdk.nftDetectionApi; if (!nftDetectionApi?.getAllNftInstances) { - console.warn('[NftService] getAllNftInstances not available'); + nftServiceLogger.warn('getAllNftInstances not available'); return false; } @@ -222,24 +225,24 @@ export default class NftService { continue; } - console.log('FOR TESTER (before)', instances); + nftServiceLogger.debug('FOR TESTER (before)', instances); const nftList = instances.map((inst) => mapSdkToNftItem(inst, chainInfo.slug, contractAddress, eachOwner) ).filter((i): i is NftItem => Boolean(i)); - console.log('FOR TESTER (after)', nftList); + nftServiceLogger.debug('FOR TESTER (after)', nftList); await this.state.handleDetectedNfts(eachOwner, nftList); } catch (innerErr) { - console.warn(`[NftService] getAllNftInstances failed for ${eachOwner}`, innerErr); + nftServiceLogger.warn(`getAllNftInstances failed for ${eachOwner}`, innerErr); } } return true; } catch (err) { - console.error( - `[NftDetectionService] getFullNftInstancesByCollection error for ${contractAddress}`, + nftServiceLogger.error( + `getFullNftInstancesByCollection error for ${contractAddress}`, err ); diff --git a/packages/extension-base/src/services/notification-service/NotificationService.ts b/packages/extension-base/src/services/notification-service/NotificationService.ts index bb781791f1f..bd7debbe1d7 100644 --- a/packages/extension-base/src/services/notification-service/NotificationService.ts +++ b/packages/extension-base/src/services/notification-service/NotificationService.ts @@ -2,9 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 import { Notification, NotificationButton, NotificationParams } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isFirefox } from '@subwallet/extension-base/utils'; import { BehaviorSubject } from 'rxjs'; +const notificationServiceLogger = createLogger('NotificationService'); + export default class NotificationService { private notificationSubject = new BehaviorSubject([]); @@ -52,7 +55,7 @@ export default class NotificationService { if (onClick) { onClick(); } else { - chrome.tabs.create({ url: link }).catch(console.error); + chrome.tabs.create({ url: link }).catch((error) => notificationServiceLogger.error('Error creating notification tab', error)); } } }); diff --git a/packages/extension-base/src/services/price-service/coingecko.ts b/packages/extension-base/src/services/price-service/coingecko.ts index 3d934e9cb70..86f4f58eb37 100644 --- a/packages/extension-base/src/services/price-service/coingecko.ts +++ b/packages/extension-base/src/services/price-service/coingecko.ts @@ -3,11 +3,14 @@ import { CurrencyJson, CurrencyType, ExchangeRateJSON, HistoryTokenPriceJSON, PriceChartTimeframe, PriceJson } from '@subwallet/extension-base/background/KoniTypes'; import { isProductionMode } from '@subwallet/extension-base/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData'; import subwalletApiSdk from '@subwallet-monorepos/subwallet-services-sdk'; import { isArray } from '@polkadot/util'; +const priceServiceLogger = createLogger('PriceService'); + interface GeckoItem { id: string, name: string, @@ -95,7 +98,7 @@ const fetchDerivativeTokenSlugs = async () => { return new Set(apiSlugs.length > 0 ? apiSlugs : DERIVATIVE_TOKEN_SLUG_LIST); } catch (error) { - console.error('Error fetching derivative token slugs from API:', error); + priceServiceLogger.error('Error fetching derivative token slugs from API:', error); return new Set(DERIVATIVE_TOKEN_SLUG_LIST); } @@ -123,11 +126,11 @@ export const getPriceMap = async (priceIds: Set, currency: CurrencyType } }); } else { - console.warn('Invalid data from derivative API:', generateDerivativePriceRaw); + priceServiceLogger.warn('Invalid data from derivative API:', generateDerivativePriceRaw); derivativeApiError = true; } } catch (error) { - console.error('Error fetching derivative API:', error); + priceServiceLogger.error('Error fetching derivative API:', error); derivativeApiError = true; } } @@ -207,7 +210,7 @@ export const getHistoryPrice = async (priceId: string, type: PriceChartTimeframe return response; } } catch (e) { - console.error('Error fetching price history:', e); + priceServiceLogger.error('Error fetching price history:', e); } return { history: [] }; diff --git a/packages/extension-base/src/services/price-service/index.ts b/packages/extension-base/src/services/price-service/index.ts index 2fefe2f8cd0..f53366b99be 100644 --- a/packages/extension-base/src/services/price-service/index.ts +++ b/packages/extension-base/src/services/price-service/index.ts @@ -13,8 +13,10 @@ import { CurrentCurrencyStore } from '@subwallet/extension-base/stores'; import { getTokenPriceHistoryId, TIME_INTERVAL, wait } from '@subwallet/extension-base/utils'; import { createPromiseHandler } from '@subwallet/extension-base/utils/promise'; import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BehaviorSubject, combineLatest, distinctUntilChanged, map, Subject } from 'rxjs'; +const priceServiceLogger = createLogger('PriceService'); const DEFAULT_CURRENCY: CurrencyType = 'USD'; const DEFAULT_PRICE_SUBJECT: PriceJson = { currency: DEFAULT_CURRENCY, @@ -58,12 +60,12 @@ export class PriceService implements StoppableServiceInterface, PersistDataServi SWStorage.instance.getItem(CURRENCY) .then((currency) => { this.setCurrentCurrency(currency as CurrencyType || currentCurrency || DEFAULT_CURRENCY); - }).catch(console.error); + }).catch((error) => priceServiceLogger.error('Error getting currency', error)); }; this.init().then( () => this.getCurrentCurrency(updateCurrency) - ).catch(console.error); + ).catch((error) => priceServiceLogger.error('Error initializing price service', error)); } private async getTokenPrice (priceIds: Set, currency?: CurrencyType, resolve?: (rs: boolean) => void, reject?: (e: boolean) => void) { @@ -115,7 +117,7 @@ export class PriceService implements StoppableServiceInterface, PersistDataServi this.priceSubject.next(newPriceMap); } } catch (e) { - console.error(e); + priceServiceLogger.error('Error in price service', e); } finally { this.refreshPromise = null; } @@ -203,7 +205,7 @@ export class PriceService implements StoppableServiceInterface, PersistDataServi this.refreshPriceMapByAction(); }) .catch((e) => { - console.error(e); + priceServiceLogger.error('Error in price service', e); }); this.refreshTimeout = setTimeout(this.refreshPriceData.bind(this), CRON_REFRESH_PRICE_INTERVAL); @@ -309,7 +311,7 @@ export class PriceService implements StoppableServiceInterface, PersistDataServi if (data) { this.priceSubject.next(data); } - }).catch(console.error); + }).catch((error) => priceServiceLogger.error('Error calculating price map', error)); }); this.status = ServiceStatus.INITIALIZED; @@ -334,7 +336,7 @@ export class PriceService implements StoppableServiceInterface, PersistDataServi } async persistData (): Promise { - await this.dbService.updatePriceStore(this.priceSubject.value).catch(console.error); + await this.dbService.updatePriceStore(this.priceSubject.value).catch((error) => priceServiceLogger.error('Error updating price store', error)); } startPromiseHandler = createPromiseHandler(); diff --git a/packages/extension-base/src/services/request-service/handler/AuthRequestHandler.ts b/packages/extension-base/src/services/request-service/handler/AuthRequestHandler.ts index 1162a325365..fc010bc179f 100644 --- a/packages/extension-base/src/services/request-service/handler/AuthRequestHandler.ts +++ b/packages/extension-base/src/services/request-service/handler/AuthRequestHandler.ts @@ -11,6 +11,7 @@ import { KeyringService } from '@subwallet/extension-base/services/keyring-servi import RequestService from '@subwallet/extension-base/services/request-service'; import { DAPP_CONNECT_BOTH_TYPE_ACCOUNT_URL, PREDEFINED_CHAIN_DAPP_CHAIN_MAP, WEB_APP_URL } from '@subwallet/extension-base/services/request-service/constants'; import { AuthUrlInfoNeedMigration, AuthUrls } from '@subwallet/extension-base/services/request-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import AuthorizeStore from '@subwallet/extension-base/stores/Authorize'; import { createPromiseHandler, getDomainFromUrl, PromiseHandler, stripUrl } from '@subwallet/extension-base/utils'; import { getId } from '@subwallet/extension-base/utils/getId'; @@ -20,6 +21,8 @@ import { BehaviorSubject } from 'rxjs'; import { isEthereumAddress } from '@polkadot/util-crypto'; +const authRequestHandlerLogger = createLogger('AuthRequestHandler'); + const AUTH_URLS_KEY = 'authUrls'; export default class AuthRequestHandler { @@ -36,8 +39,8 @@ export default class AuthRequestHandler { this.#requestService = requestService; this.#chainService = chainService; this.migrateAuthUrlInfoToUnified().then(() => { - this.init().catch(console.error); - }).catch(console.error); + this.init().catch((error) => authRequestHandlerLogger.error('Error initializing auth request handler', error)); + }).catch((error) => authRequestHandlerLogger.error('Error migrating auth URL info', error)); } private async init () { diff --git a/packages/extension-base/src/services/request-service/handler/BitcoinRequestHandler.ts b/packages/extension-base/src/services/request-service/handler/BitcoinRequestHandler.ts index 087325ab9cd..0c6d0eeb360 100644 --- a/packages/extension-base/src/services/request-service/handler/BitcoinRequestHandler.ts +++ b/packages/extension-base/src/services/request-service/handler/BitcoinRequestHandler.ts @@ -10,6 +10,8 @@ import RequestService from '@subwallet/extension-base/services/request-service'; import TransactionService from '@subwallet/extension-base/services/transaction-service'; import { TransactionEventResponse } from '@subwallet/extension-base/services/transaction-service/types'; import { BasicTxErrorType } from '@subwallet/extension-base/types'; + +const bitcoinRequestHandlerLogger = createLogger('BitcoinRequestHandler'); import { createPromiseHandler } from '@subwallet/extension-base/utils'; import { isInternalRequest } from '@subwallet/extension-base/utils/request'; import keyring from '@subwallet/ui-keyring'; @@ -432,7 +434,7 @@ export default class BitcoinRequestHandler { const { resolver } = this.confirmationsPromiseMap[id]; if (!resolver || !confirmation) { - console.error('Not found confirmation', type, id); + bitcoinRequestHandlerLogger.error('Not found confirmation', type, id); } else { resolver.reject(new Error('Reset wallet')); } diff --git a/packages/extension-base/src/services/request-service/handler/CardanoRequestHandler.ts b/packages/extension-base/src/services/request-service/handler/CardanoRequestHandler.ts index cdf53409fec..9a4c9349df8 100644 --- a/packages/extension-base/src/services/request-service/handler/CardanoRequestHandler.ts +++ b/packages/extension-base/src/services/request-service/handler/CardanoRequestHandler.ts @@ -5,17 +5,16 @@ import { FixedTransaction, TransactionWitnessSet, Vkeywitnesses } from '@emurgo/ import { ConfirmationDefinitionsCardano, ConfirmationsQueueCardano, ConfirmationsQueueItemOptions, ConfirmationTypeCardano, RequestConfirmationCompleteCardano, ResponseCardanoSignData } from '@subwallet/extension-base/background/KoniTypes'; import { ConfirmationRequestBase, Resolver } from '@subwallet/extension-base/background/types'; import RequestService from '@subwallet/extension-base/services/request-service'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isInternalRequest } from '@subwallet/extension-base/utils/request'; import { keyring } from '@subwallet/ui-keyring'; import { t } from 'i18next'; import { BehaviorSubject } from 'rxjs'; -import { logger as createLogger } from '@polkadot/util/logger'; -import { Logger } from '@polkadot/util/types'; +const cardanoRequestHandlerLogger = createLogger('CardanoRequestHandler'); export default class CardanoRequestHandler { readonly #requestService: RequestService; - readonly #logger: Logger; private readonly confirmationsQueueSubjectCardano = new BehaviorSubject({ cardanoSignatureRequest: {}, @@ -28,7 +27,6 @@ export default class CardanoRequestHandler { constructor (requestService: RequestService) { this.#requestService = requestService; - this.#logger = createLogger('CardanoRequestHandler'); } public get numCardanoRequests (): number { @@ -115,7 +113,7 @@ export default class CardanoRequestHandler { const confirmation = confirmations[type][id]; if (!resolver || !confirmation) { - this.#logger.error(t('bg.DAPP.services.service.request.CardanoHandler.unableToProceed'), type, id); + cardanoRequestHandlerLogger.error(t('bg.DAPP.services.service.request.CardanoHandler.unableToProceed'), type, id); throw new Error(t('bg.DAPP.services.service.request.CardanoHandler.unableToProceed')); } @@ -222,7 +220,7 @@ export default class CardanoRequestHandler { const { resolver } = this.confirmationsPromiseMap[id]; if (!resolver || !confirmation) { - console.error('Not found confirmation', type, id); + cardanoRequestHandlerLogger.error('Not found confirmation', type, id); } else { resolver.reject(new Error('Reset wallet')); } diff --git a/packages/extension-base/src/services/request-service/handler/EvmRequestHandler.ts b/packages/extension-base/src/services/request-service/handler/EvmRequestHandler.ts index cf863aca2a3..f80ee734bc8 100644 --- a/packages/extension-base/src/services/request-service/handler/EvmRequestHandler.ts +++ b/packages/extension-base/src/services/request-service/handler/EvmRequestHandler.ts @@ -10,6 +10,8 @@ import RequestService from '@subwallet/extension-base/services/request-service'; import { anyNumberToBN } from '@subwallet/extension-base/utils/eth'; import { isInternalRequest } from '@subwallet/extension-base/utils/request'; import keyring from '@subwallet/ui-keyring'; + +const evmRequestHandlerLogger = createLogger('EvmRequestHandler'); import BigN from 'bignumber.js'; import BN from 'bn.js'; import { toBuffer } from 'ethereumjs-util'; @@ -305,7 +307,7 @@ export default class EvmRequestHandler { const { resolver } = this.confirmationsPromiseMap[id]; if (!resolver || !confirmation) { - console.error('Not found confirmation', type, id); + evmRequestHandlerLogger.error('Not found confirmation', type, id); } else { resolver.reject(new Error('Reset wallet')); } diff --git a/packages/extension-base/src/services/request-service/handler/TonRequestHandler.ts b/packages/extension-base/src/services/request-service/handler/TonRequestHandler.ts index 81cd419d251..14406cc2720 100644 --- a/packages/extension-base/src/services/request-service/handler/TonRequestHandler.ts +++ b/packages/extension-base/src/services/request-service/handler/TonRequestHandler.ts @@ -11,6 +11,8 @@ import { t } from 'i18next'; import { BehaviorSubject } from 'rxjs'; import { u8aToHex } from '@polkadot/util'; + +const tonRequestHandlerLogger = createLogger('TonRequestHandler'); import { logger as createLogger } from '@polkadot/util/logger'; import { Logger } from '@polkadot/util/types'; @@ -186,7 +188,7 @@ export default class TonRequestHandler { const { resolver } = this.confirmationsPromiseMap[id]; if (!resolver || !confirmation) { - console.error('Not found confirmation', type, id); + tonRequestHandlerLogger.error('Not found confirmation', type, id); } else { resolver.reject(new Error('Reset wallet')); } diff --git a/packages/extension-base/src/services/request-service/index.ts b/packages/extension-base/src/services/request-service/index.ts index 13f4029edee..af8333800e3 100644 --- a/packages/extension-base/src/services/request-service/index.ts +++ b/packages/extension-base/src/services/request-service/index.ts @@ -11,10 +11,13 @@ import SettingService from '@subwallet/extension-base/services/setting-service/S import TransactionService from '@subwallet/extension-base/services/transaction-service'; import { WalletConnectNotSupportRequest, WalletConnectSessionRequest } from '@subwallet/extension-base/services/wallet-connect-service/types'; import { MetadataDef } from '@subwallet/extension-inject/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BehaviorSubject } from 'rxjs'; import { SignerPayloadJSON } from '@polkadot/types/types/extrinsic'; +const requestServiceLogger = createLogger('RequestService'); + import TonRequestHandler from './handler/TonRequestHandler'; import { AuthRequestHandler, ConnectWCRequestHandler, EvmRequestHandler, MetadataRequestHandler, NotSupportWCRequestHandler, PopupHandler, SubstrateRequestHandler } from './handler'; import { AuthUrls, MetaRequest } from './types'; @@ -83,7 +86,7 @@ export default class RequestService { const popupList = this.#popupHandler.popup; if (popupList && popupList.length > 0) { - chrome.windows.update(popupList[0], { focused: true })?.catch(console.error); + chrome.windows.update(popupList[0], { focused: true })?.catch((error) => requestServiceLogger.error('Error updating popup window', error)); } else { this.#popupHandler.popupOpen(); } diff --git a/packages/extension-base/src/services/setting-service/SettingService.ts b/packages/extension-base/src/services/setting-service/SettingService.ts index d4e640bdac3..af6419b7076 100644 --- a/packages/extension-base/src/services/setting-service/SettingService.ts +++ b/packages/extension-base/src/services/setting-service/SettingService.ts @@ -8,11 +8,14 @@ import { SWStorage } from '@subwallet/extension-base/storage'; import ChainlistStore, { ChainlistConfig } from '@subwallet/extension-base/stores/ChainlistStore'; import PassPhishingStore from '@subwallet/extension-base/stores/PassPhishingStore'; import SettingsStore from '@subwallet/extension-base/stores/Settings'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Subject } from 'rxjs'; import i18n from './i18n/i18n'; import { DEFAULT_SETTING } from './constants'; +const settingServiceLogger = createLogger('SettingService'); + export default class SettingService { private readonly settingsStore = new SettingsStore(); private readonly passPhishingStore = new PassPhishingStore(); @@ -20,7 +23,7 @@ export default class SettingService { private readonly environmentStore = new EnvironmentStoreSubject(); constructor () { - this.initSetting().catch(console.error); + this.initSetting().catch((error) => settingServiceLogger.error('Error initializing settings', error)); } private async initSetting () { @@ -29,7 +32,7 @@ export default class SettingService { const updateLanguage = ({ language }: UiSettings) => { if (language !== old) { old = language; - i18n.changeLanguage(language).catch(console.error); + i18n.changeLanguage(language).catch((error) => settingServiceLogger.error('Error changing language', error)); } }; diff --git a/packages/extension-base/src/services/setting-service/i18n/i18n.ts b/packages/extension-base/src/services/setting-service/i18n/i18n.ts index e40e8ffc340..e5a13d7f2d8 100644 --- a/packages/extension-base/src/services/setting-service/i18n/i18n.ts +++ b/packages/extension-base/src/services/setting-service/i18n/i18n.ts @@ -1,10 +1,13 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import i18next from 'i18next'; import Backend from './Backend'; +const i18nLogger = createLogger('I18n'); + i18next.use(Backend).init({ backend: {}, debug: false, @@ -18,6 +21,6 @@ i18next.use(Backend).init({ nsSeparator: false, returnEmptyString: false, returnNull: false -}).catch(console.error); +}).catch((error) => i18nLogger.error('Error initializing i18n', error)); export default i18next; diff --git a/packages/extension-base/src/services/storage-service/db-stores/Crowdloan.ts b/packages/extension-base/src/services/storage-service/db-stores/Crowdloan.ts index 7a45a515502..d9572a85949 100644 --- a/packages/extension-base/src/services/storage-service/db-stores/Crowdloan.ts +++ b/packages/extension-base/src/services/storage-service/db-stores/Crowdloan.ts @@ -1,10 +1,13 @@ // Copyright 2019-2022 @subwallet/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import BaseStoreWithAddressAndChain from '@subwallet/extension-base/services/storage-service/db-stores/BaseStoreWithAddressAndChain'; import { ICrowdloanItem } from '../databases'; +const crowdloanStoreLogger = createLogger('CrowdloanStore'); + export default class CrowdloanStore extends BaseStoreWithAddressAndChain { async removeEndedCrowdloans () { const now = new Date(); @@ -16,7 +19,7 @@ export default class CrowdloanStore extends BaseStoreWithAddressAndChain { async getNotificationInfo (id: string) { return this.table.get(id); @@ -51,7 +54,7 @@ export default class InappNotificationStore extends BaseStore<_NotificationInfo> item.proxyId = newProxyId; item.title = item.title.replace(/\[.*?\]/, `[${newName}]`); }) - .catch(console.error); + .catch((error) => inappNotificationStoreLogger.error('Error updating notification proxy ID', error)); } async cleanUpOldNotifications (overdueTime: number) { diff --git a/packages/extension-base/src/services/swap-service/handler/base-handler.ts b/packages/extension-base/src/services/swap-service/handler/base-handler.ts index 63d2b5a19e3..382557031e6 100644 --- a/packages/extension-base/src/services/swap-service/handler/base-handler.ts +++ b/packages/extension-base/src/services/swap-service/handler/base-handler.ts @@ -27,6 +27,9 @@ import BigN from 'bignumber.js'; import { t } from 'i18next'; import { isEthereumAddress } from '@polkadot/util-crypto'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const swapBaseHandlerLogger = createLogger('SwapBaseHandler'); import { createAcrossBridgeExtrinsic } from '../../balance-service/transfer/xcm'; @@ -246,7 +249,7 @@ export class SwapBaseHandler { if (needEditAmount) { bnSendingValue = BigN(selectedQuote.toAmount).multipliedBy(DEFAULT_EXCESS_AMOUNT_WEIGHT); // need to round } else { // todo: remove - console.log('The code cannot run into here, if it runs into here, pls ask dev to check'); + swapBaseHandlerLogger.warn('The code cannot run into here, if it runs into here, pls ask dev to check'); bnSendingValue = BigN(selectedQuote.toAmount); } } @@ -271,7 +274,7 @@ export class SwapBaseHandler { return [step, fee]; } catch (e) { - console.error('Error creating xcm step', e); + swapBaseHandlerLogger.error('Error creating xcm step', e); return undefined; } diff --git a/packages/extension-base/src/services/swap-service/handler/chainflip-handler.ts b/packages/extension-base/src/services/swap-service/handler/chainflip-handler.ts index 76624ea28f1..22049e75c0e 100644 --- a/packages/extension-base/src/services/swap-service/handler/chainflip-handler.ts +++ b/packages/extension-base/src/services/swap-service/handler/chainflip-handler.ts @@ -19,9 +19,12 @@ import BigNumber from 'bignumber.js'; import * as bitcoin from 'bitcoinjs-lib'; import { SubmittableExtrinsic } from '@polkadot/api/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { SWTransaction } from '../../transaction-service/types'; +const chainflipHandlerLogger = createLogger('ChainflipHandler'); + interface DepositAddressResponse { id: number; address: string; @@ -149,7 +152,7 @@ export class ChainflipSwapHandler implements SwapBaseInterface { const data = await response.json() as DepositAddressResponse; - console.log('Chainflip channel info:', data); + chainflipHandlerLogger.debug('Chainflip channel info', data); if (!data.id || !data.address || data.address === '' || !data.issuedBlock || !data.network || !data.channelId) { throw new Error('Error get Chainflip data'); diff --git a/packages/extension-base/src/services/swap-service/handler/kyber-handler.ts b/packages/extension-base/src/services/swap-service/handler/kyber-handler.ts index c34b5588628..37f4bd0ec79 100644 --- a/packages/extension-base/src/services/swap-service/handler/kyber-handler.ts +++ b/packages/extension-base/src/services/swap-service/handler/kyber-handler.ts @@ -12,8 +12,11 @@ import { getId } from '@subwallet/extension-base/utils/getId'; import BigNumber from 'bignumber.js'; import { TransactionConfig } from 'web3-core'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BalanceService } from '../../balance-service'; import { ChainService } from '../../chain-service'; + +const kyberHandlerLogger = createLogger('KyberHandler'); import { _getChainNativeTokenSlug, _getContractAddressOfToken, _isNativeToken } from '../../chain-service/utils'; import FeeService from '../../fee-service/service'; import { calculateGasFeeParams } from '../../fee-service/utils'; @@ -83,7 +86,7 @@ async function buildTxForKyberSwap (params: BuildTxForSwapParams, chain: string) const { recipient, sender, slippageTolerance } = params; let routeSummary = params.routeSummary; - console.log('routeSummary1', routeSummary); + kyberHandlerLogger.debug('routeSummary1', routeSummary); if (!routeSummary || !routeSummary.tokenIn || !routeSummary.tokenOut || !routeSummary.amountIn) { return { @@ -125,7 +128,7 @@ async function buildTxForKyberSwap (params: BuildTxForSwapParams, chain: string) routeSummary = routeData.data.routeSummary; } catch (error) { - console.error('Error:', error); + kyberHandlerLogger.error('Error in Kyber handler', error); return { error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR, 'Unable to build Kyber swap transaction') }; } @@ -139,7 +142,7 @@ async function buildTxForKyberSwap (params: BuildTxForSwapParams, chain: string) enableGasEstimation: true }; - console.log('routeSummary2', routeSummary); + kyberHandlerLogger.debug('routeSummary2', routeSummary); try { const res = await fetchFromProxyService(ProxyServiceRoute.KYBER, `/${chain}/api/v1/route/build`, { @@ -179,7 +182,7 @@ async function buildTxForKyberSwap (params: BuildTxForSwapParams, chain: string) } }; } catch (error) { - console.error('Kyber error:', error); + kyberHandlerLogger.error('Kyber error', error); return { error: new TransactionError(BasicTxErrorType.INTERNAL_ERROR) }; } @@ -391,7 +394,7 @@ export class KyberHandler implements SwapBaseInterface { const rawTx = await buildTxForKyberSwap({ routeSummary: metadata.routeSummary, sender: params.address, recipient, slippageTolerance }, metadata.network); if (rawTx.error) { - console.error('Kyber error:', rawTx.error); + kyberHandlerLogger.error('Kyber error', rawTx.error); throw rawTx.error; } diff --git a/packages/extension-base/src/services/swap-service/handler/optimex-handler.ts b/packages/extension-base/src/services/swap-service/handler/optimex-handler.ts index c5146e05651..10fe2cc7a92 100644 --- a/packages/extension-base/src/services/swap-service/handler/optimex-handler.ts +++ b/packages/extension-base/src/services/swap-service/handler/optimex-handler.ts @@ -21,6 +21,9 @@ import BigNumber from 'bignumber.js'; import * as bitcoin from 'bitcoinjs-lib'; import { hexStripPrefix, u8aToHex } from '@polkadot/util'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const optimexHandlerLogger = createLogger('OptimexHandler'); interface OptimexQuoteMetadata { session_id: string; @@ -187,7 +190,7 @@ export class OptimexHandler implements SwapBaseInterface { }); if (!rawResponse.ok) { - console.log('Error bad request while init quote'); + optimexHandlerLogger.error('Error bad request while init quote'); return undefined; } @@ -196,7 +199,7 @@ export class OptimexHandler implements SwapBaseInterface { tradeInfo = response.data; } catch (e) { - console.log('Error while init quote'); + optimexHandlerLogger.error('Error while init quote'); return undefined; } @@ -233,7 +236,7 @@ export class OptimexHandler implements SwapBaseInterface { const depositAddress = this.currentTradeMetadata?.deposit_address; if (!depositAddress) { - console.log('Optimex Trade metadata is undefined, request for new quote'); + optimexHandlerLogger.warn('Optimex Trade metadata is undefined, request for new quote'); return Promise.resolve(undefined); } @@ -303,7 +306,7 @@ export class OptimexHandler implements SwapBaseInterface { networkFeeAmount = Math.ceil(feeCombine.feeRate * sizeInfo.txVBytes).toString(); } else { - console.log('Unsupported swap from this chain type', originChainType); + optimexHandlerLogger.warn('Unsupported swap from this chain type', originChainType); return Promise.resolve(undefined); } @@ -437,8 +440,8 @@ export class OptimexHandler implements SwapBaseInterface { let extrinsic: SWTransaction['transaction']; // dont remove this log - console.log('Optimex Trade metadata:', this.currentTradeMetadata); - console.log('Optimex Trade channel:', this.isTestnet ? `https://provider-api-docs.vercel.app/swap/${tradeId}` : `https://provider-api-docs.vercel.app/swap/${tradeId}?env=sub_wallet`); + optimexHandlerLogger.debug('Optimex Trade metadata', this.currentTradeMetadata); + optimexHandlerLogger.debug('Optimex Trade channel', this.isTestnet ? `https://provider-api-docs.vercel.app/swap/${tradeId}` : `https://provider-api-docs.vercel.app/swap/${tradeId}?env=sub_wallet`); if (chainType === ChainType.BITCOIN) { const bitcoinApi = this.chainService.getBitcoinApi(chainInfo.slug); diff --git a/packages/extension-base/src/services/swap-service/handler/simpleswap-handler.ts b/packages/extension-base/src/services/swap-service/handler/simpleswap-handler.ts index c104c153ba2..967b050bd4b 100644 --- a/packages/extension-base/src/services/swap-service/handler/simpleswap-handler.ts +++ b/packages/extension-base/src/services/swap-service/handler/simpleswap-handler.ts @@ -14,8 +14,11 @@ import { getId } from '@subwallet/extension-base/utils/getId'; import BigN, { BigNumber } from 'bignumber.js'; import { SubmittableExtrinsic } from '@polkadot/api/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BalanceService } from '../../balance-service'; + +const simpleSwapHandlerLogger = createLogger('SimpleSwapHandler'); import { getERC20TransactionObject, getEVMTransactionObject } from '../../balance-service/transfer/smart-contract'; import { createSubstrateExtrinsic } from '../../balance-service/transfer/token'; import { ChainService } from '../../chain-service'; @@ -101,7 +104,7 @@ const buildTxForSimpleSwap = async (params: BuildSimpleSwapTxParams): Promise action.action === DynamicSwapType.SWAP); if (!swapPairInfo) { - console.error('Swap pair is not found'); + logger.error('Swap pair is not found'); return result; } @@ -152,15 +155,15 @@ export class SwapService implements StoppableServiceInterface { const { path, swapQuoteResponse } = await this.getLatestQuoteFromSwapRequest(request); - console.group('Swap Logger'); - console.log('path', path); - console.log('swapQuoteResponse', swapQuoteResponse); + logger.group('Swap Logger'); + logger.info('path', path); + logger.info('swapQuoteResponse', swapQuoteResponse); if (swapQuoteResponse.optimalQuote && swapQuoteResponse.optimalQuote.metadata) { const routing = (swapQuoteResponse.optimalQuote.metadata as UniswapMetadata).routing; if (routing) { - console.log('Uniswap routing', routing); + logger.info('Uniswap routing', routing); } } @@ -190,8 +193,8 @@ export class SwapService implements StoppableServiceInterface { }; } - console.log('optimalProcess', optimalProcess); - console.groupEnd(); + logger.info('optimalProcess', optimalProcess); + logger.groupEnd(); if (JSON.stringify(processStepsToPathActions(optimalProcess.steps)) !== JSON.stringify(optimalProcess.path.map((e) => e.action))) { throw new Error('Swap pair is not found'); @@ -209,7 +212,7 @@ export class SwapService implements StoppableServiceInterface { try { availablePath = await subwalletApiSdk.swapApi.findAvailablePath(request); } catch (e) { - console.log('Error findAvailablePath', e); + logger.error('Error findAvailablePath', e); } if (!availablePath) { diff --git a/packages/extension-base/src/services/swap-service/utils.ts b/packages/extension-base/src/services/swap-service/utils.ts index fe5ba8d36bf..f6f9d1e45be 100644 --- a/packages/extension-base/src/services/swap-service/utils.ts +++ b/packages/extension-base/src/services/swap-service/utils.ts @@ -5,8 +5,11 @@ import { _ChainAsset } from '@subwallet/chain-list/types'; import { _getOriginChainOfAsset, _parseAssetRefKey } from '@subwallet/extension-base/services/chain-service/utils'; import { BaseSwapStepMetadata, CommonStepDetail, CommonStepType, DynamicSwapAction, DynamicSwapType, SwapStepType } from '@subwallet/extension-base/types'; import { SwapPair, SwapProviderId } from '@subwallet/extension-base/types/swap'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import BigN from 'bignumber.js'; +const swapUtilsLogger = createLogger('SwapUtils'); + export const CHAIN_FLIP_TESTNET_EXPLORER = 'https://blocks-perseverance.chainflip.io'; export const CHAIN_FLIP_MAINNET_EXPLORER = 'https://scan.chainflip.io'; @@ -59,7 +62,7 @@ export function getChainRouteFromSteps (steps: CommonStepDetail[]): string[] { const metadata = currentStep.metadata as unknown as BaseSwapStepMetadata; if (!metadata) { - console.error('Step has no metadata'); + swapUtilsLogger.error('Step has no metadata'); return chainRoute; } diff --git a/packages/extension-base/src/services/transaction-service/index.ts b/packages/extension-base/src/services/transaction-service/index.ts index 864196ee72c..6956eb308f3 100644 --- a/packages/extension-base/src/services/transaction-service/index.ts +++ b/packages/extension-base/src/services/transaction-service/index.ts @@ -42,6 +42,9 @@ import { EventRecord } from '@polkadot/types/interfaces'; import { SignerPayloadJSON } from '@polkadot/types/types/extrinsic'; import { hexToU8a, isHex } from '@polkadot/util'; import { HexString } from '@polkadot/util/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const transactionServiceLogger = createLogger('TransactionService'); export default class TransactionService { private readonly state: KoniState; @@ -1144,14 +1147,14 @@ export default class TransactionService { return [historyItem, receiverHistory]; } } catch (e) { - console.warn(e); + transactionServiceLogger.warn('Error processing transaction history', e); } return [historyItem]; } private onSigned ({ id }: TransactionEventResponse) { - console.debug(`Transaction "${id}" is signed`); + transactionServiceLogger.debug(`Transaction "${id}" is signed`); } private onSend ({ id, nonce, startBlock }: TransactionEventResponse) { @@ -1159,11 +1162,11 @@ export default class TransactionService { this.updateTransaction(id, { status: ExtrinsicStatus.SUBMITTING }); // Create Input History Transaction History - this.state.historyService.insertHistories(this.transactionToHistories(id, startBlock, nonce)).catch(console.error); + this.state.historyService.insertHistories(this.transactionToHistories(id, startBlock, nonce)).catch((error) => transactionServiceLogger.error('Error inserting transaction histories', error)); - this.createProcessNotification(id).catch(console.error); + this.createProcessNotification(id).catch((error) => transactionServiceLogger.error('Error creating process notification', error)); - console.debug(`Transaction "${id}" is sent`); + transactionServiceLogger.debug(`Transaction "${id}" is sent`); } private onHasTransactionHash ({ blockHash, extrinsicHash, id }: TransactionEventResponse) { @@ -1173,9 +1176,9 @@ export default class TransactionService { this.updateTransaction(id, updateData); // In this case transaction id is the same as extrinsic hash and will change after below update - this.state.historyService.updateHistoryByExtrinsicHash(id, updateData).catch(console.error); + this.state.historyService.updateHistoryByExtrinsicHash(id, updateData).catch((error) => transactionServiceLogger.error('Error updating history by extrinsic hash', error)); - console.debug(`Transaction "${id}" is submitted with hash ${extrinsicHash || ''}`); + transactionServiceLogger.debug(`Transaction "${id}" is submitted with hash ${extrinsicHash || ''}`); const transaction = this.getTransaction(id); @@ -1202,18 +1205,18 @@ export default class TransactionService { const sender = keyring.getPair(inputData.from); balanceService.refreshBalanceForAddress(sender.address, transaction.chain, inputData.tokenSlug, transaction.extrinsicType) - .catch((error) => console.error('Failed to run balance subscription:', error)); + .catch((error) => transactionServiceLogger.error('Failed to run balance subscription', error)); } catch (e) { - console.error(e); + transactionServiceLogger.error('Error refreshing sender balance', e); } try { const recipient = keyring.getPair(inputData.to); balanceService.refreshBalanceForAddress(recipient.address, transaction.chain, inputData.tokenSlug, transaction.extrinsicType) - .catch((error) => console.error('Failed to run balance subscription:', error)); + .catch((error) => transactionServiceLogger.error('Failed to run balance subscription', error)); } catch (e) { - console.error(e); + transactionServiceLogger.error('Error refreshing recipient balance', e); } } } @@ -1231,18 +1234,18 @@ export default class TransactionService { .then(() => { this.state.eventService.emit('transaction.transferNft', undefined); }) - .catch(console.error); + .catch((error) => transactionServiceLogger.error('Error handling NFT transfer', error)); } catch (e) { - console.error(e); + transactionServiceLogger.error('Error processing NFT transfer for sender', e); } try { const recipient = keyring.getPair(inputData.recipientAddress); recipient && this.state.dbService.addNft(recipient.address, { ...inputData.nftItem, owner: recipient.address }) - .catch(console.error); + .catch((error) => transactionServiceLogger.error('Error adding NFT for recipient', error)); } catch (e) { - console.error(e); + transactionServiceLogger.error('Error processing NFT transfer for recipient', e); } } else if ([ExtrinsicType.STAKING_BOND, ExtrinsicType.STAKING_UNBOND, ExtrinsicType.STAKING_WITHDRAW, ExtrinsicType.STAKING_CANCEL_UNSTAKE, ExtrinsicType.STAKING_CLAIM_REWARD, ExtrinsicType.JOIN_YIELD_POOL, ExtrinsicType.STAKING_LEAVE_POOL].includes(transaction.extrinsicType)) { this.state.eventService.emit('transaction.submitStaking', transaction.chain); @@ -1251,7 +1254,7 @@ export default class TransactionService { const toAssetSlug = inputData.quote.pair.to; // todo: consider async - this.state.chainService.updateAssetSetting(toAssetSlug, { visible: true }, true).catch(console.error); + this.state.chainService.updateAssetSetting(toAssetSlug, { visible: true }, true).catch((error) => transactionServiceLogger.error('Error updating asset setting', error)); } } @@ -1267,7 +1270,7 @@ export default class TransactionService { blockNumber: blockNumber || 0, blockHash: blockHash || '', blockTime - }).catch(console.error); + }).catch((error) => transactionServiceLogger.error('Error updating history on success', error)); const info = isHex(extrinsicHash) ? extrinsicHash : getBaseTransactionInfo(transaction, this.state.chainService.getChainInfoMap()); @@ -1295,7 +1298,7 @@ export default class TransactionService { status: nextStatus, blockNumber: blockNumber || 0, blockHash: blockHash || '' - }).catch(console.error); + }).catch((error) => transactionServiceLogger.error('Error updating history on failure', error)); const info = isHex(transaction?.extrinsicHash) ? transaction?.extrinsicHash : getBaseTransactionInfo(transaction, this.state.chainService.getChainInfoMap()); @@ -1323,7 +1326,7 @@ export default class TransactionService { status: nextStatus, blockNumber: blockNumber || 0, blockHash: blockHash || '' - }).catch(console.error); + }).catch((error) => transactionServiceLogger.error('Error updating history on failure', error)); const info = isHex(transaction?.extrinsicHash) ? transaction?.extrinsicHash : getBaseTransactionInfo(transaction, this.state.chainService.getChainInfoMap()); @@ -1398,7 +1401,7 @@ export default class TransactionService { : '' : payload.data || ''; } catch (e) { - console.warn('Unable to parse contract input data'); + transactionServiceLogger.warn('Unable to parse contract input data'); payload.parseData = payload.data as string; } } @@ -2034,7 +2037,7 @@ export default class TransactionService { }); event.on('success', (transactionStatus) => { - console.log(transactionStatus); + transactionServiceLogger.debug('Transaction success', transactionStatus); eventData.blockHash = transactionStatus.block_hash || undefined; eventData.blockNumber = transactionStatus.block_height || undefined; eventData.blockTime = transactionStatus.block_time ? (transactionStatus.block_time * 1000) : undefined; @@ -2176,7 +2179,7 @@ export default class TransactionService { network: transaction.chain, extrinsicHash: transaction.extrinsicHash }) - .catch(console.error); + .catch((error) => transactionServiceLogger.error('Error creating transaction notification', error)); } public async createProcessIfNeed (process: ProcessTransactionData) { @@ -2196,7 +2199,7 @@ export default class TransactionService { const { processId } = step; this.aliveProcessMap.delete(processId); - this.state.dbService.deleteProcessTransactionById(processId).catch(console.error); + this.state.dbService.deleteProcessTransactionById(processId).catch((error) => transactionServiceLogger.error('Error deleting process transaction', error)); this.updateAliveProcess(); } @@ -2252,7 +2255,7 @@ export default class TransactionService { } this.aliveProcessMap.set(processId, process); - this.state.dbService.upsertProcessTransaction(process).catch(console.error); + this.state.dbService.upsertProcessTransaction(process).catch((error) => transactionServiceLogger.error('Error upserting process transaction', error)); if ([StepStatus.COMPLETE, StepStatus.FAILED, StepStatus.TIMEOUT].includes(process.status)) { this.aliveProcessMap.delete(processId); @@ -2274,11 +2277,11 @@ export default class TransactionService { process.status = data.status; } - this.state.dbService.upsertProcessTransaction(process).catch(console.error); + this.state.dbService.upsertProcessTransaction(process).catch((error) => transactionServiceLogger.error('Error upserting process transaction', error)); } } }) - .catch(console.error); + .catch((error) => transactionServiceLogger.error('Error getting process transaction by id', error)); } } diff --git a/packages/extension-base/src/services/wallet-connect-service/handler/Eip155RequestHandler.ts b/packages/extension-base/src/services/wallet-connect-service/handler/Eip155RequestHandler.ts index c97278be8f8..deaeba22891 100644 --- a/packages/extension-base/src/services/wallet-connect-service/handler/Eip155RequestHandler.ts +++ b/packages/extension-base/src/services/wallet-connect-service/handler/Eip155RequestHandler.ts @@ -6,9 +6,12 @@ import KoniState from '@subwallet/extension-base/koni/background/handlers/State' import WalletConnectService from '@subwallet/extension-base/services/wallet-connect-service'; import { getWCId, parseRequestParams } from '@subwallet/extension-base/services/wallet-connect-service/helpers'; import { EIP155_SIGNING_METHODS } from '@subwallet/extension-base/services/wallet-connect-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { SignClientTypes } from '@walletconnect/types'; import { getSdkError } from '@walletconnect/utils'; +const eip155RequestHandlerLogger = createLogger('Eip155RequestHandler'); + export default class Eip155RequestHandler { readonly #walletConnectService: WalletConnectService; readonly #koniState: KoniState; @@ -19,7 +22,7 @@ export default class Eip155RequestHandler { } #handleError (topic: string, id: number, e: unknown) { - console.log(e); + eip155RequestHandlerLogger.debug('Error in EIP155 request handler', e); let message = (e as Error).message; if (message.includes('User Rejected Request')) { @@ -29,7 +32,7 @@ export default class Eip155RequestHandler { this.#walletConnectService.responseRequest({ topic: topic, response: formatJsonRpcError(id, message) - }).catch(console.error); + }).catch((error) => eip155RequestHandlerLogger.error('Error responding to wallet connect request', error)); } public handleRequest (requestEvent: SignClientTypes.EventArguments['session_request']) { diff --git a/packages/extension-base/src/services/wallet-connect-service/handler/PolkadotRequestHandler.ts b/packages/extension-base/src/services/wallet-connect-service/handler/PolkadotRequestHandler.ts index de0e5343abe..1ff0c5dbf6f 100644 --- a/packages/extension-base/src/services/wallet-connect-service/handler/PolkadotRequestHandler.ts +++ b/packages/extension-base/src/services/wallet-connect-service/handler/PolkadotRequestHandler.ts @@ -8,11 +8,14 @@ import RequestService from '@subwallet/extension-base/services/request-service'; import WalletConnectService from '@subwallet/extension-base/services/wallet-connect-service'; import { getWCId, parseRequestParams } from '@subwallet/extension-base/services/wallet-connect-service/helpers'; import { POLKADOT_SIGNING_METHODS } from '@subwallet/extension-base/services/wallet-connect-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isSameAddress } from '@subwallet/extension-base/utils'; import keyring from '@subwallet/ui-keyring'; import { SignClientTypes } from '@walletconnect/types'; import { getSdkError } from '@walletconnect/utils'; +const polkadotRequestHandlerLogger = createLogger('PolkadotRequestHandler'); + export default class PolkadotRequestHandler { readonly #walletConnectService: WalletConnectService; readonly #requestService: RequestService; @@ -38,7 +41,7 @@ export default class PolkadotRequestHandler { this.#walletConnectService.responseRequest({ topic: topic, response: formatJsonRpcError(id, message) - }).catch(console.error); + }).catch((error) => polkadotRequestHandlerLogger.error('Error responding to wallet connect request', error)); } public handleRequest (requestEvent: SignClientTypes.EventArguments['session_request']) { diff --git a/packages/extension-base/src/services/wallet-connect-service/index.ts b/packages/extension-base/src/services/wallet-connect-service/index.ts index 048cd9b5429..b48f16d2794 100644 --- a/packages/extension-base/src/services/wallet-connect-service/index.ts +++ b/packages/extension-base/src/services/wallet-connect-service/index.ts @@ -7,8 +7,11 @@ import RequestService from '@subwallet/extension-base/services/request-service'; import Eip155RequestHandler from '@subwallet/extension-base/services/wallet-connect-service/handler/Eip155RequestHandler'; import { SWStorage } from '@subwallet/extension-base/storage'; import { wait } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { IKeyValueStorage } from '@walletconnect/keyvaluestorage'; import SignClient from '@walletconnect/sign-client'; + +const walletConnectLogger = createLogger('WalletConnectService'); import { EngineTypes, SessionTypes, SignClientTypes } from '@walletconnect/types'; import { getInternalError, getSdkError } from '@walletconnect/utils'; import { BehaviorSubject } from 'rxjs'; @@ -67,7 +70,7 @@ export default class WalletConnectService { this.#polkadotRequestHandler = new PolkadotRequestHandler(this, requestService); this.#eip155RequestHandler = new Eip155RequestHandler(this.#koniState, this); - this.initClient().catch(console.error); + this.initClient().catch((error) => walletConnectLogger.error('Error initializing WalletConnect client', error)); } private async haveData () { @@ -171,7 +174,7 @@ export default class WalletConnectService { throw Error(getSdkError('INVALID_METHOD').message + ' ' + method); } } catch (e) { - console.log(e); + walletConnectLogger.error('Error in WalletConnect handler', e); try { const requestSession = this.getSession(topic); @@ -183,7 +186,7 @@ export default class WalletConnectService { this.responseRequest({ topic: topic, response: formatJsonRpcError(id, (e as Error).message) - }).catch(console.error); + }).catch((error) => walletConnectLogger.error('Error handling WalletConnect request', error)); } } @@ -200,7 +203,7 @@ export default class WalletConnectService { await this.#client.ping({ topic }); } } catch (e) { - console.error(e); + walletConnectLogger.error('Error pinging WalletConnect session', e); } } @@ -208,8 +211,8 @@ export default class WalletConnectService { this.#client?.on('session_proposal', this.#onSessionProposal.bind(this)); this.#client?.on('session_request', this.#onSessionRequest.bind(this)); this.#client?.on('session_ping', this.#onPingReply.bind(this)); - this.#client?.on('session_event', (data) => console.log('event', data)); - this.#client?.on('session_update', (data) => console.log('update', data)); + this.#client?.on('session_event', (data) => walletConnectLogger.debug('WalletConnect session event', data)); + this.#client?.on('session_update', (data) => walletConnectLogger.debug('WalletConnect session update', data)); this.#client?.on('session_delete', this.#updateSessions.bind(this)); } @@ -302,7 +305,7 @@ export default class WalletConnectService { reason: getSdkError('USER_DISCONNECTED') }); } catch (e) { - console.error(e); + walletConnectLogger.error('Error in WalletConnect operation', e); } } @@ -316,7 +319,7 @@ export default class WalletConnectService { reason: getSdkError('USER_DISCONNECTED') }); } catch (e) { - console.error(e); + walletConnectLogger.error('Error in WalletConnect operation', e); } } @@ -328,7 +331,7 @@ export default class WalletConnectService { try { await this.#client?.core.storage.removeItem(key); } catch (e) { - console.error(e); + walletConnectLogger.error('Error in WalletConnect operation', e); } } diff --git a/packages/extension-base/src/storage/index.ts b/packages/extension-base/src/storage/index.ts index cba573b6088..e4dbf367e89 100644 --- a/packages/extension-base/src/storage/index.ts +++ b/packages/extension-base/src/storage/index.ts @@ -3,9 +3,12 @@ import KoniDatabase from '@subwallet/extension-base/services/storage-service/databases'; import { createPromiseHandler } from '@subwallet/extension-base/utils/promise'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { xglobal } from '@polkadot/x-global'; +const swStorageLogger = createLogger('SWStorage'); + const hasLocalStorage = typeof localStorage !== 'undefined'; // Create localStorage adaptor @@ -26,7 +29,7 @@ export class SWStorage { this.isReady = true; this.waitReadyHandler.resolve(this); }) - .catch(console.error); + .catch((e) => swStorageLogger.error('Error initializing SWStorage', e)); } async setItem (key: string, value: string) { @@ -36,7 +39,7 @@ export class SWStorage { if (this.localStorage) { this.localStorage?.setItem(key, value); } else { - this.kvDatabase.put({ key, value }).catch(console.error); + this.kvDatabase.put({ key, value }).catch((e) => swStorageLogger.error('Error putting item to kvDatabase', e)); } } @@ -59,7 +62,7 @@ export class SWStorage { this.kvDatabase .bulkPut(putList) - .catch(console.error); + .catch((e) => swStorageLogger.error('Error bulk putting items to kvDatabase', e)); } } @@ -95,7 +98,7 @@ export class SWStorage { this.kvDatabase .where({ key }) .delete() - .catch(console.error); + .catch((e) => swStorageLogger.error('Error deleting item from kvDatabase', e)); } } @@ -114,7 +117,7 @@ export class SWStorage { .where('key') .anyOf(keys) .delete() - .catch(console.error); + .catch((e) => swStorageLogger.error('Error deleting items from kvDatabase', e)); } } @@ -125,7 +128,7 @@ export class SWStorage { if (this.localStorage) { this.localStorage.clear(); } else { - this.kvDatabase.clear().catch(console.error); + this.kvDatabase.clear().catch((e) => swStorageLogger.error('Error clearing kvDatabase', e)); } } diff --git a/packages/extension-base/src/stores/Base.ts b/packages/extension-base/src/stores/Base.ts index 59783b79325..4917552fb2e 100644 --- a/packages/extension-base/src/stores/Base.ts +++ b/packages/extension-base/src/stores/Base.ts @@ -1,13 +1,17 @@ // Copyright 2019-2022 @polkadot/extension-base authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; + type StoreValue = Record; +const baseStoreLogger = createLogger('BaseStore'); + const lastError = (type: string): void => { const error = chrome.runtime.lastError; if (error) { - console.error(`BaseStore.${type}:: runtime.lastError:`, error); + baseStoreLogger.error(`BaseStore.${type}:: runtime.lastError`, error); } }; diff --git a/packages/extension-base/src/stores/Keyring.ts b/packages/extension-base/src/stores/Keyring.ts index d4ca29c61f6..7fcabf05df3 100644 --- a/packages/extension-base/src/stores/Keyring.ts +++ b/packages/extension-base/src/stores/Keyring.ts @@ -6,13 +6,17 @@ import type { PasswordStore } from '@subwallet/ui-keyring/types'; import { SUBWALLET_KEYRING } from '@subwallet/ui-keyring/defaults'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + type StoreValue = Record; +const keyringStoreLogger = createLogger('KeyringStore'); + const lastError = (type: string): void => { const error = chrome.runtime.lastError; if (error) { - console.error(`KeyringStore.${type}:: runtime.lastError:`, error); + keyringStoreLogger.error(`KeyringStore.${type}:: runtime.lastError`, error); } }; diff --git a/packages/extension-base/src/stores/TransactionHistory.ts b/packages/extension-base/src/stores/TransactionHistory.ts index 6e3c103b6da..67b9235b847 100644 --- a/packages/extension-base/src/stores/TransactionHistory.ts +++ b/packages/extension-base/src/stores/TransactionHistory.ts @@ -4,12 +4,15 @@ import { TxHistoryItem } from '@subwallet/extension-base/background/KoniTypes'; import { EXTENSION_PREFIX } from '@subwallet/extension-base/defaults'; import SubscribableStore from '@subwallet/extension-base/stores/SubscribableStore'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const transactionHistoryStoreLogger = createLogger('TransactionHistoryStore'); const lastError = (type: string): void => { const error = chrome.runtime.lastError; if (error) { - console.error(`TransactionHistoryStore.${type}:: runtime.lastError:`, error); + transactionHistoryStoreLogger.error(`TransactionHistoryStore.${type}:: runtime.lastError`, error); } }; diff --git a/packages/extension-base/src/strategy/api-request-strategy-v2/index.ts b/packages/extension-base/src/strategy/api-request-strategy-v2/index.ts index 9f42a1c002c..7def33d2a7c 100644 --- a/packages/extension-base/src/strategy/api-request-strategy-v2/index.ts +++ b/packages/extension-base/src/strategy/api-request-strategy-v2/index.ts @@ -3,9 +3,12 @@ import { SWError } from '@subwallet/extension-base/background/errors/SWError'; import { BASE_MINUTE_INTERVAL } from '@subwallet/extension-base/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Md5 } from 'ts-md5'; import { ApiRequestContext } from '../api-request-strategy/types'; + +const apiRequestStrategyLogger = createLogger('ApiRequestStrategyV2'); import { ApiRequestStrategyV2, ApiRequestV2 } from './types'; export abstract class BaseApiRequestStrategyV2 implements ApiRequestStrategyV2 { @@ -79,7 +82,7 @@ export abstract class BaseApiRequestStrategyV2 implements ApiRequestStrategyV2 { return; } - console.log('[ApiRequestStrategyV2] Processing requests...', remainingRequests.map((r) => r.groupId)); + apiRequestStrategyLogger.debug('Processing requests', remainingRequests.map((r) => r.groupId)); // Get first this.limit requests base on id const requests = remainingRequests @@ -98,7 +101,7 @@ export abstract class BaseApiRequestStrategyV2 implements ApiRequestStrategyV2 { request.resolve(resp); - console.log('[ApiRequestStrategyV2] Cache hit for request', request.id, 'with cache key', request.cacheKey); + apiRequestStrategyLogger.debug(`Cache hit for request ${request.id} with cache key ${request.cacheKey}`); delete this.requestMap[request.id]; diff --git a/packages/extension-base/src/utils/eth/parseTransaction/base.ts b/packages/extension-base/src/utils/eth/parseTransaction/base.ts index 2b2aa1d80cd..0bca84a032e 100644 --- a/packages/extension-base/src/utils/eth/parseTransaction/base.ts +++ b/packages/extension-base/src/utils/eth/parseTransaction/base.ts @@ -9,6 +9,10 @@ import isBuffer from 'is-buffer'; // @ts-ignore import { _jsonInterfaceMethodToString, AbiInput, AbiItem, keccak256 } from 'web3-utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const parseTransactionLogger = createLogger('ParseTransaction'); + export interface InputData { method: string | null; methodName: string | null; @@ -275,7 +279,7 @@ export class InputDataDecoder { }; } } catch (err) { - console.log(err); + parseTransactionLogger.error('Error parsing transaction', err); } } diff --git a/packages/extension-base/src/utils/fee/transfer.ts b/packages/extension-base/src/utils/fee/transfer.ts index 9e2d20e062f..48e56bd0c74 100644 --- a/packages/extension-base/src/utils/fee/transfer.ts +++ b/packages/extension-base/src/utils/fee/transfer.ts @@ -26,8 +26,11 @@ import { ValidateTransactionResponseInput } from '@subwallet/extension-base/serv import { EvmEIP1559FeeDetail, EvmEIP1559FeeOption, FeeChainType, FeeDetail, FeeInfo, SubstrateTipInfo, TransactionFee } from '@subwallet/extension-base/types'; import { ResponseSubscribeTransfer } from '@subwallet/extension-base/types/balance/transfer'; import { BN_ZERO } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isCardanoAddress, isTonAddress } from '@subwallet/keyring'; import { isBitcoinAddress } from '@subwallet/keyring/utils/address/validate'; + +const feeTransferLogger = createLogger('FeeTransfer'); import BigN from 'bignumber.js'; import * as bitcoin from 'bitcoinjs-lib'; import { TransactionConfig } from 'web3-core'; @@ -320,7 +323,7 @@ export const calculateTransferMaxTransferable = async (id: string, request: Calc error = (e as Error).message || 'Unable to estimate fee'; - console.warn('Unable to estimate fee', e); + feeTransferLogger.warn('Unable to estimate fee', e); } if (isTransferLocalTokenAndPayThatTokenAsFee && feeChainType === 'substrate') { @@ -518,7 +521,7 @@ export const calculateXcmMaxTransferable = async (id: string, request: Calculate error = (e as Error).message || 'Unable to estimate fee'; - console.warn('Unable to estimate fee', e); + feeTransferLogger.warn('Unable to estimate fee', e); } if (!destToken) { diff --git a/packages/extension-base/src/utils/index.ts b/packages/extension-base/src/utils/index.ts index 7f7563b6764..40c415b42f4 100644 --- a/packages/extension-base/src/utils/index.ts +++ b/packages/extension-base/src/utils/index.ts @@ -440,3 +440,4 @@ export * from './swap'; export * from './translate'; export * from './bitcoin'; export * from './setup-api-sdk'; +export * from './logger'; \ No newline at end of file diff --git a/packages/extension-base/src/utils/logger/Logger.ts b/packages/extension-base/src/utils/logger/Logger.ts new file mode 100644 index 00000000000..1b19121d38b --- /dev/null +++ b/packages/extension-base/src/utils/logger/Logger.ts @@ -0,0 +1,298 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import log from 'loglevel'; +import { LogContext, LogLevel, LoggerConfig, StructuredLogData } from './types'; +import { sentryAdapter } from './sentry-adapter'; + +const LOG_LEVELS: Record = { + trace: 0, + debug: 1, + info: 2, + warn: 3, + error: 4 +}; + +const isDevelopment = process.env.NODE_ENV !== 'production'; + +/** + * Extract context from Error stack trace + */ +function extractContext (skipFrames = 2): LogContext | null { + try { + const stack = new Error().stack; + if (!stack) { + return null; + } + + const lines = stack.split('\n'); + // Skip Error constructor and extractContext call + const frame = lines[skipFrames + 1]; + + if (!frame) { + return null; + } + + // Match patterns like: "at functionName (file://path/to/file.ts:123:45)" + const match = frame.match(/at\s+(?:async\s+)?(.+?)\s+\((.+?):(\d+):(\d+)\)/); + + if (match) { + const [, functionName, filePath, line, column] = match; + const fileName = filePath.split('/').pop() || filePath; + + return { + file: fileName, + function: functionName, + line: parseInt(line, 10), + column: parseInt(column, 10), + timestamp: new Date().toISOString(), + level: 'info' as LogLevel, + loggerName: '' + }; + } + } catch { + // Ignore errors in context extraction + } + + return null; +} + +export class Logger { + private logInstance: log.Logger; + private name: string; + private config: Required; + private groupStack: string[] = []; + + constructor (config: LoggerConfig) { + this.name = config.name; + this.config = { + name: config.name, + level: config.level || (isDevelopment ? 'debug' : 'info'), + enableStructuredLogging: config.enableStructuredLogging ?? false, + enableContextCapture: config.enableContextCapture ?? true + }; + + // Create a named logger instance + this.logInstance = log.getLogger(this.name); + this.logInstance.setLevel(this.getLogLevelNumber(this.config.level) as log.LogLevelDesc); + } + + private getLogLevelNumber (level: LogLevel): number { + return LOG_LEVELS[level]; + } + + private shouldLog (level: LogLevel): boolean { + return LOG_LEVELS[level] >= this.getLogLevelNumber(this.config.level); + } + + private formatMessage (level: LogLevel, message: string, ...args: unknown[]): string { + const prefix = `[${this.name}] [${level.toUpperCase()}]`; + return `${prefix} ${message}`; + } + + private createLogContext (level: LogLevel): LogContext { + const baseContext: LogContext = { + timestamp: new Date().toISOString(), + level, + loggerName: this.name + }; + + if (this.config.enableContextCapture) { + const extracted = extractContext(3); + if (extracted) { + return { ...baseContext, ...extracted }; + } + } + + return baseContext; + } + + private logStructured (level: LogLevel, data: StructuredLogData): void { + if (!this.shouldLog(level)) { + return; + } + + const context = this.createLogContext(level); + const logEntry = { + ...context, + message: data.message, + context: data.context, + error: data.error instanceof Error ? { + name: data.error.name, + message: data.error.message, + stack: data.error.stack + } : data.error, + tags: data.tags, + extra: data.extra + }; + + // Output structured JSON + const jsonOutput = JSON.stringify(logEntry, null, 2); + this.logInstance[level](jsonOutput); + + // Add breadcrumb to Sentry + if (data.error instanceof Error) { + sentryAdapter.captureException(data.error, { + ...data.context, + logger: this.name, + tags: data.tags + }); + } else { + sentryAdapter.addBreadcrumb(data.message, level, { + ...data.context, + logger: this.name, + tags: data.tags + }); + } + } + + // Simple logging methods (drop-in console replacement) + error (message: string, ...args: unknown[]): void { + if (!this.shouldLog('error')) { + return; + } + + const formatted = this.formatMessage('error', message); + this.logInstance.error(formatted, ...args); + + // Add breadcrumb for errors + if (args.length > 0 && args[0] instanceof Error) { + sentryAdapter.captureException(args[0] as Error, { + message, + logger: this.name + }); + } else { + sentryAdapter.addBreadcrumb(message, 'error', { + logger: this.name, + args: args.length > 0 ? args : undefined + }); + } + } + + warn (message: string, ...args: unknown[]): void { + if (!this.shouldLog('warn')) { + return; + } + + const formatted = this.formatMessage('warn', message); + this.logInstance.warn(formatted, ...args); + sentryAdapter.addBreadcrumb(message, 'warn', { + logger: this.name, + args: args.length > 0 ? args : undefined + }); + } + + info (message: string, ...args: unknown[]): void { + if (!this.shouldLog('info')) { + return; + } + + const formatted = this.formatMessage('info', message); + this.logInstance.info(formatted, ...args); + sentryAdapter.addBreadcrumb(message, 'info', { + logger: this.name, + args: args.length > 0 ? args : undefined + }); + } + + log (message: string, ...args: unknown[]): void { + this.info(message, ...args); + } + + debug (message: string, ...args: unknown[]): void { + if (!this.shouldLog('debug')) { + return; + } + + const formatted = this.formatMessage('debug', message); + this.logInstance.debug(formatted, ...args); + sentryAdapter.addBreadcrumb(message, 'debug', { + logger: this.name, + args: args.length > 0 ? args : undefined + }); + } + + trace (message: string, ...args: unknown[]): void { + if (!this.shouldLog('trace')) { + return; + } + + const formatted = this.formatMessage('trace', message); + this.logInstance.trace(formatted, ...args); + sentryAdapter.addBreadcrumb(message, 'trace', { + logger: this.name, + args: args.length > 0 ? args : undefined + }); + } + + // Structured logging methods + errorStructured (data: StructuredLogData): void { + this.logStructured('error', data); + } + + warnStructured (data: StructuredLogData): void { + this.logStructured('warn', data); + } + + infoStructured (data: StructuredLogData): void { + this.logStructured('info', data); + } + + debugStructured (data: StructuredLogData): void { + this.logStructured('debug', data); + } + + traceStructured (data: StructuredLogData): void { + this.logStructured('trace', data); + } + + // Public alias for backward compatibility (calls infoStructured) + logStructuredPublic (data: StructuredLogData): void { + this.infoStructured(data); + } + + // Group methods (console.group/groupEnd replacement) + group (label?: string): void { + const groupLabel = label || `Group ${this.groupStack.length + 1}`; + this.groupStack.push(groupLabel); + + if (this.shouldLog('debug')) { + const indent = ' '.repeat(this.groupStack.length - 1); + const formatted = this.formatMessage('debug', `${indent}▼ ${groupLabel}`); + this.logInstance.debug(formatted); + } + } + + groupEnd (): void { + if (this.groupStack.length === 0) { + return; + } + + const groupLabel = this.groupStack.pop()!; + + if (this.shouldLog('debug')) { + const indent = ' '.repeat(this.groupStack.length); + const formatted = this.formatMessage('debug', `${indent}▲ ${groupLabel}`); + this.logInstance.debug(formatted); + } + } + + // Utility methods + setLevel (level: LogLevel): void { + this.config.level = level; + this.logInstance.setLevel(this.getLogLevelNumber(level) as log.LogLevelDesc); + } + + getLevel (): LogLevel { + return this.config.level; + } + + getName (): string { + return this.name; + } + + // Polkadot compatibility - noop method + noop (...values: unknown[]): void { + // No operation - required by Polkadot Logger interface + } +} diff --git a/packages/extension-base/src/utils/logger/index.ts b/packages/extension-base/src/utils/logger/index.ts new file mode 100644 index 00000000000..ee2466644d3 --- /dev/null +++ b/packages/extension-base/src/utils/logger/index.ts @@ -0,0 +1,32 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { Logger } from './Logger'; +import { LoggerConfig } from './types'; + +/** + * Create a named logger instance + * @param name - Logger name (typically the class or module name) + * @param config - Optional logger configuration + * @returns Logger instance + */ +export function createLogger (name: string, config?: Partial): Logger { + return new Logger({ + name, + ...config + }); +} + +/** + * Default logger instance + */ +export const defaultLogger = createLogger('SubWallet'); + +// Export types +export type { LogLevel, LoggerConfig, LogContext, StructuredLogData, SentryAdapter } from './types'; + +// Export Logger class for advanced usage +export { Logger } from './Logger'; + +// Export Sentry adapter for future integration +export { sentryAdapter } from './sentry-adapter'; diff --git a/packages/extension-base/src/utils/logger/sentry-adapter.ts b/packages/extension-base/src/utils/logger/sentry-adapter.ts new file mode 100644 index 00000000000..82941a2abb6 --- /dev/null +++ b/packages/extension-base/src/utils/logger/sentry-adapter.ts @@ -0,0 +1,28 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import { LogLevel, SentryAdapter } from './types'; + +/** + * Placeholder Sentry adapter for future integration + * Currently implements no-op methods + * When Sentry SDK is integrated, replace these with actual Sentry calls + */ +class SentryAdapterImpl implements SentryAdapter { + captureException (error: Error, context?: Record): void { + // TODO: Integrate Sentry SDK + // Example: Sentry.captureException(error, { extra: context }); + } + + addBreadcrumb (message: string, level: LogLevel, data?: Record): void { + // TODO: Integrate Sentry SDK + // Example: Sentry.addBreadcrumb({ message, level, data }); + } + + setContext (key: string, context: Record): void { + // TODO: Integrate Sentry SDK + // Example: Sentry.setContext(key, context); + } +} + +export const sentryAdapter = new SentryAdapterImpl(); diff --git a/packages/extension-base/src/utils/logger/types.ts b/packages/extension-base/src/utils/logger/types.ts new file mode 100644 index 00000000000..3b21139876f --- /dev/null +++ b/packages/extension-base/src/utils/logger/types.ts @@ -0,0 +1,35 @@ +// Copyright 2019-2022 @subwallet/extension-base authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace'; + +export interface LoggerConfig { + name: string; + level?: LogLevel; + enableStructuredLogging?: boolean; + enableContextCapture?: boolean; +} + +export interface LogContext { + file?: string; + function?: string; + line?: number; + column?: number; + timestamp: string; + level: LogLevel; + loggerName: string; +} + +export interface StructuredLogData { + message: string; + context?: Record; + error?: Error | unknown; + tags?: string[]; + extra?: Record; +} + +export interface SentryAdapter { + captureException(error: Error, context?: Record): void; + addBreadcrumb(message: string, level: LogLevel, data?: Record): void; + setContext(key: string, context: Record): void; +} diff --git a/packages/extension-base/src/utils/metadata.ts b/packages/extension-base/src/utils/metadata.ts index 05e5555936f..686fe356841 100644 --- a/packages/extension-base/src/utils/metadata.ts +++ b/packages/extension-base/src/utils/metadata.ts @@ -8,6 +8,10 @@ import { ApiPromise } from '@polkadot/api'; import { TypeRegistry } from '@polkadot/types'; import { getSpecExtensions, getSpecTypes } from '@polkadot/types-known'; import { formatBalance, isNumber, u8aToHex } from '@polkadot/util'; + +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const metadataUtilsLogger = createLogger('MetadataUtils'); import { HexString } from '@polkadot/util/types'; import { defaults as addressDefaults } from '@polkadot/util-crypto/address/defaults'; import { ExtraInfo, merkleizeMetadata } from '@polkadot-api/merkleize-metadata'; @@ -64,11 +68,11 @@ const updateMetadataV15 = async (chain: string, api: ApiPromise, chainService?: hexV15 }; - chainService?.upsertMetadataV15(chain, { ...updateMetadata }).catch(console.error); + chainService?.upsertMetadataV15(chain, { ...updateMetadata }).catch((e) => metadataUtilsLogger.error('Error upserting metadata V15', e)); } } } catch (err) { - console.error('Error:', err); + metadataUtilsLogger.error('Error in updateMetadataV15', err); } }; @@ -110,7 +114,7 @@ const updateMetadata = async ( tokenInfo }; - chainService?.upsertMetadata(chain, { ...updateMetadata }).catch(console.error); + chainService?.upsertMetadata(chain, { ...updateMetadata }).catch((e) => metadataUtilsLogger.error('Error upserting metadata', e)); }; export const cacheMetadata = ( @@ -120,7 +124,7 @@ export const cacheMetadata = ( ): void => { // Update metadata to database with async methods substrateApi.api.isReady.then((api) => { - updateMetadata(chain, api, chainService).catch(console.error); - updateMetadataV15(chain, api, chainService).catch(console.error); - }).catch(console.error); + updateMetadata(chain, api, chainService).catch((e) => metadataUtilsLogger.error('Error updating metadata', e)); + updateMetadataV15(chain, api, chainService).catch((e) => metadataUtilsLogger.error('Error updating metadata V15', e)); + }).catch((e) => metadataUtilsLogger.error('Error in cacheMetadata', e)); }; diff --git a/packages/extension-base/src/utils/promise.ts b/packages/extension-base/src/utils/promise.ts index b56d5ae0c10..6249f5240e8 100644 --- a/packages/extension-base/src/utils/promise.ts +++ b/packages/extension-base/src/utils/promise.ts @@ -1,13 +1,17 @@ // Copyright 2019-2022 @subwallet/extension-base // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; + +const promiseUtilsLogger = createLogger('PromiseUtils'); + export function createPromiseHandler () { let _resolve: (value: T) => void = () => { - console.warn('This promise handler is not implemented'); + promiseUtilsLogger.warn('This promise handler is not implemented'); }; let _reject: (reason?: unknown) => void = () => { - console.warn('This promise handler is not implemented'); + promiseUtilsLogger.warn('This promise handler is not implemented'); }; const promise = new Promise((resolve, reject) => { From 13cc0b51b975da65388032fbfd6ec0914fed6ec9 Mon Sep 17 00:00:00 2001 From: ruhil6789 Date: Wed, 31 Dec 2025 18:24:25 +0530 Subject: [PATCH 2/2] fix: resolve TypeScript circular dependency and logger import issues - Break circular dependency between extension-base and extension-dapp by creating local logger in extension-dapp - Add missing logger imports in extension-koni-ui components - Fix TypeScript project references to resolve build errors - Update tsconfig files to maintain rootDir while breaking circular dependencies - Fix type errors in DebuggerAPI component --- packages/extension-dapp/package.json | 1 + packages/extension-dapp/src/bundle.ts | 15 +++++---- packages/extension-dapp/src/logger.ts | 33 +++++++++++++++++++ .../src/Popup/Account/ConnectLedger.tsx | 9 +++-- .../src/Popup/Account/ImportSeedPhrase.tsx | 3 +- .../src/Popup/Account/NewSeedPhrase.tsx | 5 +-- .../extension-koni-ui/src/Popup/BuyTokens.tsx | 3 +- .../parts/Detail/Substrate/Extrinsic.tsx | 7 ++-- .../Confirmations/parts/Sign/Bitcoin.tsx | 7 ++-- .../Popup/Confirmations/parts/Sign/Evm.tsx | 7 ++-- .../Confirmations/parts/Sign/Substrate.tsx | 11 ++++--- ...coinSendTransactionRequestConfirmation.tsx | 13 +++++--- .../variants/Message/SignConfirmation.tsx | 5 ++- .../src/Popup/Debugger/DebuggerAPI.tsx | 5 +-- .../EarningEntry/EarningPositions/index.tsx | 5 ++- .../src/Popup/Home/History/index.tsx | 9 +++-- .../Popup/Home/Nfts/NftCollectionDetail.tsx | 9 +++-- .../src/Popup/Home/Nfts/NftCollections.tsx | 5 ++- .../src/Popup/Home/Nfts/NftItemDetail.tsx | 15 +++++---- .../Popup/Home/Tokens/DetailUpperBlock.tsx | 5 ++- .../Home/Tokens/PriceChartArea/index.tsx | 11 ++++--- .../src/Popup/Home/Tokens/UpperBlock.tsx | 7 ++-- .../src/Popup/Home/index.tsx | 5 ++- .../Popup/MigrateAccount/BriefView/index.tsx | 3 +- .../ProcessViewItem.tsx | 5 ++- .../SoloAccountMigrationView/index.tsx | 5 ++- .../MigrateAccount/SummaryView/index.tsx | 5 ++- .../src/Popup/MigrateAccount/index.tsx | 7 ++-- .../src/Popup/RemindExportAccount.tsx | 7 ++-- packages/extension-koni-ui/src/Popup/Root.tsx | 7 ++-- .../src/Popup/Settings/Chains/ChainDetail.tsx | 3 +- .../src/Popup/Settings/Chains/ChainImport.tsx | 7 ++-- .../src/Popup/Settings/GeneralSetting.tsx | 3 +- .../Settings/Notifications/Notification.tsx | 25 +++++++------- .../Notifications/NotificationSetting.tsx | 5 ++- .../Security/ManageWebsiteAccess/Detail.tsx | 3 +- .../Security/ManageWebsiteAccess/index.tsx | 9 +++-- .../src/Popup/Settings/Security/index.tsx | 19 ++++++----- .../src/Popup/Settings/Tokens/TokenDetail.tsx | 9 +++-- .../src/Popup/Settings/index.tsx | 2 ++ .../helper/staking/stakingHandler.ts | 7 ++-- .../src/Popup/Transaction/variants/Earn.tsx | 9 +++-- .../Popup/Transaction/variants/SendFund.tsx | 23 +++++++------ .../Popup/Transaction/variants/Swap/index.tsx | 13 ++++---- .../src/Popup/TransactionSubmission.tsx | 7 ++-- .../WalletConnect/ConnectWalletConnect.tsx | 5 +-- .../Popup/WalletConnect/ConnectionDetail.tsx | 3 +- .../extension-koni-ui/src/Popup/router.tsx | 5 ++- .../components/Confirmation/ZkModeFooter.tsx | 3 +- .../src/components/Field/AddressInput.tsx | 9 ++--- .../src/components/Field/AddressInputNew.tsx | 7 ++-- .../Field/Earning/EarningPoolSelector.tsx | 3 +- .../Earning/EarningValidatorSelector.tsx | 3 +- .../src/components/Field/SeedPhraseInput.tsx | 5 +-- .../FeeEditor/FeeEditorModal.tsx | 3 +- .../src/components/Layout/base/Home.tsx | 3 +- .../Layout/parts/ConnectWebsiteModal.tsx | 7 ++-- .../SelectAccount/AccountSelectorModal.tsx | 5 +-- .../Modal/Account/AttachAccountModal.tsx | 5 ++- .../Modal/Account/ImportAccountModal.tsx | 5 ++- .../Modal/Campaign/AppPopupModal.tsx | 5 +-- .../Modal/Campaign/CampaignBannerModal.tsx | 3 +- .../Modal/Customize/CustomizeModal.tsx | 5 ++- .../Modal/DAppConfigurationModal.tsx | 11 ++++--- .../Modal/DeriveAccountActionModal.tsx | 5 ++- .../ChangeValidator.tsx | 5 ++- .../EarningValidatorSelectedModal/index.tsx | 5 ++- .../Modal/Global/AddressQrModal.tsx | 5 +-- .../Modal/NotificationDetailModal.tsx | 5 ++- .../Modal/ReceiveModal/ReceiveQrModal.tsx | 5 +-- .../ReceiveModal/TokensSelectorModal.tsx | 5 ++- .../Modal/Swap/SwapQuotesSelectorModal.tsx | 3 +- .../Modal/SwitchNetworkAuthorizeModal.tsx | 5 ++- .../TermsAndConditions/GeneralTermModal.tsx | 3 +- .../TransactionProcessDetailModal/index.tsx | 7 ++-- .../parts/TransactionInfoBlock/Swap.tsx | 5 +-- .../StaticContent/BannerGenerator.tsx | 3 +- .../Ledger/LedgerTransportManager.ts | 5 ++- .../src/contexts/DataContext.tsx | 5 ++- .../src/contexts/InjectContext.tsx | 7 ++-- .../src/contexts/MktCampaignModalContext.tsx | 5 ++- .../src/contexts/ScannerContext.tsx | 3 +- .../src/contexts/ThemeContext.tsx | 5 ++- .../contexts/WalletModalContextProvider.tsx | 5 ++- .../hooks/account/useHandleMantaPaySync.tsx | 7 ++-- .../src/hooks/balance/useGetBalance.ts | 7 ++-- .../hooks/browser/useUpgradeFireFoxVersion.ts | 3 +- .../src/hooks/chain/useAssetChecker.tsx | 7 ++-- .../src/hooks/chain/useChainChecker.tsx | 5 ++- .../src/hooks/chain/useChainConnection.ts | 5 ++- .../src/hooks/common/useSubscribeLanguage.ts | 5 ++- .../src/hooks/dom/useSidePanelUtils.ts | 3 +- .../src/hooks/earning/useTaoStakingFee.ts | 3 +- .../hooks/form/useSelectModalInputHelper.ts | 3 +- .../src/hooks/ledger/useLedger.ts | 9 +++-- .../src/hooks/qr/useCreateQrPayload.ts | 3 +- .../screen/crowdloan/useGetCrowdloanList.ts | 3 +- .../hooks/screen/home/useAccountBalance.ts | 3 +- .../screen/home/useCoreReceiveModalHelper.tsx | 5 +-- .../src/hooks/screen/home/useReceiveQR.ts | 7 ++-- .../useGetAppInstructionData.ts | 3 +- .../transaction/confirmation/useMetadata.ts | 5 +-- .../useParseSubstrateRequestPayload.ts | 3 +- .../process/useGetSwapProcessStepContent.tsx | 9 ++--- .../useGetTransactionProcessStepText.ts | 9 ++--- .../useHandleSubmitMultiTransaction.ts | 3 +- packages/extension-koni-ui/src/i18n/i18n.ts | 5 ++- .../extension-koni-ui/src/messaging/base.ts | 21 +++++++----- .../src/stores/utils/index.ts | 7 ++-- .../src/utils/account/account.ts | 7 ++-- .../src/utils/chain/fetchNetworkByChainId.ts | 7 ++-- .../src/utils/connector/Ledger/index.ts | 5 ++- .../src/utils/missionPools/index.ts | 7 ++-- .../src/utils/scanner/attach.ts | 5 ++- .../src/utils/scanner/decoders.ts | 13 +++++--- .../src/utils/scanner/walletConnect.ts | 5 ++- .../extension-koni/src/background-init.ts | 5 ++- packages/extension-koni/src/background.ts | 9 +++-- packages/extension-koni/src/content.ts | 13 +++++--- .../src/helper/ActionHandler.ts | 15 +++++---- .../extension-koni/src/helper/HeartBeat.ts | 8 +++-- packages/extension-koni/src/page.ts | 5 ++- .../src/Popup/Account/AccountDetail.tsx | 3 +- .../src/Popup/Account/ConnectLedger.tsx | 7 ++-- .../src/Popup/Account/NewSeedPhrase.tsx | 5 +-- .../src/Popup/Account/RestoreJson.tsx | 3 +- .../extension-web-ui/src/Popup/BuyTokens.tsx | 3 +- .../parts/Detail/Substrate/Extrinsic.tsx | 5 +-- .../Popup/Confirmations/parts/Sign/Evm.tsx | 9 ++--- .../Confirmations/parts/Sign/Substrate.tsx | 11 ++++--- .../variants/SignConfirmation.tsx | 3 +- .../CrowdloanContributionsResult.tsx | 3 +- .../Popup/CrowdloanUnlockCampaign/index.tsx | 3 +- .../src/Popup/Debugger/DebuggerAPI.tsx | 5 +-- .../EarningPositionsBalance.tsx | 3 +- .../EarningEntry/EarningPositions/index.tsx | 3 +- .../EarningPreview/EarningPreviewOptions.tsx | 7 ++-- .../EarningPreview/EarningPreviewOutlet.tsx | 5 +-- .../EarningPreview/EarningPreviewPools.tsx | 5 +-- .../src/Popup/Home/History/index.tsx | 7 ++-- .../Inscriptions/InscriptionItemDetail.tsx | 17 +++++----- .../Popup/Home/Nfts/NftCollectionDetail.tsx | 5 +-- .../src/Popup/Home/Nfts/NftCollections.tsx | 3 +- .../src/Popup/Home/Nfts/NftItemDetail.tsx | 17 +++++----- .../src/Popup/Home/PortfolioPage/index.tsx | 3 +- .../Popup/Home/Tokens/DetailUpperBlock.tsx | 3 +- .../src/Popup/Home/Tokens/UpperBlock.tsx | 5 +-- packages/extension-web-ui/src/Popup/Root.tsx | 5 +-- .../src/Popup/Settings/Chains/ChainDetail.tsx | 3 +- .../src/Popup/Settings/Chains/ChainImport.tsx | 5 +-- .../src/Popup/Settings/GeneralSetting.tsx | 3 +- .../Security/ManageWebsiteAccess/Detail.tsx | 11 ++++--- .../Security/ManageWebsiteAccess/index.tsx | 7 ++-- .../src/Popup/Settings/Security/index.tsx | 9 ++--- .../src/Popup/Settings/Tokens/TokenDetail.tsx | 5 +-- .../src/Popup/Settings/index.tsx | 3 +- .../helper/staking/stakingHandler.ts | 5 +-- .../src/Popup/Transaction/variants/Earn.tsx | 7 ++-- .../Popup/Transaction/variants/SendFund.tsx | 3 +- .../src/Popup/Transaction/variants/Swap.tsx | 11 ++++--- .../WalletConnect/ConnectWalletConnect.tsx | 5 +-- .../Popup/WalletConnect/ConnectionDetail.tsx | 3 +- .../extension-web-ui/src/Popup/router.tsx | 3 +- .../src/components/BackgroundExpandView.tsx | 3 +- .../components/Confirmation/ZkModeFooter.tsx | 3 +- .../src/components/Field/AddressInput.tsx | 9 ++--- .../Field/Earning/EarningPoolSelector.tsx | 3 +- .../Earning/EarningValidatorSelector.tsx | 3 +- .../src/components/Field/SeedPhraseInput.tsx | 5 +-- .../Layout/parts/ConnectWebsiteModal.tsx | 5 +-- .../Layout/parts/Header/Balance.tsx | 7 ++-- .../Layout/parts/Header/parts/LockStatus.tsx | 3 +- .../Layout/parts/SelectAccount/index.tsx | 5 +-- .../Modal/Account/AttachAccountModal.tsx | 3 +- .../Modal/Account/ImportAccountModal.tsx | 3 +- .../Modal/Account/SeedPhraseModal.tsx | 3 +- .../Modal/Campaign/CampaignBannerModal.tsx | 3 +- .../Modal/Customize/CustomizeModal.tsx | 3 +- .../Modal/Customize/CustomizeModalSetting.tsx | 3 +- .../Modal/ReceiveModal/ReceiveQrModal.tsx | 7 ++-- .../TermsAndConditions/GeneralTermModal.tsx | 3 +- .../src/contexts/InjectContext.tsx | 11 ++++--- .../src/contexts/ScannerContext.tsx | 3 +- .../src/contexts/ThemeContext.tsx | 3 +- .../hooks/account/useHandleMantaPaySync.tsx | 5 +-- .../src/hooks/balance/useGetBalance.ts | 5 +-- .../src/hooks/chain/useAssetChecker.tsx | 5 +-- .../src/hooks/chain/useChainChecker.tsx | 3 +- .../src/hooks/chain/useChainConnection.ts | 3 +- .../src/hooks/common/useSubscribeLanguage.ts | 3 +- .../hooks/form/useSelectModalInputHelper.ts | 3 +- .../src/hooks/ledger/useLedger.ts | 5 +-- .../src/hooks/qr/useCreateQrPayload.ts | 3 +- .../src/hooks/router/usePreloadView.tsx | 3 +- .../screen/crowdloan/useGetCrowdloanList.ts | 3 +- .../hooks/screen/home/useAccountBalance.ts | 3 +- .../transaction/confirmation/useMetadata.ts | 5 +-- .../useParseSubstrateRequestPayload.ts | 3 +- packages/extension-web-ui/src/i18n/i18n.ts | 8 +++-- .../src/messaging/VirtualMessageCenter.ts | 11 ++++--- .../extension-web-ui/src/messaging/base.ts | 5 +-- .../src/stores/utils/index.ts | 5 +-- .../src/utils/account/account.ts | 5 +-- .../src/utils/chain/fetchNetworkByChainId.ts | 5 +-- .../src/utils/connector/Ledger/index.ts | 3 +- .../src/utils/missionPools/index.ts | 5 +-- .../src/utils/scanner/attach.ts | 3 +- .../src/utils/scanner/decoders.ts | 11 ++++--- .../src/utils/scanner/walletConnect.ts | 3 +- packages/web-runner/src/checkRestore.ts | 5 ++- packages/web-runner/src/fallback.ts | 9 +++-- packages/web-runner/src/messageHandle.ts | 5 ++- packages/web-runner/src/webRunner.ts | 11 ++++--- packages/webapp/src/fallback.ts | 9 +++-- packages/webapp/src/messageHandle.ts | 5 ++- packages/webapp/src/webRunner.ts | 13 +++++--- 216 files changed, 859 insertions(+), 452 deletions(-) create mode 100644 packages/extension-dapp/src/logger.ts diff --git a/packages/extension-dapp/package.json b/packages/extension-dapp/package.json index 6135ca0b4f0..dab3e86a3d2 100644 --- a/packages/extension-dapp/package.json +++ b/packages/extension-dapp/package.json @@ -23,6 +23,7 @@ "@babel/runtime": "^7.20.6", "@polkadot/util": "^13.5.3", "@polkadot/util-crypto": "^13.5.3", + "@subwallet/extension-base": "^1.3.68-1", "@subwallet/extension-inject": "^1.3.68-1" }, "peerDependencies": { diff --git a/packages/extension-dapp/src/bundle.ts b/packages/extension-dapp/src/bundle.ts index e0ac4b8d9ff..70d0ac33041 100644 --- a/packages/extension-dapp/src/bundle.ts +++ b/packages/extension-dapp/src/bundle.ts @@ -6,8 +6,11 @@ import type { Injected, InjectedAccount, InjectedAccountWithMeta, InjectedExtens import { u8aEq } from '@polkadot/util'; import { decodeAddress, encodeAddress } from '@polkadot/util-crypto'; +import { createLogger } from './logger'; import { documentReadyPromise } from './util'; +const logger = createLogger('ExtensionDapp'); + // expose utility functions export { packageInfo } from './packageInfo'; export { unwrapBytes, wrapBytes } from './wrapBytes'; @@ -52,11 +55,11 @@ export { isWeb3Injected, web3EnablePromise }; function getWindowExtensions (originName: string): Promise<[InjectedExtensionInfo, Injected | void][]> { return Promise.all( Object.entries(win.injectedWeb3).map( - ([name, { enable, version }]): Promise<[InjectedExtensionInfo, Injected | void]> => + ([name, { enable, version }]): Promise<[InjectedExtensionInfo, Injected | void]> => Promise.all([ Promise.resolve({ name, version }), enable(originName).catch((error: Error): void => { - console.error(`Error initializing ${name}: ${error.message}`); + logger.error(`Error initializing ${name}: ${error.message}`); }) ]) ) @@ -84,7 +87,7 @@ export function web3Enable (originName: string, compatInits: (() => Promise void | Promise): Unsubcall => { - ext.accounts.get().then(cb).catch(console.error); + ext.accounts.get().then(cb).catch((error) => logger.error('Failed to get accounts', error)); return (): void => { // no ubsubscribe needed, this is a single-shot @@ -100,7 +103,7 @@ export function web3Enable (originName: string, compatInits: (() => Promise `${name}/${version}`); isWeb3Injected = web3IsInjected(); - console.log(`web3Enable: Enabled ${values.length} extension${values.length !== 1 ? 's' : ''}: ${names.join(', ')}`); + logger.info(`web3Enable: Enabled ${values.length} extension${values.length !== 1 ? 's' : ''}: ${names.join(', ')}`); return values; }) @@ -138,7 +141,7 @@ export async function web3Accounts ({ accountType, ss58Format }: Web3AccountsOpt const addresses = accounts.map(({ address }) => address); - console.log(`web3Accounts: Found ${accounts.length} address${accounts.length !== 1 ? 'es' : ''}: ${addresses.join(', ')}`); + logger.info(`web3Accounts: Found ${accounts.length} address${accounts.length !== 1 ? 'es' : ''}: ${addresses.join(', ')}`); return accounts; } @@ -222,7 +225,7 @@ export async function web3ListRpcProviders (source: string): Promise = (props: Props) => { break; } catch (e) { await new Promise((resolve) => setTimeout(resolve, 3000)); - console.error(e); + logger.error('Error loading ledger addresses', e); if (j === maxRetry - 1) { refresh(); @@ -220,7 +223,7 @@ const Component: React.FC = (props: Props) => { setFirstStep(false); if (!page) { - onLoadMore().catch(console.error); + onLoadMore().catch((error) => logger.error('Failed to load more ledger accounts', error)); } }, [onLoadMore, page]); @@ -299,7 +302,7 @@ const Component: React.FC = (props: Props) => { onComplete(); }) .catch((e: Error) => { - console.log(e); + logger.error('Failed to create hardware accounts', e); }) .finally(() => { setIsSubmitting(false); diff --git a/packages/extension-koni-ui/src/Popup/Account/ImportSeedPhrase.tsx b/packages/extension-koni-ui/src/Popup/Account/ImportSeedPhrase.tsx index 86df790c230..06b2b9ff27a 100644 --- a/packages/extension-koni-ui/src/Popup/Account/ImportSeedPhrase.tsx +++ b/packages/extension-koni-ui/src/Popup/Account/ImportSeedPhrase.tsx @@ -3,6 +3,7 @@ import { NotificationType } from '@subwallet/extension-base/background/KoniTypes'; import { AccountProxyType, ResponseMnemonicValidateV2 } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { AccountNameModal, CloseIcon, Layout, PageWrapper, PhraseNumberSelector, SeedPhraseInput } from '@subwallet/extension-koni-ui/components'; import { ACCOUNT_NAME_MODAL, IMPORT_ACCOUNT_MODAL } from '@subwallet/extension-koni-ui/constants'; import { WalletModalContext } from '@subwallet/extension-koni-ui/contexts/WalletModalContextProvider'; @@ -102,7 +103,7 @@ const Component: React.FC = ({ className }: Props) => { try { form.setFieldValue('phraseNumber', `${words.length}`); } catch (error) { - console.error('Error updating phraseNumber field:', error); + defaultLogger.error('Error updating phraseNumber field', error); } } }, [form]); diff --git a/packages/extension-koni-ui/src/Popup/Account/NewSeedPhrase.tsx b/packages/extension-koni-ui/src/Popup/Account/NewSeedPhrase.tsx index 84735a29f1b..ba3a0182956 100644 --- a/packages/extension-koni-ui/src/Popup/Account/NewSeedPhrase.tsx +++ b/packages/extension-koni-ui/src/Popup/Account/NewSeedPhrase.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { AccountProxyType } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { AccountNameModal, CloseIcon, Layout, PageWrapper, WordPhrase } from '@subwallet/extension-koni-ui/components'; import { SeedPhraseTermModal } from '@subwallet/extension-koni-ui/components/Modal/TermsAndConditions/SeedPhraseTermModal'; import { ACCOUNT_NAME_MODAL, CONFIRM_TERM_SEED_PHRASE, CREATE_ACCOUNT_MODAL, DEFAULT_MNEMONIC_TYPE, DEFAULT_ROUTER_PATH, SEED_PREVENT_MODAL, SELECTED_MNEMONIC_TYPE, TERM_AND_CONDITION_SEED_PHRASE_MODAL } from '@subwallet/extension-koni-ui/constants'; @@ -129,14 +130,14 @@ const Component: React.FC = ({ className }: Props) => { setSeedPhrase(phrase); }) .catch((e: Error) => { - console.error(e); + defaultLogger.error('Failed to create seed', e); }); }, [selectedMnemonicType]); useEffect(() => { if (isPopupMode && isFirefox() && hasMasterPassword && !isOpenWindowRef.current) { isOpenWindowRef.current = true; - windowOpen({ allowedPath: '/accounts/new-seed-phrase' }).then(window.close).catch(console.log); + windowOpen({ allowedPath: '/accounts/new-seed-phrase' }).then(window.close).catch((error) => defaultLogger.debug('Failed to open window', error)); } }, [isPopupMode, hasMasterPassword]); diff --git a/packages/extension-koni-ui/src/Popup/BuyTokens.tsx b/packages/extension-koni-ui/src/Popup/BuyTokens.tsx index cff9955e36f..d7c18b89e57 100644 --- a/packages/extension-koni-ui/src/Popup/BuyTokens.tsx +++ b/packages/extension-koni-ui/src/Popup/BuyTokens.tsx @@ -4,6 +4,7 @@ import { Resolver } from '@subwallet/extension-base/background/types'; import { _getOriginChainOfAsset, _isChainCompatibleLedgerEvm } from '@subwallet/extension-base/services/chain-service/utils'; import { AccountChainType, AccountProxy, AccountSignMode, BuyServiceInfo, BuyTokenInfo, SupportService } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { detectTranslate, isAccountAll, isSubstrateEcdsaLedgerAssetSupported } from '@subwallet/extension-base/utils'; import { AccountAddressSelector, baseServiceItems, Layout, PageWrapper, ServiceItem } from '@subwallet/extension-koni-ui/components'; import { ServiceSelector } from '@subwallet/extension-koni-ui/components/Field/BuyTokens/ServiceSelector'; @@ -334,7 +335,7 @@ function Component ({ className, currentAccountProxy }: ComponentProps) { }) .catch((e: Error) => { if (e.message !== 'User reject') { - console.error(e); + defaultLogger.error('Failed to create buy order', e); notify({ message: t('ui.BUY.screen.BuyTokens.createBuyOrderFail'), diff --git a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Detail/Substrate/Extrinsic.tsx b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Detail/Substrate/Extrinsic.tsx index 67a1e344b47..cd158c1f29b 100644 --- a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Detail/Substrate/Extrinsic.tsx +++ b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Detail/Substrate/Extrinsic.tsx @@ -5,6 +5,7 @@ import type { Chain } from '@subwallet/extension-chains/types'; import type { Call, ExtrinsicEra, ExtrinsicPayload } from '@polkadot/types/interfaces'; import type { AnyJson, SignerPayloadJSON } from '@polkadot/types/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import MetaInfo from '@subwallet/extension-koni-ui/components/MetaInfo/MetaInfo'; import useGetChainInfoByGenesisHash from '@subwallet/extension-koni-ui/hooks/chain/useGetChainInfoByGenesisHash'; import useMetadata from '@subwallet/extension-koni-ui/hooks/transaction/confirmation/useMetadata'; @@ -42,10 +43,10 @@ const decodeMethod = (data: string, chain: Chain, specVersion: BN): Decoded => { method = chain.registry.createType('Call', data); args = (method.toHuman() as { args: AnyJson }).args; } else { - console.log(displayDecodeVersion('Your metadata is out of date', chain, specVersion)); + defaultLogger.warn(displayDecodeVersion('Your metadata is out of date', chain, specVersion)); } } catch (error) { - console.error(`${displayDecodeVersion('Error decoding method', chain, specVersion)}:: ${(error as Error).message}`); + defaultLogger.error(`${displayDecodeVersion('Error decoding method', chain, specVersion)}:: ${(error as Error).message}`); args = null; method = null; @@ -114,7 +115,7 @@ const Component: React.FC = ({ accountName, address, className, payload: [method, chain, specVersion] ); - console.debug('tip', tip); + defaultLogger.debug('tip', tip); return ( diff --git a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Bitcoin.tsx b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Bitcoin.tsx index 5685c93b771..13e72b981d3 100644 --- a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Bitcoin.tsx +++ b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Bitcoin.tsx @@ -4,6 +4,7 @@ import { BitcoinSignPsbtRequest, ConfirmationDefinitionsBitcoin, ConfirmationResult, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import { AccountSignMode } from '@subwallet/extension-base/types'; import { RequestSubmitTransferWithId } from '@subwallet/extension-base/types/balance/transfer'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { wait } from '@subwallet/extension-base/utils'; import { AlertBox } from '@subwallet/extension-koni-ui/components'; import { CONFIRMATION_QR_MODAL } from '@subwallet/extension-koni-ui/constants'; @@ -137,7 +138,7 @@ const Component: React.FC = (props: Props) => { }); }) .catch((error) => { - console.error(error); + defaultLogger.error('Failed to handle confirm', error); notify({ message: t((error as Error).message), type: 'error', @@ -155,7 +156,7 @@ const Component: React.FC = (props: Props) => { setTimeout(() => { handleSignature(type, id, signature.signature) .catch((e) => { - console.log(e); + defaultLogger.debug('Signature error', e); }) .finally(() => { setLoading(false); @@ -196,7 +197,7 @@ const Component: React.FC = (props: Props) => { // }, [account?.accountIndex, account?.addressOffset, hashPayload, isLedgerConnected, isMessage, ledger, ledgerSignMessage, ledgerSignTransaction, onApproveSignature, refreshLedger]); const onConfirmInject = useCallback(() => { - console.error('Not implemented yet'); + defaultLogger.error('Not implemented yet'); // if (evmWallet) { // let promise: Promise<`0x${string}`>; // diff --git a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Evm.tsx b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Evm.tsx index 056582d8b4a..0c0ef9fed78 100644 --- a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Evm.tsx +++ b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Evm.tsx @@ -3,6 +3,7 @@ import { ConfirmationDefinitions, ConfirmationResult, EvmSendTransactionRequest, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import { AccountSignMode } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { AlertBox } from '@subwallet/extension-koni-ui/components'; import { CONFIRMATION_QR_MODAL } from '@subwallet/extension-koni-ui/constants/modal'; import { InjectContext } from '@subwallet/extension-koni-ui/contexts/InjectContext'; @@ -126,7 +127,7 @@ const Component: React.FC = (props: Props) => { setTimeout(() => { handleSignature(type, id, signature.signature) .catch((e) => { - console.log(e); + defaultLogger.debug('Signature error', e); }) .finally(() => { setLoading(false); @@ -161,7 +162,7 @@ const Component: React.FC = (props: Props) => { onApproveSignature({ signature }); }) .catch((e: Error) => { - console.log(e); + defaultLogger.debug('Sign error', e); setLoading(false); }); }); @@ -198,7 +199,7 @@ const Component: React.FC = (props: Props) => { onApproveSignature({ signature }); }) .catch((e) => { - console.error(e); + defaultLogger.error('Failed to sign', e); }) .finally(() => { setLoading(false); diff --git a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Substrate.tsx b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Substrate.tsx index 2458c08e184..5a83c7f6a33 100644 --- a/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Substrate.tsx +++ b/packages/extension-koni-ui/src/Popup/Confirmations/parts/Sign/Substrate.tsx @@ -4,6 +4,7 @@ import { ExtrinsicType, NotificationType, POLKADOT_LEDGER_SCHEME } from '@subwallet/extension-base/background/KoniTypes'; import { RequestSign } from '@subwallet/extension-base/background/types'; import { AccountSignMode } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { _isRuntimeUpdated, detectTranslate } from '@subwallet/extension-base/utils'; import { AlertBox, AlertModal } from '@subwallet/extension-koni-ui/components'; import { CONFIRMATION_QR_MODAL, NotNeedMigrationGens, SUBSTRATE_GENERIC_KEY, SUBSTRATE_MIGRATION_KEY, SubstrateLedgerSignModeSupport } from '@subwallet/extension-koni-ui/constants'; @@ -302,7 +303,7 @@ const Component: React.FC = (props: Props) => { setTimeout(() => { handleConfirm(id) .catch((e) => { - console.log(e); + defaultLogger.debug('Confirm error', e); }) .finally(() => { setLoading(false); @@ -316,7 +317,7 @@ const Component: React.FC = (props: Props) => { setTimeout(() => { handleSignature(id, signature) .catch((e) => { - console.log(e); + defaultLogger.debug('Signature error', e); }) .finally(() => { setLoading(false); @@ -349,7 +350,7 @@ const Component: React.FC = (props: Props) => { onApproveSignature({ signature }); } catch (e) { - console.error(e); + defaultLogger.error('Failed to approve signature', e); } setLoading(false); @@ -394,7 +395,7 @@ const Component: React.FC = (props: Props) => { onApproveSignature({ signature }); } } catch (e) { - console.error(e); + defaultLogger.error('Failed to approve signature', e); } setLoading(false); @@ -432,7 +433,7 @@ const Component: React.FC = (props: Props) => { onApproveSignature({ signature, signedTransaction }); }) .catch((e) => { - console.error(e); + defaultLogger.error('Failed to approve signature', e); }) .finally(() => { setLoading(false); diff --git a/packages/extension-koni-ui/src/Popup/Confirmations/variants/BitcoinSendTransactionRequestConfirmation.tsx b/packages/extension-koni-ui/src/Popup/Confirmations/variants/BitcoinSendTransactionRequestConfirmation.tsx index 668d86ede64..045cb58f489 100644 --- a/packages/extension-koni-ui/src/Popup/Confirmations/variants/BitcoinSendTransactionRequestConfirmation.tsx +++ b/packages/extension-koni-ui/src/Popup/Confirmations/variants/BitcoinSendTransactionRequestConfirmation.tsx @@ -5,6 +5,7 @@ import { _ChainAsset } from '@subwallet/chain-list/types'; import { BitcoinSendTransactionRequest, ConfirmationsQueueItem } from '@subwallet/extension-base/background/KoniTypes'; import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils'; import { ResponseSubscribeTransferConfirmation } from '@subwallet/extension-base/types/balance/transfer'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { BN_ZERO, getDomainFromUrl } from '@subwallet/extension-base/utils'; import { MetaInfo } from '@subwallet/extension-koni-ui/components'; import { useGetAccountByAddress, useNotification } from '@subwallet/extension-koni-ui/hooks'; @@ -20,6 +21,8 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; +const logger = createLogger('BitcoinSendTransactionRequestConfirmation'); + interface Props extends ThemeProps { type: BitcoinSignatureSupportType request: ConfirmationsQueueItem @@ -89,12 +92,12 @@ function Component ({ className, request, type }: Props) { }); setIsErrorTransaction(true); setTransferInfo(transferInfo); - cancelSubscription(transferInfo.id).catch(console.error); + cancelSubscription(transferInfo.id).catch((error) => logger.error('Failed to cancel subscription', error)); } else if (!cancel) { setTransferInfo(transferInfo); id = transferInfo.id; } else { - cancelSubscription(transferInfo.id).catch(console.error); + cancelSubscription(transferInfo.id).catch((error) => logger.error('Failed to cancel subscription', error)); } }; @@ -112,7 +115,7 @@ function Component ({ className, request, type }: Props) { }, callback) .then(callback) .catch((e) => { - console.error(e); + logger.error('Failed to subscribe transfer when confirmation', e); notify({ message: t(e), type: 'error', @@ -123,7 +126,7 @@ function Component ({ className, request, type }: Props) { }) .finally(() => { clearTimeout(timeout); - id && cancelSubscription(id).catch(console.error); + id && cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription', error)); setIsFetchingInfo(false); }); }, 100); @@ -132,7 +135,7 @@ function Component ({ className, request, type }: Props) { return () => { cancel = true; clearTimeout(timeout); - id && cancelSubscription(id).catch(console.error); + id && cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription on cleanup', error)); }; }, [assetRegistry, assetValue, chainValue, fromValue, toValue, transferAmountValue, notify, t]); diff --git a/packages/extension-koni-ui/src/Popup/Confirmations/variants/Message/SignConfirmation.tsx b/packages/extension-koni-ui/src/Popup/Confirmations/variants/Message/SignConfirmation.tsx index 49e4b8eebd2..afba3a3f8b4 100644 --- a/packages/extension-koni-ui/src/Popup/Confirmations/variants/Message/SignConfirmation.tsx +++ b/packages/extension-koni-ui/src/Popup/Confirmations/variants/Message/SignConfirmation.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { SigningRequest } from '@subwallet/extension-base/background/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { AccountItemWithProxyAvatar, ConfirmationGeneralInfo, ViewDetailIcon } from '@subwallet/extension-koni-ui/components'; import { useGetAccountByAddress, useMetadata, useOpenDetailModal, useParseSubstrateRequestPayload } from '@subwallet/extension-koni-ui/hooks'; import { enableChain } from '@subwallet/extension-koni-ui/messaging'; @@ -15,6 +16,8 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; +const logger = createLogger('SignConfirmation'); + import { ExtrinsicPayload } from '@polkadot/types/interfaces'; import { SignerPayloadJSON } from '@polkadot/types/types'; @@ -53,7 +56,7 @@ function Component ({ className, request }: Props) { !chainState.active && enableChain(chainInfo.slug, false) .then(noop) - .catch(console.error); + .catch((error) => logger.error('Failed to enable chain', error)); } }, [chainStateMap, chainInfo, isMessage]); diff --git a/packages/extension-koni-ui/src/Popup/Debugger/DebuggerAPI.tsx b/packages/extension-koni-ui/src/Popup/Debugger/DebuggerAPI.tsx index 52cda293c53..3af89709e06 100644 --- a/packages/extension-koni-ui/src/Popup/Debugger/DebuggerAPI.tsx +++ b/packages/extension-koni-ui/src/Popup/Debugger/DebuggerAPI.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { MessageTypesWithSubscriptions } from '@subwallet/extension-base/background/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { subscribeMessage } from '@subwallet/extension-koni-ui/messaging'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import { Button, Form, Input, Select } from '@subwallet/react-ui'; @@ -227,7 +228,7 @@ const Component = ({ className }: ComponentProps) => { const request = JSON.parse(formValues?.payload || 'null'); const callback = (response: any) => { - console.debug(formValues?.api, response); + defaultLogger.debug(formValues?.api || 'unknown', response); setResponse(JSON.stringify(response, null, 2)); }; @@ -236,7 +237,7 @@ const Component = ({ className }: ComponentProps) => { unsub = subscription.unsub; }).catch((e) => { - console.error(e); + defaultLogger.error('Failed to subscribe message', e); }); }, []); diff --git a/packages/extension-koni-ui/src/Popup/Home/Earning/EarningEntry/EarningPositions/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Earning/EarningEntry/EarningPositions/index.tsx index c60bf11f17e..2be251cff79 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Earning/EarningEntry/EarningPositions/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Earning/EarningEntry/EarningPositions/index.tsx @@ -4,6 +4,7 @@ import { _ChainInfo } from '@subwallet/chain-list/types'; import { NotificationType } from '@subwallet/extension-base/background/KoniTypes'; import { YieldPoolType, YieldPositionInfo } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { detectTranslate, isAccountAll } from '@subwallet/extension-base/utils'; import { AlertModal, EmptyList, FilterModal, Layout } from '@subwallet/extension-koni-ui/components'; import { EarningPositionItem } from '@subwallet/extension-koni-ui/components/Earning'; @@ -24,6 +25,8 @@ import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { useLocalStorage } from 'usehooks-ts'; +const logger = createLogger('EarningPositions'); + type Props = ThemeProps & { earningPositions: YieldPositionInfo[]; setEntryView: React.Dispatch>; @@ -318,7 +321,7 @@ function Component ({ className, earningPositions, setEntryView, setLoading }: P onClick: () => { setLoading(true); reloadCron({ data: 'staking' }) - .catch(console.error).finally(() => { + .catch((error) => logger.error('Failed to reload staking cron', error)).finally(() => { setTimeout(() => { setLoading(false); }, 1000); diff --git a/packages/extension-koni-ui/src/Popup/Home/History/index.tsx b/packages/extension-koni-ui/src/Popup/Home/History/index.tsx index 40ba7a383b6..9aa0ff5dbfc 100644 --- a/packages/extension-koni-ui/src/Popup/Home/History/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/History/index.tsx @@ -4,6 +4,7 @@ import { ExtrinsicStatus, ExtrinsicType, TransactionDirection, TransactionHistoryItem } from '@subwallet/extension-base/background/KoniTypes'; import { YIELD_EXTRINSIC_TYPES } from '@subwallet/extension-base/koni/api/yield/helper/utils'; import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { quickFormatAddressToCompare } from '@subwallet/extension-base/utils'; import { AccountAddressSelector, BasicInputEvent, ChainSelector, EmptyList, FilterModal, HistoryItem, Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { DEFAULT_SESSION_VALUE, HISTORY_DETAIL_MODAL, LATEST_SESSION, REMIND_BACKUP_SEED_PHRASE_MODAL } from '@subwallet/extension-koni-ui/constants'; @@ -19,6 +20,8 @@ import { useTranslation } from 'react-i18next'; import { useParams } from 'react-router-dom'; import styled from 'styled-components'; +const logger = createLogger('History'); + import { HistoryDetailModal } from './Detail'; type Props = ThemeProps @@ -648,17 +651,17 @@ function Component ({ className = '' }: Props): React.ReactElement { if (isSubscribed) { setRawHistoryList(isSelectedChainEvm ? filterDuplicateItems(res.items) : res.items); } else { - cancelSubscription(id).catch(console.log); + cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription', error)); } }).catch((e) => { - console.log('subscribeTransactionHistory error:', e); + logger.error('subscribeTransactionHistory error', e); }); return () => { isSubscribed = false; if (id) { - cancelSubscription(id).catch(console.log); + cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription on cleanup', error)); } }; }, [isSelectedChainEvm, selectedAddress, selectedChain]); diff --git a/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollectionDetail.tsx b/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollectionDetail.tsx index afd64e2a12e..b347429a7c4 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollectionDetail.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollectionDetail.tsx @@ -3,6 +3,7 @@ import { NftCollection, NftItem } from '@subwallet/extension-base/background/KoniTypes'; import { _isCustomAsset, _isSmartContractToken } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EmptyList, Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { SHOW_3D_MODELS_CHAIN } from '@subwallet/extension-koni-ui/constants'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; @@ -23,6 +24,8 @@ import React, { useCallback, useContext, useEffect, useMemo, useState } from 're import { useNavigate, useSearchParams } from 'react-router-dom'; import styled from 'styled-components'; +const logger = createLogger('NftCollectionDetail'); + type Props = ThemeProps const subHeaderRightButton = { }); } }) - .catch(console.log); + .catch((error) => logger.error('Failed to delete custom asset', error)); } - }).catch(console.log); + }).catch((error) => logger.error('Failed to handle delete NFT collection', error)); }, [collectionInfo?.originAsset, goBack, handleSimpleConfirmModal, showNotification, t]); const subHeaderButton: ButtonProps[] = [ @@ -187,7 +190,7 @@ function Component ({ className = '' }: Props): React.ReactElement { setIsFetching(true); getFullNftList({ contractAddress: collectionInfo?.collectionId, owners: ownerAddresses, chainInfo: chainInfo }) - .catch(console.error) + .catch((error) => logger.error('Failed to get full NFT list', error)) .finally(() => { if (isMounted) { setIsFetching(false); diff --git a/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollections.tsx b/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollections.tsx index 5c52270cb35..3bfab4d0fef 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollections.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Nfts/NftCollections.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { NftCollection, NftItem } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { EmptyList, Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import BannerGenerator from '@subwallet/extension-koni-ui/components/StaticContent/BannerGenerator'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; @@ -17,6 +18,8 @@ import React, { useCallback, useContext, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +const logger = createLogger('NftCollections'); + type Props = ThemeProps const reloadIcon = { .then(() => { setLoading(false); }) - .catch(console.error); + .catch((error) => logger.error('Failed to reload NFT cron', error)); } }, { diff --git a/packages/extension-koni-ui/src/Popup/Home/Nfts/NftItemDetail.tsx b/packages/extension-koni-ui/src/Popup/Home/Nfts/NftItemDetail.tsx index e960124a62a..1c982d58f97 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Nfts/NftItemDetail.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Nfts/NftItemDetail.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { getExplorerLink } from '@subwallet/extension-base/services/transaction-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { CAMERA_CONTROLS_MODEL_VIEWER_PROPS, DEFAULT_MODEL_VIEWER_PROPS, DEFAULT_NFT_PARAMS, NFT_TRANSACTION, SHOW_3D_MODELS_CHAIN } from '@subwallet/extension-koni-ui/constants'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; @@ -29,6 +30,8 @@ import { useLocalStorage } from 'usehooks-ts'; import { isEthereumAddress } from '@polkadot/util-crypto'; +const logger = createLogger('NftItemDetail'); + type Props = ThemeProps const NFT_DESCRIPTION_MAX_LENGTH = 70; @@ -140,18 +143,18 @@ function Component ({ className = '' }: Props): React.ReactElement { const handleClickExternalAccountInfo = useCallback(() => { try { // eslint-disable-next-line no-void - void chrome.tabs.create({ url: accountExternalUrl, active: true }).then(() => console.log('redirecting')); + void chrome.tabs.create({ url: accountExternalUrl, active: true }).then(() => logger.info('redirecting to external account info')); } catch (e) { - console.log('error redirecting to a new tab'); + logger.error('error redirecting to a new tab', e); } }, [accountExternalUrl]); const handleClickExternalCollectionInfo = useCallback(() => { try { // eslint-disable-next-line no-void - void chrome.tabs.create({ url: nftItem.externalUrl, active: true }).then(() => console.log('redirecting')); + void chrome.tabs.create({ url: nftItem.externalUrl, active: true }).then(() => logger.info('redirecting to external collection info')); } catch (e) { - console.log('error redirecting to a new tab'); + logger.error('error redirecting to a new tab', e); } }, [nftItem.externalUrl]); @@ -184,8 +187,8 @@ function Component ({ className = '' }: Props): React.ReactElement { const onImageClick = useCallback(() => { if (nftItem.externalUrl) { chrome.tabs.create({ url: nftItem.externalUrl, active: true }) - .then(() => console.log('redirecting')) - .catch(console.error); + .then(() => logger.info('redirecting to external NFT URL')) + .catch((error) => logger.error('Failed to open external NFT URL', error)); } }, [nftItem.externalUrl]); diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx index d138d0987bb..8ce4bd6dea3 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/DetailUpperBlock.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { balanceNoPrefixFormater, formatNumber } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { NumberDisplay } from '@subwallet/extension-koni-ui/components'; import { useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { saveShowBalance } from '@subwallet/extension-koni-ui/messaging'; @@ -16,6 +17,8 @@ import React, { useCallback } from 'react'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; +const logger = createLogger('DetailUpperBlock'); + import { ActionButtonsContainer } from './ActionButtonsContainer'; type Props = ThemeProps & { @@ -53,7 +56,7 @@ function Component ( const { isShowBalance } = useSelector((state: RootState) => state.settings); const { currencyData } = useSelector((state: RootState) => state.price); const onChangeShowBalance = useCallback(() => { - saveShowBalance(!isShowBalance).catch(console.error); + saveShowBalance(!isShowBalance).catch((error) => logger.error('Failed to save show balance setting', error)); }, [isShowBalance]); return ( diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/PriceChartArea/index.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/PriceChartArea/index.tsx index f308ed3f2ea..63d7ac8c35a 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/PriceChartArea/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/PriceChartArea/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { PriceChartPoint, PriceChartTimeframe } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { useSelector } from '@subwallet/extension-koni-ui/hooks'; import { cancelSubscription, getHistoryTokenPrice, subscribeCurrentTokenPrice } from '@subwallet/extension-koni-ui/messaging'; import { RootState } from '@subwallet/extension-koni-ui/stores'; @@ -9,6 +10,8 @@ import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import styled from 'styled-components'; +const logger = createLogger('PriceChartArea'); + import { PriceChart } from './PriceChart'; import { PriceInfoContainer } from './PriceInfoContainer'; import { PriceInfoUI } from './PriceInfoUI'; @@ -113,7 +116,7 @@ const Component: React.FC = (props: ComponentProps) => { } }; - loadPriceHistory().catch(console.error); + loadPriceHistory().catch((error) => logger.error('Failed to load price history', error)); return () => { sync = false; @@ -131,7 +134,7 @@ const Component: React.FC = (props: ComponentProps) => { priceHistoryCacheRef.current[selectedTimeframe] = history; setRawPricePoints(history); } - }).catch(console.error); + }).catch((error) => logger.error('Failed to get history token price', error)); prevCurrencyRef.current = currency; } @@ -157,13 +160,13 @@ const Component: React.FC = (props: ComponentProps) => { if (isSync) { setLivePrice(price); } - }).catch(console.error); + }).catch((error) => logger.error('Failed to subscribe current token price', error)); return () => { isSync = false; if (subscriptionId) { - cancelSubscription(subscriptionId).catch(console.error); + cancelSubscription(subscriptionId).catch((error) => logger.error('Failed to cancel subscription', error)); } }; }, [priceId]); diff --git a/packages/extension-koni-ui/src/Popup/Home/Tokens/UpperBlock.tsx b/packages/extension-koni-ui/src/Popup/Home/Tokens/UpperBlock.tsx index ba627980180..f070a9aff70 100644 --- a/packages/extension-koni-ui/src/Popup/Home/Tokens/UpperBlock.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/Tokens/UpperBlock.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { balanceNoPrefixFormater } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { useSelector, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { reloadCron, saveShowBalance } from '@subwallet/extension-koni-ui/messaging'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; @@ -11,6 +12,8 @@ import { ArrowsClockwise, ArrowsLeftRight, CopySimple, Eye, EyeSlash, PaperPlane import React, { useCallback, useState } from 'react'; import styled from 'styled-components'; +const logger = createLogger('UpperBlock'); + import { ActionButtonsContainer } from './ActionButtonsContainer'; type Props = ThemeProps & { @@ -46,13 +49,13 @@ function Component ( const { currencyData } = useSelector((state) => state.price); const onChangeShowBalance = useCallback(() => { - saveShowBalance(!isShowBalance).catch(console.error); + saveShowBalance(!isShowBalance).catch((error) => logger.error('Failed to save show balance setting', error)); }, [isShowBalance]); const reloadBalance = useCallback(() => { setReloading(true); reloadCron({ data: 'balance' }) - .catch(console.error) + .catch((error) => logger.error('Failed to reload balance cron', error)) .finally(() => { setReloading(false); }); diff --git a/packages/extension-koni-ui/src/Popup/Home/index.tsx b/packages/extension-koni-ui/src/Popup/Home/index.tsx index 46777217a1a..69abab69643 100644 --- a/packages/extension-koni-ui/src/Popup/Home/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Home/index.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Layout } from '@subwallet/extension-koni-ui/components'; import { GlobalSearchTokenModal } from '@subwallet/extension-koni-ui/components/Modal/GlobalSearchTokenModal'; import RemindUpgradeFirefoxVersion from '@subwallet/extension-koni-ui/components/Modal/RemindUpgradeFirefoxVersion'; @@ -18,6 +19,8 @@ import { useLocation } from 'react-router-dom'; import styled from 'styled-components'; import { useLocalStorage } from 'usehooks-ts'; +const logger = createLogger('Home'); + type Props = ThemeProps; export const GlobalSearchTokenModalId = 'globalSearchToken'; @@ -73,7 +76,7 @@ function Component ({ className = '' }: Props): React.ReactElement { handleOpenBanner(); } }) - .catch(console.error); + .catch((error) => logger.error('Failed to handle campaign banner', error)); } else { handleOpenBanner(); } diff --git a/packages/extension-koni-ui/src/Popup/MigrateAccount/BriefView/index.tsx b/packages/extension-koni-ui/src/Popup/MigrateAccount/BriefView/index.tsx index 4dc6b387cf9..4ea7ab82f65 100644 --- a/packages/extension-koni-ui/src/Popup/MigrateAccount/BriefView/index.tsx +++ b/packages/extension-koni-ui/src/Popup/MigrateAccount/BriefView/index.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { LoadingScreen } from '@subwallet/extension-koni-ui/components'; import ContentGenerator from '@subwallet/extension-koni-ui/components/StaticContent/ContentGenerator'; import { useFetchMarkdownContentData } from '@subwallet/extension-koni-ui/hooks'; @@ -46,7 +47,7 @@ function Component ({ className = '', isForcedMigration, onDismiss, onMigrateNow setIsFetchingBriefContent(false); } }) - .catch((e) => console.log('fetch unified_account_migration_content error:', e)); + .catch((e) => defaultLogger.error('fetch unified_account_migration_content error', e)); } return () => { diff --git a/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/ProcessViewItem.tsx b/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/ProcessViewItem.tsx index 99bea533450..1da8bc19881 100644 --- a/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/ProcessViewItem.tsx +++ b/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/ProcessViewItem.tsx @@ -3,6 +3,7 @@ import { SoloAccountToBeMigrated } from '@subwallet/extension-base/background/KoniTypes'; import { AccountProxyType, SUPPORTED_ACCOUNT_CHAIN_TYPES } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { AccountChainTypeLogos, AccountProxyTypeTag } from '@subwallet/extension-koni-ui/components'; import { useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { validateAccountName } from '@subwallet/extension-koni-ui/messaging'; @@ -16,6 +17,8 @@ import { Callbacks, FieldData, RuleObject } from 'rc-field-form/lib/interface'; import React, { useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; +const logger = createLogger('ProcessViewItem'); + type Props = ThemeProps & { currentProcessOrdinal: number; totalProcessSteps: number; @@ -48,7 +51,7 @@ function Component ({ className = '', currentProcessOrdinal, currentSoloAccountT const { name } = form.getFieldsValue(); onApprove(currentSoloAccountToBeMigratedGroup, name.trim()) - .catch(console.error) + .catch((error) => logger.error('Failed to approve solo account migration', error)) .finally(() => { setLoading(false); }); diff --git a/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/index.tsx b/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/index.tsx index a3845c6f23d..59af7057137 100644 --- a/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/index.tsx +++ b/packages/extension-koni-ui/src/Popup/MigrateAccount/SoloAccountMigrationView/index.tsx @@ -3,11 +3,14 @@ import { RequestMigrateSoloAccount, SoloAccountToBeMigrated } from '@subwallet/extension-base/background/KoniTypes'; import { SESSION_TIMEOUT } from '@subwallet/extension-base/services/keyring-service/context/handlers/Migration'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { pingSession } from '@subwallet/extension-koni-ui/messaging/migrate-unified-account'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; import React, { useCallback, useEffect, useState } from 'react'; import styled from 'styled-components'; +const logger = createLogger('SoloAccountMigrationView'); + import { ProcessViewItem } from './ProcessViewItem'; type Props = ThemeProps & { @@ -71,7 +74,7 @@ function Component ({ onApprove, onCompleteMigrationProcess, sessionId, soloAcco if (sessionId) { const doPing = () => { - pingSession({ sessionId }).catch(console.error); + pingSession({ sessionId }).catch((error) => logger.error('Failed to ping session', error)); }; timer = setInterval(() => { diff --git a/packages/extension-koni-ui/src/Popup/MigrateAccount/SummaryView/index.tsx b/packages/extension-koni-ui/src/Popup/MigrateAccount/SummaryView/index.tsx index 746b9e86a5d..c8941373adb 100644 --- a/packages/extension-koni-ui/src/Popup/MigrateAccount/SummaryView/index.tsx +++ b/packages/extension-koni-ui/src/Popup/MigrateAccount/SummaryView/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { detectTranslate } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { pingUnifiedAccountMigrationDone } from '@subwallet/extension-koni-ui/messaging'; import { ResultAccountProxyItem, ResultAccountProxyItemType } from '@subwallet/extension-koni-ui/Popup/MigrateAccount/SummaryView/ResultAccountProxyItem'; @@ -16,6 +17,8 @@ import { Trans } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled from 'styled-components'; +const logger = createLogger('SummaryView'); + type Props = ThemeProps & { resultProxyIds: string[]; onClickFinish: VoidFunction; @@ -68,7 +71,7 @@ function Component ({ className = '', onClickFinish, resultProxyIds }: Props) { useEffect(() => { // notice to background that account migration is done - pingUnifiedAccountMigrationDone().catch(console.error); + pingUnifiedAccountMigrationDone().catch((error) => logger.error('Failed to ping unified account migration done', error)); }, []); return ( diff --git a/packages/extension-koni-ui/src/Popup/MigrateAccount/index.tsx b/packages/extension-koni-ui/src/Popup/MigrateAccount/index.tsx index ce300c454f8..32198ede8d5 100644 --- a/packages/extension-koni-ui/src/Popup/MigrateAccount/index.tsx +++ b/packages/extension-koni-ui/src/Popup/MigrateAccount/index.tsx @@ -3,6 +3,7 @@ import { RequestMigrateSoloAccount, SoloAccountToBeMigrated } from '@subwallet/extension-base/background/KoniTypes'; import { hasAnyAccountForMigration } from '@subwallet/extension-base/services/keyring-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { useDefaultNavigate, useExtensionDisplayModes } from '@subwallet/extension-koni-ui/hooks'; import { saveMigrationAcknowledgedStatus } from '@subwallet/extension-koni-ui/messaging'; import { migrateSoloAccount, migrateUnifiedAndFetchEligibleSoloAccounts } from '@subwallet/extension-koni-ui/messaging/migrate-unified-account'; @@ -15,6 +16,8 @@ import { useSelector } from 'react-redux'; import { useNavigate, useSearchParams } from 'react-router-dom'; import styled from 'styled-components'; +const logger = createLogger('MigrateAccount'); + import { EnterPasswordModal, enterPasswordModalId } from './EnterPasswordModal'; import { SoloAccountMigrationView } from './SoloAccountMigrationView'; import { SummaryView } from './SummaryView'; @@ -57,7 +60,7 @@ function Component ({ className = '' }: Props) { const onInteractAction = useCallback(() => { if (isMigrationNotion && !isAcknowledgedUnifiedAccountMigration) { // flag that user acknowledge the migration - saveMigrationAcknowledgedStatus({ isAcknowledgedUnifiedAccountMigration: true }).catch(console.error); + saveMigrationAcknowledgedStatus({ isAcknowledgedUnifiedAccountMigration: true }).catch((error) => logger.error('Failed to save migration acknowledged status', error)); } // for now, do nothing @@ -108,7 +111,7 @@ function Component ({ className = '' }: Props) { return [...prev, migratedUnifiedAccountId]; }); } catch (e) { - console.log('onApproveSoloAccountMigration error:', e); + logger.error('onApproveSoloAccountMigration error', e); } }, []); diff --git a/packages/extension-koni-ui/src/Popup/RemindExportAccount.tsx b/packages/extension-koni-ui/src/Popup/RemindExportAccount.tsx index ae885f1607c..df4af1fc265 100644 --- a/packages/extension-koni-ui/src/Popup/RemindExportAccount.tsx +++ b/packages/extension-koni-ui/src/Popup/RemindExportAccount.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Layout } from '@subwallet/extension-koni-ui/components'; import { USER_GUIDE_URL } from '@subwallet/extension-koni-ui/constants'; import { setValueLocalStorageWS } from '@subwallet/extension-koni-ui/messaging'; @@ -12,6 +13,8 @@ import React, { useCallback, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('RemindExportAccount'); + type Props = ThemeProps; const SUB_DOMAIN_USER_GUIDE = 'account-management/export-and-backup-accounts#export-all-accounts'; @@ -27,12 +30,12 @@ const Component: React.FC = (props: Props) => { const learnMore = useCallback(() => { window.open(`${USER_GUIDE_URL}/${SUB_DOMAIN_USER_GUIDE}`); setValueLocalStorageWS(valueStorage) - .catch(console.error); + .catch((error) => logger.error('Failed to set local storage value', error)); }, []); const dismiss = useCallback(() => { setValueLocalStorageWS(valueStorage) - .catch(console.error); + .catch((error) => logger.error('Failed to set local storage value', error)); window.close(); }, []); diff --git a/packages/extension-koni-ui/src/Popup/Root.tsx b/packages/extension-koni-ui/src/Popup/Root.tsx index 1095d15fc56..6587478def6 100644 --- a/packages/extension-koni-ui/src/Popup/Root.tsx +++ b/packages/extension-koni-ui/src/Popup/Root.tsx @@ -3,6 +3,7 @@ import { WalletUnlockType } from '@subwallet/extension-base/background/KoniTypes'; import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isSameAddress } from '@subwallet/extension-base/utils'; import { Logo2D } from '@subwallet/extension-koni-ui/components/Logo'; import { CURRENT_PAGE, TRANSACTION_STORAGES } from '@subwallet/extension-koni-ui/constants'; @@ -22,6 +23,8 @@ import { useSelector } from 'react-redux'; import { Outlet, useLocation, useNavigate } from 'react-router-dom'; import { useLocalStorage } from 'usehooks-ts'; +const logger = createLogger('Root'); + import { MainWrapper } from './MainWrapper'; changeHeaderLogo(); @@ -198,7 +201,7 @@ function DefaultRoute ({ children }: { children: React.ReactNode }): React.React useEffect(() => { initDataRef.current.then(() => { setDataLoaded(true); - }).catch(console.error); + }).catch((error) => logger.error('Failed to initialize data', error)); }, []); useEffect(() => { @@ -221,7 +224,7 @@ function DefaultRoute ({ children }: { children: React.ReactNode }): React.React lastNotifyTime = id; } }); - }).catch(console.error); + }).catch((error) => logger.error('Failed to subscribe notifications', error)); return () => { cancel = true; diff --git a/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainDetail.tsx b/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainDetail.tsx index 09099062e16..64897dc29d5 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainDetail.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainDetail.tsx @@ -3,6 +3,7 @@ import { _NetworkUpsertParams } from '@subwallet/extension-base/services/chain-service/types'; import { _getBlockExplorerFromChain, _getChainNativeTokenBasicInfo, _getChainSubstrateAddressPrefix, _getCrowdloanUrlFromChain, _getEvmChainId, _getSubstrateParaId, _isChainBitcoinCompatible, _isChainCardanoCompatible, _isChainEvmCompatible, _isChainSubstrateCompatible, _isChainTonCompatible, _isCustomChain, _isPureEvmChain, _isPureSubstrateChain } from '@subwallet/extension-base/services/chain-service/utils'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { isUrl } from '@subwallet/extension-base/utils'; import { Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { ProviderSelector } from '@subwallet/extension-koni-ui/components/Field/ProviderSelector'; @@ -111,7 +112,7 @@ function Component ({ className = '' }: Props): React.ReactElement { setIsDeleting(false); }); }) - .catch(console.log); + .catch((error) => defaultLogger.debug('Failed to remove chain', error)); }, [chainInfo.slug, handleSimpleConfirmModal, navigate, showNotification, t]); const chainTypeString = useCallback(() => { diff --git a/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainImport.tsx b/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainImport.tsx index 945c0081491..b9e25629c88 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainImport.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Chains/ChainImport.tsx @@ -4,6 +4,7 @@ import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types'; import { _NetworkUpsertParams } from '@subwallet/extension-base/services/chain-service/types'; import { _generateCustomProviderKey } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isUrl } from '@subwallet/extension-base/utils'; import { Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import InfoIcon from '@subwallet/extension-koni-ui/components/Icon/InfoIcon'; @@ -21,6 +22,8 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('ChainImport'); + type Props = ThemeProps interface ChainImportForm { @@ -73,7 +76,7 @@ function Component ({ className = '' }: Props): React.ReactElement { const [existentialDeposit, setExistentialDeposit] = useState('0'); const handleClickSubheaderButton = useCallback(() => { - console.log('click subheader'); + logger.debug('click subheader'); }, []); const onBack = useCallback(() => { @@ -310,7 +313,7 @@ function Component ({ className = '' }: Props): React.ReactElement { }, 300); } } - }).catch(console.error); + }).catch((error) => logger.error('Failed to fetch chain info', error)); } }, [form, location]); diff --git a/packages/extension-koni-ui/src/Popup/Settings/GeneralSetting.tsx b/packages/extension-koni-ui/src/Popup/Settings/GeneralSetting.tsx index 0ad86102f6f..45dd604e952 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/GeneralSetting.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/GeneralSetting.tsx @@ -3,6 +3,7 @@ import { BrowserConfirmationType, CurrencyJson, CurrencyType, LanguageType, ThemeNames } from '@subwallet/extension-base/background/KoniTypes'; import { ENABLE_LANGUAGES, languageOptions } from '@subwallet/extension-base/constants/i18n'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { staticData, StaticKey } from '@subwallet/extension-base/utils/staticData'; import DefaultLogosMap from '@subwallet/extension-koni-ui/assets/logo'; import { GeneralEmptyList, Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; @@ -268,7 +269,7 @@ function Component ({ className = '' }: Props): React.ReactElement { })); saveBrowserConfirmationType(value as BrowserConfirmationType) .catch((e) => { - console.log('saveBrowserConfirmationType error', e); + defaultLogger.error('saveBrowserConfirmationType error', e); }) .finally(() => { setLoadingMap((prev) => ({ diff --git a/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx b/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx index 1dddf2541f9..975b4e44ebb 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Notifications/Notification.tsx @@ -7,6 +7,7 @@ import { ALL_ACCOUNT_KEY } from '@subwallet/extension-base/constants'; import { isClaimedPosBridge } from '@subwallet/extension-base/services/balance-service/transfer/xcm/posBridge'; import { _NotificationInfo, BridgeTransactionStatus, ClaimAvailBridgeNotificationMetadata, ClaimPolygonBridgeNotificationMetadata, NotificationActionType, NotificationSetup, NotificationTab, ProcessNotificationMetadata, WithdrawClaimNotificationMetadata } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; import { GetNotificationParams, RequestSwitchStatusParams } from '@subwallet/extension-base/types/notification'; +import { createLogger, defaultLogger } from '@subwallet/extension-base/utils/logger'; import { detectTranslate } from '@subwallet/extension-base/utils'; import { AlertModal, EmptyList, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { FilterTabItemType, FilterTabs } from '@subwallet/extension-koni-ui/components/FilterTabs'; @@ -33,6 +34,8 @@ import { useTranslation } from 'react-i18next'; import { useLocation, useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('Notification'); + type Props = ThemeProps; export interface NotificationInfoItem extends _NotificationInfo { @@ -170,7 +173,7 @@ function Component ({ className = '' }: Props): React.ReactElement { setLoadingNotification(true); saveNotificationSetup(newNotificationSetup) - .catch(console.error) + .catch((error) => logger.error('Failed to save notification setup', error)) .finally(() => { setLoadingNotification(false); }); @@ -196,7 +199,7 @@ function Component ({ className = '' }: Props): React.ReactElement { setNotifications(rs); setTimeout(() => setLoading(false), 300); }) - .catch(console.error); + .catch((error) => logger.error('Failed to fetch notifications', error)); }, [currentProxyId]); const onClickMore = useCallback((item: NotificationInfoItem) => { @@ -316,7 +319,7 @@ function Component ({ className = '' }: Props): React.ReactElement { }); switchReadNotificationStatus(switchStatusParams).then(() => { navigate('/transaction/withdraw'); - }).catch(console.error); + }).catch((error) => logger.error('Failed to switch read notification status', error)); } else { showWarningModal('withdrawn'); } @@ -338,7 +341,7 @@ function Component ({ className = '' }: Props): React.ReactElement { }); switchReadNotificationStatus(switchStatusParams).then(() => { navigate('/transaction/claim-reward'); - }).catch(console.error); + }).catch((error) => defaultLogger.error('Failed to switch read notification status', error)); } else { if (chainStateMap[chainSlug]?.active) { showWarningModal('claimed'); @@ -381,12 +384,12 @@ function Component ({ className = '' }: Props): React.ReactElement { showWarningModal('claimed'); } } catch (error) { - console.error(error); + logger.error('Error claiming polygon bridge', error); } }; handleClaimPolygonBridge().catch((err) => { - console.error('Error:', err); + logger.error('Error claiming polygon bridge', err); }); break; } @@ -407,7 +410,7 @@ function Component ({ className = '' }: Props): React.ReactElement { }); switchReadNotificationStatus(switchStatusParams).then(() => { navigate('/transaction/claim-bridge'); - }).catch(console.error); + }).catch((error) => logger.error('Failed to switch read notification status', error)); } else { showWarningModal('claimed'); } @@ -429,7 +432,7 @@ function Component ({ className = '' }: Props): React.ReactElement { if (!item.isRead) { switchReadNotificationStatus(item) - .catch(console.error) + .catch((error) => defaultLogger.error('Failed to switch read notification status', error)) .finally(() => { setTrigger(!isTrigger); }); @@ -494,7 +497,7 @@ function Component ({ className = '' }: Props): React.ReactElement { const handleSwitchClick = useCallback(() => { markAllReadNotification(currentProxyId || ALL_ACCOUNT_KEY) - .catch(console.error); + .catch((error) => logger.error('Failed to mark all notifications as read', error)); setLoading(true); fetchInappNotifications({ @@ -505,7 +508,7 @@ function Component ({ className = '' }: Props): React.ReactElement { setNotifications(rs); setTimeout(() => setLoading(false), 300); }) - .catch(console.error); + .catch((error) => logger.error('Failed to fetch notifications', error)); }, [currentProxyId, selectedFilterTab]); useEffect(() => { @@ -516,7 +519,7 @@ function Component ({ className = '' }: Props): React.ReactElement { .then((rs) => { setNotifications(rs); }) - .catch(console.error); + .catch((error) => logger.error('Failed to fetch notifications', error)); }, [currentProxyId, isAllAccount, isTrigger]); useEffect(() => { diff --git a/packages/extension-koni-ui/src/Popup/Settings/Notifications/NotificationSetting.tsx b/packages/extension-koni-ui/src/Popup/Settings/Notifications/NotificationSetting.tsx index 8b6e47cf742..1649de838cb 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Notifications/NotificationSetting.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Notifications/NotificationSetting.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { NotificationSetup } from '@subwallet/extension-base/services/inapp-notification-service/interfaces'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { PageWrapper } from '@subwallet/extension-koni-ui/components'; import { useDefaultNavigate } from '@subwallet/extension-koni-ui/hooks'; import { saveNotificationSetup } from '@subwallet/extension-koni-ui/messaging'; @@ -16,6 +17,8 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('NotificationSetting'); + type Props = ThemeProps; // interface ViewOption { @@ -80,7 +83,7 @@ const Component = ({ className = '' }: Props): React.ReactElement => { return () => { setLoadingNotification(true); saveNotificationSetup(setup) - .catch(console.error) + .catch((error) => logger.error('Failed to save notification setup', error)) .finally(() => { setLoadingNotification(false); goBack(); diff --git a/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/Detail.tsx b/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/Detail.tsx index 8d0ca920eab..fc8a2416e81 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/Detail.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/Detail.tsx @@ -4,6 +4,7 @@ import { AccountAuthType } from '@subwallet/extension-base/background/types'; import { AuthUrlInfo } from '@subwallet/extension-base/services/request-service/types'; import { AccountChainType, AccountJson, AccountProxy, AccountSignMode } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { AccountProxyItem, DAppConfigurationModal, EmptyList, Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { DAPP_CONFIGURATION_MODAL } from '@subwallet/extension-koni-ui/constants'; import useDefaultNavigate from '@subwallet/extension-koni-ui/hooks/router/useDefaultNavigate'; @@ -97,7 +98,7 @@ function Component ({ accountAuthTypes, authInfo, className = '', goBack, origin }); changeAuthorizationPerSite({ values: newAllowedMap, id: authInfo.id }) - .catch(console.log) + .catch((error) => defaultLogger.debug('Failed to change authorization per site', error)) .finally(() => { setPendingMap((prevMap) => { const newMap = { ...prevMap }; diff --git a/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/index.tsx b/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/index.tsx index 6e8eeb29588..68e967b03e2 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Security/ManageWebsiteAccess/index.tsx @@ -3,6 +3,7 @@ import { AuthUrlInfo } from '@subwallet/extension-base/services/request-service/types'; import { AccountProxy } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ActionItemType, ActionModal, EmptyList, FilterModal, PageWrapper, WebsiteAccessItem } from '@subwallet/extension-koni-ui/components'; import { useDefaultNavigate, useFilterModal } from '@subwallet/extension-koni-ui/hooks'; import { changeAuthorizationAll, forgetAllSite } from '@subwallet/extension-koni-ui/messaging'; @@ -20,6 +21,8 @@ import styled, { useTheme } from 'styled-components'; import { isEthereumAddress } from '@polkadot/util-crypto'; +const logger = createLogger('ManageWebsiteAccess'); + type Props = ThemeProps; function getWebsiteItems (authUrlMap: Record): AuthUrlInfo[] { @@ -150,7 +153,7 @@ function Component ({ className = '' }: Props): React.ReactElement { iconBackgroundColor: token.colorWarning, title: t('ui.SETTINGS.screen.Setting.Security.ManageWebsiteAccess.forgetAll'), onClick: () => { - forgetAllSite(updateAuthUrls).catch(console.error); + forgetAllSite(updateAuthUrls).catch((error) => logger.error('Failed to forget all sites', error)); onCloseActionModal(); } }, @@ -160,7 +163,7 @@ function Component ({ className = '' }: Props): React.ReactElement { iconBackgroundColor: token['gray-3'], title: t('ui.SETTINGS.screen.Setting.Security.ManageWebsiteAccess.disconnectAll'), onClick: () => { - changeAuthorizationAll(false, updateAuthUrls).catch(console.error); + changeAuthorizationAll(false, updateAuthUrls).catch((error) => logger.error('Failed to disconnect all', error)); onCloseActionModal(); } }, @@ -170,7 +173,7 @@ function Component ({ className = '' }: Props): React.ReactElement { iconBackgroundColor: token['green-6'], title: t('ui.SETTINGS.screen.Setting.Security.ManageWebsiteAccess.connectAll'), onClick: () => { - changeAuthorizationAll(true, updateAuthUrls).catch(console.error); + changeAuthorizationAll(true, updateAuthUrls).catch((error) => logger.error('Failed to connect all', error)); onCloseActionModal(); } } diff --git a/packages/extension-koni-ui/src/Popup/Settings/Security/index.tsx b/packages/extension-koni-ui/src/Popup/Settings/Security/index.tsx index 62a232c0c59..e4a27651f18 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Security/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Security/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { WalletUnlockType } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { EDIT_AUTO_LOCK_TIME_MODAL, EDIT_UNLOCK_TYPE_MODAL } from '@subwallet/extension-koni-ui/constants'; import { DEFAULT_ROUTER_PATH } from '@subwallet/extension-koni-ui/constants/router'; @@ -21,6 +22,8 @@ import { useSelector } from 'react-redux'; import { useLocation, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; +const logger = createLogger('Security'); + type Props = ThemeProps; enum SecurityType { @@ -145,13 +148,13 @@ const Component: React.FC = (props: Props) => { if (openNewTab) { windowOpen({ allowedPath: '/settings/security' }) .catch((e: Error) => { - console.log(e); + logger.error('Failed to open window', e); }); isSidePanelMode && closeSidePanel(); } }) - .catch(console.error) + .catch((error) => logger.error('Failed to save camera setting', error)) .finally(() => { setLoadingCamera(false); }); @@ -163,7 +166,7 @@ const Component: React.FC = (props: Props) => { setLoadingSignOnce(true); saveAllowOneSign(!currentValue) - .catch(console.error) + .catch((error) => logger.error('Failed to save allow one sign setting', error)) .finally(() => { setLoadingSignOnce(false); }); @@ -175,7 +178,7 @@ const Component: React.FC = (props: Props) => { setLoadingChainPatrol(true); saveEnableChainPatrol(!currentValue) - .catch(console.error) + .catch((error) => logger.error('Failed to save enable chain patrol setting', error)) .finally(() => { setLoadingChainPatrol(false); }); @@ -267,10 +270,10 @@ const Component: React.FC = (props: Props) => { .then((stream) => { // Close video stream.getTracks().forEach((track) => { - track.stop(); - }); - }) - .catch(console.error); + track.stop(); + }); + }) + .catch((error) => logger.error('Failed to get user media', error)); } }, [camera]); diff --git a/packages/extension-koni-ui/src/Popup/Settings/Tokens/TokenDetail.tsx b/packages/extension-koni-ui/src/Popup/Settings/Tokens/TokenDetail.tsx index fac93324e17..e566c41c5a6 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/Tokens/TokenDetail.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/Tokens/TokenDetail.tsx @@ -3,6 +3,7 @@ import { _ChainAsset } from '@subwallet/chain-list/types'; import { _getContractAddressOfToken, _isAssetHubToken, _isCustomAsset, _isSmartContractToken } from '@subwallet/extension-base/services/chain-service/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { Layout, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; import useNotification from '@subwallet/extension-koni-ui/hooks/common/useNotification'; @@ -22,6 +23,8 @@ import styled, { useTheme } from 'styled-components'; import { isEthereumAddress } from '@polkadot/util-crypto'; +const logger = createLogger('TokenDetail'); + type WrapperProps = ThemeProps; type ComponentProps = { @@ -69,7 +72,7 @@ function Component ({ tokenInfo }: ComponentProps): React.ReactElement logger.error('Failed to handle delete token', error)); }, [goBack, handleSimpleConfirmModal, showNotification, t, tokenInfo.slug]); const subHeaderButton: ButtonProps[] = useMemo(() => { @@ -112,7 +115,7 @@ function Component ({ tokenInfo }: ComponentProps): React.ReactElement { const contractAddress = _getContractAddressOfToken(tokenInfo); - navigator.clipboard.writeText(contractAddress).then().catch(console.error); + navigator.clipboard.writeText(contractAddress).then().catch((error) => logger.error('Failed to copy contract address to clipboard', error)); showNotification({ message: t('ui.SETTINGS.screen.Setting.Tokens.TokenDetail.copiedToClipboard') @@ -343,7 +346,7 @@ const Wrapper: React.FC = (props: WrapperProps) => { if (sync && !tokenInfo) { goBack(); } - }).catch(console.error); + }).catch((error) => logger.error('Failed to load token info', error)); return () => { sync = false; diff --git a/packages/extension-koni-ui/src/Popup/Settings/index.tsx b/packages/extension-koni-ui/src/Popup/Settings/index.tsx index 57f01804d3e..649a1d02ba5 100644 --- a/packages/extension-koni-ui/src/Popup/Settings/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Settings/index.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +// Logger removed - unused import DefaultLogosMap from '@subwallet/extension-koni-ui/assets/logo'; import { PageWrapper, WalletConnect } from '@subwallet/extension-koni-ui/components'; import { CONTACT_SUPPORT_URL, EXTENSION_VERSION, SUPPORT_MAIL, TERMS_OF_SERVICE_URL, TWITTER_URL, WEBSITE_URL, WIKI_URL } from '@subwallet/extension-koni-ui/constants/common'; @@ -19,6 +20,7 @@ import React, { useCallback, useContext, useMemo, useState } from 'react'; import { Outlet, useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; + type Props = ThemeProps type SettingItemType = { diff --git a/packages/extension-koni-ui/src/Popup/Transaction/helper/staking/stakingHandler.ts b/packages/extension-koni-ui/src/Popup/Transaction/helper/staking/stakingHandler.ts index 3c31e4c625e..2cf757c6c10 100644 --- a/packages/extension-koni-ui/src/Popup/Transaction/helper/staking/stakingHandler.ts +++ b/packages/extension-koni-ui/src/Popup/Transaction/helper/staking/stakingHandler.ts @@ -4,6 +4,7 @@ import { StakingType } from '@subwallet/extension-base/background/KoniTypes'; import { _STAKING_CHAIN_GROUP } from '@subwallet/extension-base/services/earning-service/constants'; import { UnstakingStatus } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ALL_KEY } from '@subwallet/extension-koni-ui/constants/common'; import { getBondingOptions, getNominationPoolOptions } from '@subwallet/extension-koni-ui/messaging'; import { store } from '@subwallet/extension-koni-ui/stores'; @@ -11,6 +12,8 @@ import { store } from '@subwallet/extension-koni-ui/stores'; import humanizeDuration from 'humanize-duration'; import { TFunction } from 'react-i18next'; +const logger = createLogger('StakingHandler'); + export function getUnstakingPeriod (t: TFunction, unstakingPeriod?: number) { if (unstakingPeriod) { const days = unstakingPeriod / 24; @@ -61,7 +64,7 @@ const fetchChainValidator = (chain: string, unmount: boolean, setValidatorLoadin .then((result) => { store.dispatch({ type: 'bonding/updateChainValidators', payload: { chain, validators: result } }); }) - .catch(console.error) + .catch((error) => logger.error('Failed to fetch chain validators', error)) .finally(() => { if (!unmount) { setValidatorLoading(false); @@ -78,7 +81,7 @@ const fetchChainPool = (chain: string, unmount: boolean, setPoolLoading: (value: .then((result) => { store.dispatch({ type: 'bonding/updateNominationPools', payload: { chain, pools: result } }); }) - .catch(console.error) + .catch((error) => logger.error('Failed to fetch nomination pools', error)) .finally(() => { if (!unmount) { setPoolLoading(false); diff --git a/packages/extension-koni-ui/src/Popup/Transaction/variants/Earn.tsx b/packages/extension-koni-ui/src/Popup/Transaction/variants/Earn.tsx index 97212b141ab..f4ce6d6c985 100644 --- a/packages/extension-koni-ui/src/Popup/Transaction/variants/Earn.tsx +++ b/packages/extension-koni-ui/src/Popup/Transaction/variants/Earn.tsx @@ -8,6 +8,7 @@ import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/se import { isLendingPool, isLiquidPool } from '@subwallet/extension-base/services/earning-service/utils'; import { SWTransactionResponse } from '@subwallet/extension-base/services/transaction-service/types'; import { BalanceType, NominationPoolInfo, OptimalYieldPath, OptimalYieldPathParams, ProcessType, SlippageType, SubmitJoinNativeStaking, SubmitJoinNominationPool, SubmitYieldJoinData, ValidatorInfo, YieldPoolType, YieldStepType } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { addLazy } from '@subwallet/extension-base/utils'; import { getId } from '@subwallet/extension-base/utils/getId'; import { AccountAddressSelector, AlertBox, AmountInput, EarningPoolSelector, EarningValidatorSelector, HiddenInput, InfoIcon, LoadingScreen, MetaInfo } from '@subwallet/extension-koni-ui/components'; @@ -28,6 +29,8 @@ import { convertFieldToObject, getExtrinsicTypeByPoolInfo, parseNominations, ref import { ActivityIndicator, Button, ButtonProps, Form, Icon, Logo, ModalContext, Number, Tooltip } from '@subwallet/react-ui'; import BigN from 'bignumber.js'; import CN from 'classnames'; + +const logger = createLogger('Earn'); import { CheckCircle, Info, PencilSimpleLine, PlusCircle } from 'phosphor-react'; import React, { useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -125,7 +128,7 @@ const Component = () => { params: { 'transaction-process-id': transactionProcessId } - }).then(window.close).catch(console.log); + }).then(window.close).catch((error) => logger.error('Failed to open window', error)); isSidePanelMode && closeSidePanel(); } else { @@ -1082,7 +1085,7 @@ const Component = () => { setConnectionError(errorNetwork); }) - .catch(console.error) + .catch((error) => logger.error('Failed to validate yield process', error)) .finally(() => setStepLoading(false)); }, 1000, @@ -1124,7 +1127,7 @@ const Component = () => { store.dispatch({ type: 'earning/updatePoolTargets', payload: result }); } }) - .catch(console.error) + .catch((error) => logger.error('Failed to fetch pool target', error)) .finally(() => { if (!unmount) { setTargetLoading(false); diff --git a/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx b/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx index 7c9c27304c1..f7ec6d00191 100644 --- a/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx +++ b/packages/extension-koni-ui/src/Popup/Transaction/variants/SendFund.tsx @@ -19,6 +19,7 @@ import { SWTransactionResponse } from '@subwallet/extension-base/services/transa import { AccountChainType, AccountProxy, AccountProxyType, AccountSignMode, AnalyzedGroup, BasicTxWarningCode, FeeChainType, TransactionFee } from '@subwallet/extension-base/types'; import { ResponseSubscribeTransfer } from '@subwallet/extension-base/types/balance/transfer'; import { CommonStepType } from '@subwallet/extension-base/types/service-base'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { _reformatAddressWithChain, isAccountAll, isSubstrateEcdsaLedgerAssetSupported } from '@subwallet/extension-base/utils'; import { AccountAddressSelector, AddressInputNew, AddressInputRef, AlertBox, AlertBoxInstant, AlertModal, AmountInput, ChainSelector, FeeEditor, HiddenInput, TokenSelector } from '@subwallet/extension-koni-ui/components'; import { ADDRESS_INPUT_AUTO_FORMAT_VALUE } from '@subwallet/extension-koni-ui/constants'; @@ -38,6 +39,8 @@ import BigN from 'bignumber.js'; import CN from 'classnames'; import { PaperPlaneRight, PaperPlaneTilt } from 'phosphor-react'; import React, { useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState } from 'react'; + +const logger = createLogger('SendFund'); import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import { useIsFirstRender, useLocalStorage } from 'usehooks-ts'; @@ -763,7 +766,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone setLoading(true); options.isTransferBounceable = true; _doSubmit().catch((error) => { - console.error('Error during submit:', error); + logger.error('Error during submit', error); }); } }, @@ -796,7 +799,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone setLoading(true); checkTransferAll = true; _doSubmit().catch((error) => { - console.error('Error during submit:', error); + logger.error('Error during submit', error); }); } }, @@ -819,7 +822,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone }; _doSubmit().catch((error) => { - console.error('Error during submit:', error); + logger.error('Error during submit', error); }); }, [assetInfo, chainInfoMap, closeAlert, doSubmit, form, isTransferAll, openAlert, t, updateAddressInputValue]); @@ -889,7 +892,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone validate(); } else { - cancelSubscription(transferInfo.id).catch(console.error); + cancelSubscription(transferInfo.id).catch((error) => logger.error('Failed to cancel subscription', error)); } }; @@ -908,7 +911,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone }, callback) .then((callback)) .catch((e) => { - console.error('Error in subscribeMaxTransfer:', e); + logger.error('Error in subscribeMaxTransfer', e); setTransferInfo(undefined); validate(); @@ -920,7 +923,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone return () => { cancel = true; - id && cancelSubscription(id).catch(console.error); + id && cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription on cleanup', error)); }; }, [assetValue, assetRegistry, chainValue, chainStatus, form, fromValue, destChainValue, selectedTransactionFee, nativeTokenSlug, currentTokenPayFee, transferAmountValue, toValue, isTransferAll]); @@ -960,7 +963,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone }); }) .catch((e) => { - console.log('error', e); + logger.error('Error fetching optimal transfer process', e); }); }, [assetValue, chainValue, destChainValue, fromValue, transferAmountValue]); @@ -1009,12 +1012,12 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone setIsFetchingListFeeToken(false); } - console.error('Error fetching tokens:', error); + logger.error('Error fetching tokens', error); } }; fetchTokens().catch((error) => { - console.error('Unhandled error in fetchTokens:', error); + logger.error('Unhandled error in fetchTokens', error); }); return () => { @@ -1023,7 +1026,7 @@ const Component = ({ className = '', isAllAccount, targetAccountProxy }: Compone }, [chainValue, fromValue, nativeTokenBalance, nativeTokenSlug]); useEffect(() => { - console.log('transferInfo', transferInfo); + logger.debug('transferInfo updated', transferInfo); }, [transferInfo]); useRestoreTransaction(form); diff --git a/packages/extension-koni-ui/src/Popup/Transaction/variants/Swap/index.tsx b/packages/extension-koni-ui/src/Popup/Transaction/variants/Swap/index.tsx index 164981b94c7..43e218ba1a5 100644 --- a/packages/extension-koni-ui/src/Popup/Transaction/variants/Swap/index.tsx +++ b/packages/extension-koni-ui/src/Popup/Transaction/variants/Swap/index.tsx @@ -13,6 +13,7 @@ import { DetectedGenOptimalProcessErrMsg } from '@subwallet/extension-base/servi import { SWTransactionResponse } from '@subwallet/extension-base/services/transaction-service/types'; import { AccountChainType, AccountProxy, AccountProxyType, AnalyzedGroup, CommonOptimalSwapPath, ProcessType, SwapRequestResult, SwapRequestV2 } from '@subwallet/extension-base/types'; import { CHAINFLIP_SLIPPAGE, SIMPLE_SWAP_SLIPPAGE, SlippageType, SwapProviderId, SwapQuote } from '@subwallet/extension-base/types/swap'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { isSameAddress } from '@subwallet/extension-base/utils'; import { getId } from '@subwallet/extension-base/utils/getId'; import { AccountAddressSelector, AddressInputNew, AddressInputRef, AlertBox, HiddenInput, LoadingScreen, PageWrapper } from '@subwallet/extension-koni-ui/components'; @@ -845,7 +846,7 @@ const Component = ({ allowedChainAndExcludedTokenForTargetAccountProxy, defaultS }); form.setFieldValue('recipient', address); } catch (e) { - console.log('Parse recipientAutoFilledInfo error', e); + defaultLogger.debug('Parse recipientAutoFilledInfo error', e); } } else { addressInputCurrent?.setInputValue?.(''); @@ -865,7 +866,7 @@ const Component = ({ allowedChainAndExcludedTokenForTargetAccountProxy, defaultS const timeout: NodeJS.Timeout = setTimeout(() => { if (recipientValue && toAssetInfo && isRecipientFieldAllowed) { form.validateFields(['recipient']).catch((e) => { - console.log('Error when validating', e); + defaultLogger.debug('Error when validating recipient', e); }); } }, 300); @@ -940,7 +941,7 @@ const Component = ({ allowedChainAndExcludedTokenForTargetAccountProxy, defaultS setHandleRequestLoading(false); } }).catch((e: Error) => { - console.log('handleSwapRequest error', e); + defaultLogger.error('handleSwapRequest error', e); if (sync) { if (e.message.toLowerCase().startsWith('swap pair is not found')) { @@ -963,7 +964,7 @@ const Component = ({ allowedChainAndExcludedTokenForTargetAccountProxy, defaultS } }); }).catch((e) => { - console.log('Error when validating', e); + defaultLogger.debug('Error when validating swap form', e); if (sync) { setIsFormInvalid(true); @@ -996,7 +997,7 @@ const Component = ({ allowedChainAndExcludedTokenForTargetAccountProxy, defaultS updateSwapStates(rs); } }).catch((e: Error) => { - console.log('Error when doing refreshSwapRequestResult', e); + defaultLogger.error('Error when doing refreshSwapRequestResult', e); if (e.message.toLowerCase().startsWith('swap pair is not found')) { notifyErrorMessage(ErrorMessageMap.NoQuote); @@ -1459,7 +1460,7 @@ const Wrapper: React.FC = (props: WrapperProps) => { setLoading(false); }) .catch((error: Error) => { - console.error(`Error while fetching swap destinations: ${error.message}`); + defaultLogger.error(`Error while fetching swap destinations: ${error.message}`, error); setFetchError(true); setLoading(false); diff --git a/packages/extension-koni-ui/src/Popup/TransactionSubmission.tsx b/packages/extension-koni-ui/src/Popup/TransactionSubmission.tsx index 146b21f9686..72369a5b558 100644 --- a/packages/extension-koni-ui/src/Popup/TransactionSubmission.tsx +++ b/packages/extension-koni-ui/src/Popup/TransactionSubmission.tsx @@ -3,6 +3,7 @@ import { getTokenPairFromStep } from '@subwallet/extension-base/services/swap-service/utils'; import { ProcessTransactionData, ProcessType, ResponseSubscribeProcessById, SwapBaseTxData } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { CloseIcon, Layout, LoadingScreen, PageWrapper } from '@subwallet/extension-koni-ui/components'; import { SwapTransactionBlock } from '@subwallet/extension-koni-ui/components/Swap'; import { useDefaultNavigate } from '@subwallet/extension-koni-ui/hooks'; @@ -20,6 +21,8 @@ import styled from 'styled-components'; type Props = ThemeProps; +const logger = createLogger('TransactionSubmission'); + type SwapProcessingContentComponentProps = { processData: ProcessTransactionData; } @@ -133,7 +136,7 @@ const Component: React.FC = (props: Props) => { const onCancel = () => { if (id) { - cancelSubscription(id).catch(console.error); + cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription', error)); } }; @@ -149,7 +152,7 @@ const Component: React.FC = (props: Props) => { subscribeProcess({ processId: transactionProcessId }, updateProcess) .then(updateProcess) - .catch(console.error); + .catch((error) => logger.error('Failed to subscribe process', error)); } return () => { diff --git a/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectWalletConnect.tsx b/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectWalletConnect.tsx index 8c9623ac94d..fc6ce0d6212 100644 --- a/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectWalletConnect.tsx +++ b/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectWalletConnect.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { WALLET_CONNECT_SESSION_TIMEOUT } from '@subwallet/extension-base/services/wallet-connect-service/constants'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { CloseIcon, Layout, QrScannerErrorNotice, WalletConnect } from '@subwallet/extension-koni-ui/components'; import { TIME_OUT_RECORD } from '@subwallet/extension-koni-ui/constants'; import { useDefaultNavigate, useOpenQrScanner } from '@subwallet/extension-koni-ui/hooks'; @@ -150,7 +151,7 @@ const Component: React.FC = (props: Props) => { }) .then(noop) .catch((e: Error) => { - console.error(e); + defaultLogger.error('Failed to add connection', e); setLoading(false); setConnectionError(convertWCErrorMessage(e)); activeModal(modalId); @@ -190,7 +191,7 @@ const Component: React.FC = (props: Props) => { }, []); const onScanError = useCallback((error: string) => { - console.log(error); + defaultLogger.debug('Scan error', error); setScanError(error); }, []); diff --git a/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectionDetail.tsx b/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectionDetail.tsx index a1a8e06727d..acc79d4fc36 100644 --- a/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectionDetail.tsx +++ b/packages/extension-koni-ui/src/Popup/WalletConnect/ConnectionDetail.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { AccountProxy } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { stripUrl } from '@subwallet/extension-base/utils'; import { AccountProxyItem, EmptyList, GeneralEmptyList, Layout, MetaInfo, PageWrapper, WCNetworkAvatarGroup } from '@subwallet/extension-koni-ui/components'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; @@ -89,7 +90,7 @@ const Component: React.FC = (props) => { setLoading(true); disconnectWalletConnectConnection(topic) .catch((e) => { - console.log(e); + defaultLogger.debug('Failed to disconnect wallet connect connection', e); notification({ type: 'error', message: t('ui.WALLET_CONNECT.screen.WalletConnect.ConnectionDetail.failToDisconnect') diff --git a/packages/extension-koni-ui/src/Popup/router.tsx b/packages/extension-koni-ui/src/Popup/router.tsx index aa65d638d1b..b3c656ef9bc 100644 --- a/packages/extension-koni-ui/src/Popup/router.tsx +++ b/packages/extension-koni-ui/src/Popup/router.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { PHISHING_PAGE_REDIRECT } from '@subwallet/extension-base/defaults'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { PageWrapper } from '@subwallet/extension-koni-ui/components'; import { AppOnlineContentContextProvider } from '@subwallet/extension-koni-ui/contexts/AppOnlineContentProvider'; import { MktCampaignModalContextProvider } from '@subwallet/extension-koni-ui/contexts/MktCampaignModalContext'; @@ -11,6 +12,8 @@ import { i18nPromise } from '@subwallet/extension-koni-ui/utils/common/i18n'; import React, { ComponentType } from 'react'; import { createHashRouter, IndexRouteObject, Outlet, useLocation } from 'react-router-dom'; +const logger = createLogger('Router'); + export const lazyLoaderMap: Record = {}; export class LazyLoader { @@ -36,7 +39,7 @@ export class LazyLoader { public generateRouterObject (path: string, preload = false): Pick { if (preload) { - this.loadElement().catch(console.error); + this.loadElement().catch((error) => logger.error('Failed to load element', error)); } return { diff --git a/packages/extension-koni-ui/src/components/Confirmation/ZkModeFooter.tsx b/packages/extension-koni-ui/src/components/Confirmation/ZkModeFooter.tsx index ccc2995f398..709c5ead234 100644 --- a/packages/extension-koni-ui/src/components/Confirmation/ZkModeFooter.tsx +++ b/packages/extension-koni-ui/src/components/Confirmation/ZkModeFooter.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { FormCallbacks, FormFieldData, ThemeProps } from '@subwallet/extension-koni-ui/types'; import { simpleCheckForm } from '@subwallet/extension-koni-ui/utils'; import { Button, Form, Icon, Input } from '@subwallet/react-ui'; @@ -55,7 +56,7 @@ const Component: React.FC = (props: Props) => { .then((validatedData) => { onOk(validatedData.password); }) - .catch(console.error); + .catch((error) => defaultLogger.error('Failed to validate password fields', error)); }, [form, onOk]); const onClickCancel = useCallback(() => { diff --git a/packages/extension-koni-ui/src/components/Field/AddressInput.tsx b/packages/extension-koni-ui/src/components/Field/AddressInput.tsx index 30d5ad87f92..ea051242c6d 100644 --- a/packages/extension-koni-ui/src/components/Field/AddressInput.tsx +++ b/packages/extension-koni-ui/src/components/Field/AddressInput.tsx @@ -3,6 +3,7 @@ import { CHAINS_SUPPORTED_DOMAIN, isAzeroDomain } from '@subwallet/extension-base/koni/api/dotsama/domain'; import { AbstractAddressJson } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { reformatAddress } from '@subwallet/extension-base/utils'; import { useForwardInputRef, useOpenQrScanner, useSelector, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { resolveAddressToDomain, resolveDomainToAddress, saveRecentAccount } from '@subwallet/extension-koni-ui/messaging'; @@ -95,11 +96,11 @@ function Component (props: Props, ref: ForwardedRef): React.ReactEleme if (isAddress(val) && saveAddress) { if (isEthereumAddress(val)) { - saveRecentAccount(val, chain).catch(console.error); + saveRecentAccount(val, chain).catch((error) => defaultLogger.error('Failed to save recent account', error)); } else { try { if (decodeAddress(val, true, addressPrefix)) { - saveRecentAccount(val, chain).catch(console.error); + saveRecentAccount(val, chain).catch((error) => defaultLogger.error('Failed to save recent account', error)); } } catch (e) {} } @@ -163,7 +164,7 @@ function Component (props: Props, ref: ForwardedRef): React.ReactEleme inputRef?.current?.blur(); } }) - .catch(console.error); + .catch((error) => defaultLogger.error('Failed to resolve domain to address', error)); } else if (isAddress(value)) { resolveAddressToDomain({ chain, @@ -174,7 +175,7 @@ function Component (props: Props, ref: ForwardedRef): React.ReactEleme setDomainName(result); } }) - .catch(console.error); + .catch((error) => defaultLogger.error('Failed to resolve address to domain', error)); } } else { setDomainName(undefined); diff --git a/packages/extension-koni-ui/src/components/Field/AddressInputNew.tsx b/packages/extension-koni-ui/src/components/Field/AddressInputNew.tsx index 021e2bd3ee2..d30dc2143f7 100644 --- a/packages/extension-koni-ui/src/components/Field/AddressInputNew.tsx +++ b/packages/extension-koni-ui/src/components/Field/AddressInputNew.tsx @@ -7,6 +7,7 @@ import { NotificationType } from '@subwallet/extension-base/background/KoniTypes import { ActionType } from '@subwallet/extension-base/core/types'; import { _isPureSubstrateChain } from '@subwallet/extension-base/services/chain-service/utils'; import { AnalyzeAddress, AnalyzedGroup, ResponseInputAccountSubscribe } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { _reformatAddressWithChain, reformatAddress } from '@subwallet/extension-base/utils'; import { AddressSelectorItem } from '@subwallet/extension-koni-ui/components'; import { ADDRESS_INPUT_AUTO_FORMAT_VALUE } from '@subwallet/extension-koni-ui/constants'; @@ -105,7 +106,7 @@ function Component (props: Props, ref: ForwardedRef): React.Rea onChange && onChange({ target: { value: val } }); if (isAddress(val) && saveAddress) { - saveRecentAccount(val, chainSlug).catch(console.error); + saveRecentAccount(val, chainSlug).catch((error) => defaultLogger.error('Failed to save recent account', error)); } }, [chainSlug, onChange, saveAddress]); @@ -427,14 +428,14 @@ function Component (props: Props, ref: ForwardedRef): React.Rea data: inputValue, chain: chainSlug, actionType: actionType - }, handler).then(handler).catch(console.error); + }, handler).then(handler).catch((error) => defaultLogger.error('Failed to subscribe accounts input address', error)); } return () => { sync = false; if (id) { - cancelSubscription(id).catch(console.log); + cancelSubscription(id).catch((error) => defaultLogger.debug('Failed to cancel subscription', error)); } }; }, [actionType, chainSlug, inputValue, tokenSlug]); diff --git a/packages/extension-koni-ui/src/components/Field/Earning/EarningPoolSelector.tsx b/packages/extension-koni-ui/src/components/Field/Earning/EarningPoolSelector.tsx index 9523fab0e4b..800428c5a4f 100644 --- a/packages/extension-koni-ui/src/components/Field/Earning/EarningPoolSelector.tsx +++ b/packages/extension-koni-ui/src/components/Field/Earning/EarningPoolSelector.tsx @@ -3,6 +3,7 @@ import { getValidatorLabel } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; import { YieldPoolType } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { fetchStaticData } from '@subwallet/extension-base/utils'; import { StakingPoolItem } from '@subwallet/extension-koni-ui/components'; import EmptyValidator from '@subwallet/extension-koni-ui/components/Account/EmptyValidator'; @@ -373,7 +374,7 @@ const Component = (props: Props, ref: ForwardedRef) => { useEffect(() => { fetchStaticData>('nomination-pool-recommendation').then((earningPoolRecommendation) => { setDefaultPoolMap(earningPoolRecommendation); - }).catch(console.error); + }).catch((error) => defaultLogger.error('Failed to fetch static data for nomination pool recommendation', error)); }, []); useEffect(() => { diff --git a/packages/extension-koni-ui/src/components/Field/Earning/EarningValidatorSelector.tsx b/packages/extension-koni-ui/src/components/Field/Earning/EarningValidatorSelector.tsx index 2abf012fef7..755e2e0bd69 100644 --- a/packages/extension-koni-ui/src/components/Field/Earning/EarningValidatorSelector.tsx +++ b/packages/extension-koni-ui/src/components/Field/Earning/EarningValidatorSelector.tsx @@ -5,6 +5,7 @@ import { ChainRecommendValidator } from '@subwallet/extension-base/constants'; import { getValidatorLabel } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; import { _STAKING_CHAIN_GROUP, RELAY_HANDLER_DIRECT_STAKING_CHAINS } from '@subwallet/extension-base/services/earning-service/constants'; import { NominationInfo, YieldPoolType } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { detectTranslate, fetchStaticData } from '@subwallet/extension-base/utils'; import { SelectValidatorInput, StakingValidatorItem } from '@subwallet/extension-koni-ui/components'; import EmptyValidator from '@subwallet/extension-koni-ui/components/Account/EmptyValidator'; @@ -350,7 +351,7 @@ const Component = (props: Props, ref: ForwardedRef) => { useEffect(() => { fetchStaticData>('direct-nomination-validator').then((earningPoolRecommendation) => { setDefaultPoolMap(earningPoolRecommendation); - }).catch(console.error); + }).catch((error) => defaultLogger.error('Failed to fetch static data for direct nomination validator', error)); }, []); useEffect(() => { diff --git a/packages/extension-koni-ui/src/components/Field/SeedPhraseInput.tsx b/packages/extension-koni-ui/src/components/Field/SeedPhraseInput.tsx index fc2740e010a..ecd94c344b4 100644 --- a/packages/extension-koni-ui/src/components/Field/SeedPhraseInput.tsx +++ b/packages/extension-koni-ui/src/components/Field/SeedPhraseInput.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { BasicInputWrapper } from '@subwallet/extension-koni-ui/components'; import { FormInstance, ThemeProps } from '@subwallet/extension-koni-ui/types'; import { Input, InputRef } from '@subwallet/react-ui'; @@ -61,7 +62,7 @@ const Component: React.ForwardRefRenderFunction = (props: Props } } - form.validateFields(validates).catch(console.error); + form.validateFields(validates).catch((error) => defaultLogger.error('Failed to validate fields', error)); }, [form, formName, index, prefix]); const onPaste: ClipboardEventHandler = useCallback((event) => { @@ -95,7 +96,7 @@ const Component: React.ForwardRefRenderFunction = (props: Props form.setFieldsValue(result); - form.validateFields(validates).catch(console.error); + form.validateFields(validates).catch((error) => defaultLogger.error('Failed to validate fields', error)); }, [form, handlePaste, prefix]); const _onFocus: FocusEventHandler = useCallback((event) => { diff --git a/packages/extension-koni-ui/src/components/Field/TransactionFee/FeeEditor/FeeEditorModal.tsx b/packages/extension-koni-ui/src/components/Field/TransactionFee/FeeEditor/FeeEditorModal.tsx index de7938dc94f..57fdd980777 100644 --- a/packages/extension-koni-ui/src/components/Field/TransactionFee/FeeEditor/FeeEditorModal.tsx +++ b/packages/extension-koni-ui/src/components/Field/TransactionFee/FeeEditor/FeeEditorModal.tsx @@ -4,6 +4,7 @@ import { _SUPPORT_TOKEN_PAY_FEE_GROUP } from '@subwallet/extension-base/constants'; import { TokenHasBalanceInfo } from '@subwallet/extension-base/services/fee-service/interfaces'; import { EvmEIP1559FeeOption, FeeCustom, FeeDefaultOption, FeeDetail, FeeOptionKey, TransactionFee } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { BN_ZERO, formatNumber, isEvmEIP1559FeeDetail } from '@subwallet/extension-base/utils'; import { AmountInput, BasicInputEvent, RadioGroup } from '@subwallet/extension-koni-ui/components'; import { FeeOptionItem } from '@subwallet/extension-koni-ui/components/Field/TransactionFee/FeeEditor/FeeOptionItem'; @@ -282,7 +283,7 @@ const Component = ({ chainValue, className, decimals, feeOptionsInfo, feeType, m if (part.priorityFeeValue) { form.validateFields(['maxFeeValue']).catch((e) => { - console.log(e); + defaultLogger.debug('Failed to validate maxFeeValue field', e); }); } }, diff --git a/packages/extension-koni-ui/src/components/Layout/base/Home.tsx b/packages/extension-koni-ui/src/components/Layout/base/Home.tsx index e5004bd4618..0b722e3c57c 100644 --- a/packages/extension-koni-ui/src/components/Layout/base/Home.tsx +++ b/packages/extension-koni-ui/src/components/Layout/base/Home.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @polkadot/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { Layout } from '@subwallet/extension-koni-ui/components'; import { CUSTOMIZE_MODAL } from '@subwallet/extension-koni-ui/constants/modal'; import { useExtensionDisplayModes, useSelector, useSidePanelUtils } from '@subwallet/extension-koni-ui/hooks'; @@ -81,7 +82,7 @@ const Component = ({ children, className, isDisableHeader, onClickSearchToken, s ), onClick: () => { - windowOpen({ allowedPath: '/' }).catch(console.error); + windowOpen({ allowedPath: '/' }).catch((error) => defaultLogger.error('Failed to open window', error)); isSidePanelMode && closeSidePanel(); } }; diff --git a/packages/extension-koni-ui/src/components/Layout/parts/ConnectWebsiteModal.tsx b/packages/extension-koni-ui/src/components/Layout/parts/ConnectWebsiteModal.tsx index cdec7de50b6..9cc68812d32 100644 --- a/packages/extension-koni-ui/src/components/Layout/parts/ConnectWebsiteModal.tsx +++ b/packages/extension-koni-ui/src/components/Layout/parts/ConnectWebsiteModal.tsx @@ -3,6 +3,7 @@ import { AuthUrlInfo } from '@subwallet/extension-base/services/request-service/types'; import { AccountProxy } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { isAccountAll, isSameAddress } from '@subwallet/extension-base/utils'; import { AccountProxyItem, DAppConfigurationModal } from '@subwallet/extension-koni-ui/components'; import ConfirmationGeneralInfo from '@subwallet/extension-koni-ui/components/Confirmation/ConfirmationGeneralInfo'; @@ -21,6 +22,8 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('ConnectWebsiteModal'); + type Props = ThemeProps & { id: string; onCancel: () => void; @@ -88,7 +91,7 @@ function Component ({ authInfo, className = '', id, isBlocked = true, isNotConne setIsSubmit(true); changeAuthorizationPerSite({ values: allowedMap, id: authInfo.id }) .catch((e) => { - console.log('changeAuthorizationPerSite error', e); + logger.error('changeAuthorizationPerSite error', e); }).finally(() => { onCancel(); setIsSubmit(false); @@ -103,7 +106,7 @@ function Component ({ authInfo, className = '', id, isBlocked = true, isNotConne .then(() => { setIsSubmit(false); }) - .catch(console.error); + .catch((error) => logger.error('Failed to change authorization block', error)); } }, [authInfo?.id, isSubmit]); diff --git a/packages/extension-koni-ui/src/components/Layout/parts/SelectAccount/AccountSelectorModal.tsx b/packages/extension-koni-ui/src/components/Layout/parts/SelectAccount/AccountSelectorModal.tsx index aea6d1a6059..f75b78b7991 100644 --- a/packages/extension-koni-ui/src/components/Layout/parts/SelectAccount/AccountSelectorModal.tsx +++ b/packages/extension-koni-ui/src/components/Layout/parts/SelectAccount/AccountSelectorModal.tsx @@ -5,6 +5,7 @@ import type { ButtonProps } from '@subwallet/react-ui/es/button/button'; import { CurrentAccountInfo } from '@subwallet/extension-base/background/types'; import { AccountActions, AccountProxy, AccountProxyType } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { AccountChainAddressesModal, AccountProxySelectorAllItem, AccountProxySelectorItem, GeneralEmptyList } from '@subwallet/extension-koni-ui/components'; import ExportAllSelector from '@subwallet/extension-koni-ui/components/Layout/parts/SelectAccount/ExportAllSelector'; import SelectAccountFooter from '@subwallet/extension-koni-ui/components/Layout/parts/SelectAccount/Footer'; @@ -238,10 +239,10 @@ const Component: React.FC = ({ className }: Props) => { } } }).catch((e) => { - console.error('Failed to switch account', e); + defaultLogger.error('Failed to switch account', e); }); } else { - console.error('Failed to switch account'); + defaultLogger.error('Failed to switch account - no account selected'); } inactiveModal(modalId); diff --git a/packages/extension-koni-ui/src/components/Modal/Account/AttachAccountModal.tsx b/packages/extension-koni-ui/src/components/Modal/Account/AttachAccountModal.tsx index 23f556c65ad..82ae95d7964 100644 --- a/packages/extension-koni-ui/src/components/Modal/Account/AttachAccountModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Account/AttachAccountModal.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import BackIcon from '@subwallet/extension-koni-ui/components/Icon/BackIcon'; import CloseIcon from '@subwallet/extension-koni-ui/components/Icon/CloseIcon'; import { SettingItemSelection } from '@subwallet/extension-koni-ui/components/Setting/SettingItemSelection'; @@ -20,6 +21,8 @@ import React, { useCallback, useContext, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('AttachAccountModal'); + type Props = ThemeProps; interface AttachAccountItem { @@ -77,7 +80,7 @@ const Component: React.FC = ({ className }: Props) => { setStateSelectAccount(true); if (!isExpanseMode) { - windowOpen({ allowedPath: '/accounts/connect-ledger' }).catch(console.error); + windowOpen({ allowedPath: '/accounts/connect-ledger' }).catch((error) => logger.error('Failed to open window', error)); isSidePanelMode && closeSidePanel(); } else { navigate('accounts/connect-ledger'); diff --git a/packages/extension-koni-ui/src/components/Modal/Account/ImportAccountModal.tsx b/packages/extension-koni-ui/src/components/Modal/Account/ImportAccountModal.tsx index 70aaf32daba..7aeb6a07861 100644 --- a/packages/extension-koni-ui/src/components/Modal/Account/ImportAccountModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Account/ImportAccountModal.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { IMPORT_ACCOUNT_MODAL } from '@subwallet/extension-koni-ui/constants'; import { useClickOutSide, useExtensionDisplayModes, useGoBackSelectAccount, useSetSessionLatest, useSidePanelUtils, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { windowOpen } from '@subwallet/extension-koni-ui/messaging'; @@ -14,6 +15,8 @@ import React, { useCallback, useContext, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('ImportAccountModal'); + import { BackIcon, CloseIcon } from '../../Icon'; import { SettingItemSelection } from '../../Setting'; @@ -58,7 +61,7 @@ const Component: React.FC = ({ className }: Props) => { const onClickJson = useCallback(() => { if (!isExpanseMode) { - windowOpen({ allowedPath: '/accounts/restore-json' }).catch(console.error); + windowOpen({ allowedPath: '/accounts/restore-json' }).catch((error) => logger.error('Failed to open window', error)); isSidePanelMode && closeSidePanel(); } else { diff --git a/packages/extension-koni-ui/src/components/Modal/Campaign/AppPopupModal.tsx b/packages/extension-koni-ui/src/components/Modal/Campaign/AppPopupModal.tsx index 20c4d28798a..8864410303d 100644 --- a/packages/extension-koni-ui/src/components/Modal/Campaign/AppPopupModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Campaign/AppPopupModal.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { YieldPoolType } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import AppInstructionModal from '@subwallet/extension-koni-ui/components/Modal/Campaign/AppInstructionModal'; import ContentGenerator from '@subwallet/extension-koni-ui/components/StaticContent/ContentGenerator'; import { APP_INSTRUCTION_DATA, APP_INSTRUCTION_MODAL, APP_POPUP_MODAL } from '@subwallet/extension-koni-ui/constants'; @@ -45,7 +46,7 @@ const Component: React.FC = (props: Props) => { try { return JSON.parse(appInstructionData || '[]') as StaticDataProps[]; } catch (e) { - console.error(e); + defaultLogger.error('Failed to parse app instruction data', e); return []; } @@ -91,7 +92,7 @@ const Component: React.FC = (props: Props) => { } else { onAccept(url); } - }).catch((e) => console.log(e)); + }).catch((e) => defaultLogger.debug('Failed to toggle campaign popup', e)); }, [currentInstructionData, instructionButton, onAccept, activeModal] ); diff --git a/packages/extension-koni-ui/src/components/Modal/Campaign/CampaignBannerModal.tsx b/packages/extension-koni-ui/src/components/Modal/Campaign/CampaignBannerModal.tsx index 8b4d2d9331b..96d91d5e4e2 100644 --- a/packages/extension-koni-ui/src/components/Modal/Campaign/CampaignBannerModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Campaign/CampaignBannerModal.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { CampaignBanner, CampaignButton } from '@subwallet/extension-base/background/KoniTypes'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { HOME_CAMPAIGN_BANNER_MODAL } from '@subwallet/extension-koni-ui/constants'; import { completeBannerCampaign } from '@subwallet/extension-koni-ui/messaging/campaigns'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; @@ -29,7 +30,7 @@ const Component: React.FC = (props: Props) => { completeBannerCampaign({ slug: banner.slug }) - .catch((console.error)); + .catch((error) => defaultLogger.error('Failed to complete banner campaign', error)); }, [banner.slug, inactiveModal]); const onClickButton = useCallback((item: CampaignButton) => { diff --git a/packages/extension-koni-ui/src/components/Modal/Customize/CustomizeModal.tsx b/packages/extension-koni-ui/src/components/Modal/Customize/CustomizeModal.tsx index 419dedc4807..3f3ee47f383 100644 --- a/packages/extension-koni-ui/src/components/Modal/Customize/CustomizeModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Customize/CustomizeModal.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { CUSTOMIZE_MODAL } from '@subwallet/extension-koni-ui/constants/modal'; import useTranslation from '@subwallet/extension-koni-ui/hooks/common/useTranslation'; import { saveShowZeroBalance } from '@subwallet/extension-koni-ui/messaging'; @@ -12,6 +13,8 @@ import React, { useCallback, useContext } from 'react'; import { useSelector } from 'react-redux'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('CustomizeModal'); + import CustomizeModalContent from './CustomizeModalContent'; type Props = ThemeProps; @@ -23,7 +26,7 @@ function Component ({ className = '' }: Props): React.ReactElement { const isShowZeroBalance = useSelector((state: RootState) => state.settings.isShowZeroBalance); const onChangeZeroBalance = useCallback(() => { - saveShowZeroBalance(!isShowZeroBalance).catch(console.error); + saveShowZeroBalance(!isShowZeroBalance).catch((error) => logger.error('Failed to save show zero balance setting', error)); }, [isShowZeroBalance]); const onCancel = useCallback(() => { diff --git a/packages/extension-koni-ui/src/components/Modal/DAppConfigurationModal.tsx b/packages/extension-koni-ui/src/components/Modal/DAppConfigurationModal.tsx index 07f6e9cc5e6..a45e8904792 100644 --- a/packages/extension-koni-ui/src/components/Modal/DAppConfigurationModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/DAppConfigurationModal.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { AuthUrlInfo } from '@subwallet/extension-base/services/request-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ActionItemType, ActionModal } from '@subwallet/extension-koni-ui/components'; import { DAPP_CONFIGURATION_MODAL } from '@subwallet/extension-koni-ui/constants'; import { WalletModalContext } from '@subwallet/extension-koni-ui/contexts/WalletModalContextProvider'; @@ -14,6 +15,8 @@ import React, { useCallback, useContext, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('DAppConfigurationModal'); + type Props = ThemeProps & { authInfo: AuthUrlInfo; } @@ -45,7 +48,7 @@ function Component ({ authInfo, className = '' }: Props): React.ReactElement { updateAuthUrls(list); }) - .catch(console.error); + .catch((error) => logger.error('Failed to toggle authorization', error)); onCloseActionModal(); } }, @@ -55,7 +58,7 @@ function Component ({ authInfo, className = '' }: Props): React.ReactElement { - forgetSite(authInfo.id, updateAuthUrls).catch(console.error); + forgetSite(authInfo.id, updateAuthUrls).catch((error) => logger.error('Failed to forget site', error)); onCloseActionModal(); } } @@ -69,7 +72,7 @@ function Component ({ authInfo, className = '' }: Props): React.ReactElement { - changeAuthorization(false, authInfo.id, updateAuthUrls).catch(console.error); + changeAuthorization(false, authInfo.id, updateAuthUrls).catch((error) => logger.error('Failed to change authorization (disconnect)', error)); onCloseActionModal(); } }, @@ -79,7 +82,7 @@ function Component ({ authInfo, className = '' }: Props): React.ReactElement { - changeAuthorization(true, authInfo.id, updateAuthUrls).catch(console.error); + changeAuthorization(true, authInfo.id, updateAuthUrls).catch((error) => logger.error('Failed to change authorization (connect)', error)); onCloseActionModal(); } } diff --git a/packages/extension-koni-ui/src/components/Modal/DeriveAccountActionModal.tsx b/packages/extension-koni-ui/src/components/Modal/DeriveAccountActionModal.tsx index bd9a4fa4753..5329482b901 100644 --- a/packages/extension-koni-ui/src/components/Modal/DeriveAccountActionModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/DeriveAccountActionModal.tsx @@ -4,6 +4,7 @@ import { NotificationType } from '@subwallet/extension-base/background/KoniTypes'; import { AccountChainType, AccountProxyType, DerivePathInfo } from '@subwallet/extension-base/types'; import { addLazy, detectTranslate, getAccountChainTypeFromKeypairType } from '@subwallet/extension-base/utils'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { DERIVE_ACCOUNT_ACTION_MODAL } from '@subwallet/extension-koni-ui/constants'; import { WalletModalContext } from '@subwallet/extension-koni-ui/contexts/WalletModalContextProvider'; import { useCompleteCreateAccount, useGetAccountProxyById, useTranslation, useUnlockChecker } from '@subwallet/extension-koni-ui/hooks'; @@ -20,6 +21,8 @@ import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } import { Trans } from 'react-i18next'; import styled from 'styled-components'; +const logger = createLogger('DeriveAccountActionModal'); + import { AccountChainTypeLogos, AccountProxyTypeTag } from '../AccountProxy'; export interface AccountDeriveActionProps { @@ -232,7 +235,7 @@ const Component: React.FC = (props: Props) => { } } }) - .catch(console.error); + .catch((error) => logger.error('Failed to derive suggest', error)); } return () => { diff --git a/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/ChangeValidator.tsx b/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/ChangeValidator.tsx index 1495c42059e..4bc18ac4cb1 100644 --- a/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/ChangeValidator.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/ChangeValidator.tsx @@ -5,6 +5,7 @@ import { ExtrinsicType, NotificationType } from '@subwallet/extension-base/backg import { ChainRecommendValidator } from '@subwallet/extension-base/constants'; import { RELAY_HANDLER_DIRECT_STAKING_CHAINS } from '@subwallet/extension-base/services/earning-service/constants'; import { NominationInfo, SubmitChangeValidatorStaking, ValidatorInfo, YieldPoolType } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { detectTranslate, fetchStaticData } from '@subwallet/extension-base/utils'; import { StakingValidatorItem } from '@subwallet/extension-koni-ui/components'; import EmptyValidator from '@subwallet/extension-koni-ui/components/Account/EmptyValidator'; @@ -27,6 +28,8 @@ import React, { forwardRef, SyntheticEvent, useCallback, useContext, useEffect, import { useTranslation } from 'react-i18next'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('ChangeValidator'); + interface Props extends ThemeProps, BasicInputWrapper { modalId: string; chain: string; @@ -427,7 +430,7 @@ const Component = (props: Props) => { useEffect(() => { fetchStaticData>('direct-nomination-validator').then((earningValidatorRecommendation) => { setDefaultValidatorMap(earningValidatorRecommendation); - }).catch(console.error); + }).catch((error) => logger.error('Failed to fetch static data for direct nomination validator', error)); }, []); useEffect(() => { diff --git a/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/index.tsx b/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/index.tsx index 0754a75af0d..aab76e6126f 100644 --- a/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/index.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Earning/EarningValidatorSelectedModal/index.tsx @@ -5,6 +5,7 @@ import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import { getValidatorLabel } from '@subwallet/extension-base/koni/api/staking/bonding/utils'; import { _getAssetDecimals, _getAssetSymbol } from '@subwallet/extension-base/services/chain-service/utils'; import { NominationInfo, YieldPoolType, YieldPositionInfo } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { StakingNominationItem, StakingValidatorItem } from '@subwallet/extension-koni-ui/components'; import EmptyValidator from '@subwallet/extension-koni-ui/components/Account/EmptyValidator'; import { BasicInputWrapper } from '@subwallet/extension-koni-ui/components/Field/Base'; @@ -25,6 +26,8 @@ import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; import { useLocalStorage } from 'usehooks-ts'; +const logger = createLogger('EarningValidatorSelectedModal'); + import ChangeBittensorValidator from './ChangeBittensorValidator'; import ChangeValidator from './ChangeValidator'; @@ -275,7 +278,7 @@ const Component = (props: Props) => { store.dispatch({ type: 'earning/updatePoolTargets', payload: result }); } }) - .catch(console.error) + .catch((error) => logger.error('Failed to fetch pool target', error)) .finally(() => { if (!unmount) { setTargetLoading(false); diff --git a/packages/extension-koni-ui/src/components/Modal/Global/AddressQrModal.tsx b/packages/extension-koni-ui/src/components/Modal/Global/AddressQrModal.tsx index cbab9c8f0f5..a0207081e7b 100644 --- a/packages/extension-koni-ui/src/components/Modal/Global/AddressQrModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Global/AddressQrModal.tsx @@ -4,6 +4,7 @@ import type { ButtonProps } from '@subwallet/react-ui/es/button/button'; import { getExplorerLink } from '@subwallet/extension-base/services/transaction-service/utils'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { AccountActions } from '@subwallet/extension-base/types'; import { CloseIcon, TonWalletContractSelectorModal } from '@subwallet/extension-koni-ui/components'; import { RELAY_CHAINS_TO_MIGRATE } from '@subwallet/extension-koni-ui/constants'; @@ -96,10 +97,10 @@ const Component: React.FC = ({ accountTokenAddresses = [], address: initi try { if (scanExplorerAddressUrl) { // eslint-disable-next-line no-void - void chrome.tabs.create({ url: scanExplorerAddressUrl, active: true }).then(() => console.log('redirecting')); + void chrome.tabs.create({ url: scanExplorerAddressUrl, active: true }).then(() => defaultLogger.debug('redirecting to explorer')); } } catch (e) { - console.log('error redirecting to a new tab'); + defaultLogger.debug('error redirecting to a new tab', e); } }, [scanExplorerAddressUrl]); diff --git a/packages/extension-koni-ui/src/components/Modal/NotificationDetailModal.tsx b/packages/extension-koni-ui/src/components/Modal/NotificationDetailModal.tsx index df393c626e9..19b72251ee4 100644 --- a/packages/extension-koni-ui/src/components/Modal/NotificationDetailModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/NotificationDetailModal.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { NOTIFICATION_DETAIL_MODAL } from '@subwallet/extension-koni-ui/constants'; import { switchReadNotificationStatus } from '@subwallet/extension-koni-ui/messaging/transaction/notification'; import { NotificationInfoItem } from '@subwallet/extension-koni-ui/Popup/Settings/Notifications/Notification'; @@ -13,6 +14,8 @@ import React, { useCallback, useContext, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled, { useTheme } from 'styled-components'; +const logger = createLogger('NotificationDetailModal'); + type Props = ThemeProps & { onCancel?: () => void; notificationItem: NotificationInfoItem; @@ -92,7 +95,7 @@ function Component (props: Props): React.ReactElement { id: notificationItem.id, isRead: notificationItem.isRead }) - .catch(console.error) + .catch((error) => logger.error('Failed to switch read notification status', error)) .finally(() => { _onCancel(); setTrigger(!isTrigger); diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModal/ReceiveQrModal.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModal/ReceiveQrModal.tsx index dfa30685cbb..5c7541a3408 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModal/ReceiveQrModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModal/ReceiveQrModal.tsx @@ -3,6 +3,7 @@ import { _getChainSubstrateAddressPrefix } from '@subwallet/extension-base/services/chain-service/utils'; import { getExplorerLink } from '@subwallet/extension-base/services/transaction-service/utils'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import InfoIcon from '@subwallet/extension-koni-ui/components/Icon/InfoIcon'; import { RECEIVE_QR_MODAL } from '@subwallet/extension-koni-ui/constants/modal'; import useNotification from '@subwallet/extension-koni-ui/hooks/common/useNotification'; @@ -60,10 +61,10 @@ const Component: React.FC = ({ address, className, selectedNetwork }: Pro try { if (scanExplorerAddressUrl) { // eslint-disable-next-line no-void - void chrome.tabs.create({ url: scanExplorerAddressUrl, active: true }).then(() => console.log('redirecting')); + void chrome.tabs.create({ url: scanExplorerAddressUrl, active: true }).then(() => defaultLogger.debug('redirecting to explorer')); } } catch (e) { - console.log('error redirecting to a new tab'); + defaultLogger.debug('error redirecting to a new tab', e); } }, [scanExplorerAddressUrl]); diff --git a/packages/extension-koni-ui/src/components/Modal/ReceiveModal/TokensSelectorModal.tsx b/packages/extension-koni-ui/src/components/Modal/ReceiveModal/TokensSelectorModal.tsx index 7c1864efe15..7e744310478 100644 --- a/packages/extension-koni-ui/src/components/Modal/ReceiveModal/TokensSelectorModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/ReceiveModal/TokensSelectorModal.tsx @@ -4,6 +4,7 @@ import { _ChainAsset } from '@subwallet/chain-list/types'; import { ledgerMustCheckNetwork } from '@subwallet/extension-base/core/utils'; import { _MANTA_ZK_CHAIN_GROUP, _ZK_ASSET_PREFIX } from '@subwallet/extension-base/services/chain-service/constants'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { RECEIVE_QR_MODAL, RECEIVE_TOKEN_SELECTOR_MODAL, WARNING_LEDGER_RECEIVE_MODAL } from '@subwallet/extension-koni-ui/constants'; import { useConfirmModal, useGetAccountByAddress, useGetZkAddress, useSelector, useTranslation } from '@subwallet/extension-koni-ui/hooks'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; @@ -12,6 +13,8 @@ import { SwListSectionRef } from '@subwallet/react-ui/es/sw-list'; import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'react'; import styled from 'styled-components'; +const logger = createLogger('TokensSelectorModal'); + import { TokenEmptyList } from '../../EmptyList'; import { TokenSelectionItem } from '../../TokenItem'; @@ -91,7 +94,7 @@ function Component ({ address, className = '', items, onSelectItem }: Props): Re inactiveModal(modalId); activeModal(RECEIVE_QR_MODAL); }) - .catch(console.error); + .catch((error) => logger.error('Failed to handle ledger warning confirmation', error)); return; } diff --git a/packages/extension-koni-ui/src/components/Modal/Swap/SwapQuotesSelectorModal.tsx b/packages/extension-koni-ui/src/components/Modal/Swap/SwapQuotesSelectorModal.tsx index 650dbbd52af..707978170b3 100644 --- a/packages/extension-koni-ui/src/components/Modal/Swap/SwapQuotesSelectorModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/Swap/SwapQuotesSelectorModal.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { SwapQuote } from '@subwallet/extension-base/types/swap'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import SwapQuotesItem from '@subwallet/extension-koni-ui/components/Field/Swap/SwapQuotesItem'; import { QuoteResetTime } from '@subwallet/extension-koni-ui/components/Swap'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; @@ -40,7 +41,7 @@ const Component: React.FC = (props: Props) => { if (quoteResult) { setLoading(true); applyQuote(quoteResult).catch((error) => { - console.error('Error when confirm swap quote:', error); + defaultLogger.error('Error when confirm swap quote', error); }).finally(() => { onCancel(); setLoading(false); diff --git a/packages/extension-koni-ui/src/components/Modal/SwitchNetworkAuthorizeModal.tsx b/packages/extension-koni-ui/src/components/Modal/SwitchNetworkAuthorizeModal.tsx index 103bcb19d8a..964b20631b4 100644 --- a/packages/extension-koni-ui/src/components/Modal/SwitchNetworkAuthorizeModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/SwitchNetworkAuthorizeModal.tsx @@ -3,6 +3,7 @@ import { _isChainEvmCompatible } from '@subwallet/extension-base/services/chain-service/utils'; import { AuthUrlInfo, AuthUrls } from '@subwallet/extension-base/services/request-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { stripUrl } from '@subwallet/extension-base/utils'; import { BasicInputEvent, ChainSelector } from '@subwallet/extension-koni-ui/components'; import { AUTHORIZE_TYPE_SUPPORTS_NETWORK_SWITCH, SWITCH_CURRENT_NETWORK_AUTHORIZE_MODAL } from '@subwallet/extension-koni-ui/constants'; @@ -16,6 +17,8 @@ import styled from 'styled-components'; import useNotification from '../../hooks/common/useNotification'; +const logger = createLogger('SwitchNetworkAuthorizeModal'); + export interface SwitchNetworkAuthorizeModalProps { authUrlInfo: AuthUrlInfo; onComplete: (authInfo: AuthUrls) => void; @@ -67,7 +70,7 @@ function Component ({ authUrlInfo, className, needsTabAuthCheck, onCancel, onCom message: t('ui.DAPP.components.Modal.SwitchNetworkAuthorize.switchedNetworkSuccessfully') }); onComplete(list); - }).catch(console.error).finally(() => { + }).catch((error) => logger.error('Failed to switch current network authorization', error)).finally(() => { onCancel(); if (isSync) { diff --git a/packages/extension-koni-ui/src/components/Modal/TermsAndConditions/GeneralTermModal.tsx b/packages/extension-koni-ui/src/components/Modal/TermsAndConditions/GeneralTermModal.tsx index 93ad43b0950..565d80cbef2 100644 --- a/packages/extension-koni-ui/src/components/Modal/TermsAndConditions/GeneralTermModal.tsx +++ b/packages/extension-koni-ui/src/components/Modal/TermsAndConditions/GeneralTermModal.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { fetchStaticData } from '@subwallet/extension-base/utils/fetchStaticData'; import { GENERAL_TERM_AND_CONDITION_MODAL } from '@subwallet/extension-koni-ui/constants'; import useTranslation from '@subwallet/extension-koni-ui/hooks/common/useTranslation'; @@ -35,7 +36,7 @@ const Component = ({ className, onOk }: Props) => { useEffect(() => { fetchStaticData('term-and-condition', 'index.md', false) .then((md) => setStaticData({ md })) - .catch((e) => console.log('fetch _termAndCondition error:', e)); + .catch((e) => defaultLogger.error('fetch _termAndCondition error', e)); }, []); const onCheckedInput = useCallback((e: CheckboxChangeEvent) => { diff --git a/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/index.tsx b/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/index.tsx index 83b5104333d..4fe77bf6aaa 100644 --- a/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/index.tsx +++ b/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/index.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { ProcessTransactionData, ProcessType, ResponseSubscribeProcessById } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { TRANSACTION_PROCESS_DETAIL_MODAL } from '@subwallet/extension-koni-ui/constants'; import { cancelSubscription, subscribeProcess } from '@subwallet/extension-koni-ui/messaging'; import { ThemeProps } from '@subwallet/extension-koni-ui/types'; @@ -10,6 +11,8 @@ import React, { FC, useContext, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import styled from 'styled-components'; +const logger = createLogger('TransactionProcessDetailModal'); + import { CurrentProcessStep } from './parts/CurrentProcessStep'; import { ProcessStepList } from './parts/ProcessStepList'; import { TransactionInfoBlock } from './parts/TransactionInfoBlock'; @@ -50,7 +53,7 @@ const Component: FC = (props: Props) => { const onCancel = () => { if (id) { - cancelSubscription(id).catch(console.error); + cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription', error)); } }; @@ -68,7 +71,7 @@ const Component: FC = (props: Props) => { subscribeProcess({ processId }, updateProcess) .then(updateProcess) - .catch(console.error); + .catch((error) => logger.error('Failed to subscribe process', error)); } return () => { diff --git a/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/parts/TransactionInfoBlock/Swap.tsx b/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/parts/TransactionInfoBlock/Swap.tsx index 0c7ffb5e79a..5f178bc0a7c 100644 --- a/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/parts/TransactionInfoBlock/Swap.tsx +++ b/packages/extension-koni-ui/src/components/Modal/TransactionProcessDetailModal/parts/TransactionInfoBlock/Swap.tsx @@ -4,6 +4,7 @@ import { _parseAssetRefKey } from '@subwallet/extension-base/services/chain-service/utils'; import { getTokenPairFromStep } from '@subwallet/extension-base/services/swap-service/utils'; import { SwapBaseTxData, SwapPair } from '@subwallet/extension-base/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { MetaInfo } from '@subwallet/extension-koni-ui/components'; import { QuoteRateDisplay, SwapTransactionBlock } from '@subwallet/extension-koni-ui/components/Swap'; import { useGetAccountByAddress, useGetChainPrefixBySlug, useSelector } from '@subwallet/extension-koni-ui/hooks'; @@ -46,7 +47,7 @@ const Component: FC = (props: Props) => { return result; } } catch (e) { - console.log('getTokenPairFromStep error', e); + defaultLogger.debug('getTokenPairFromStep error', e); } // try to fetch originSwapPair, hotfix for old data. @@ -92,7 +93,7 @@ const Component: FC = (props: Props) => { } as SwapPair; } } catch (e) { - console.log('try handling old data error', e); + defaultLogger.debug('try handling old data error', e); } return undefined; diff --git a/packages/extension-koni-ui/src/components/StaticContent/BannerGenerator.tsx b/packages/extension-koni-ui/src/components/StaticContent/BannerGenerator.tsx index 64d9dc1ac8f..ce9b3f359a3 100644 --- a/packages/extension-koni-ui/src/components/StaticContent/BannerGenerator.tsx +++ b/packages/extension-koni-ui/src/components/StaticContent/BannerGenerator.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { AppBannerData } from '@subwallet/extension-base/services/mkt-campaign-service/types'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { StaticDataProps } from '@subwallet/extension-koni-ui/components/Modal/Campaign/AppPopupModal'; import Banner from '@subwallet/extension-koni-ui/components/StaticContent/Banner'; import { APP_INSTRUCTION_DATA } from '@subwallet/extension-koni-ui/constants'; @@ -23,7 +24,7 @@ const Component = ({ banners, className, dismissBanner, onClickBanner }: Props) try { return JSON.parse(appInstructionData || '[]') as StaticDataProps[]; } catch (e) { - console.error(e); + defaultLogger.error('Failed to parse app instruction data', e); return []; } diff --git a/packages/extension-koni-ui/src/connector/Ledger/LedgerTransportManager.ts b/packages/extension-koni-ui/src/connector/Ledger/LedgerTransportManager.ts index 2015df078db..26dd34def81 100644 --- a/packages/extension-koni-ui/src/connector/Ledger/LedgerTransportManager.ts +++ b/packages/extension-koni-ui/src/connector/Ledger/LedgerTransportManager.ts @@ -2,10 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import Transport from '@ledgerhq/hw-transport'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { LedgerTypes } from '@subwallet/extension-koni-ui/types'; import { transports } from '@polkadot/hw-ledger-transports'; +const logger = createLogger('LedgerTransportManager'); + export class LedgerTransportManager { private static instance: LedgerTransportManager; private transport: Transport | null = null; @@ -39,7 +42,7 @@ export class LedgerTransportManager { this.transport.on?.('disconnect', () => { this.transport = null; - console.warn('[Ledger] Disconnected'); + logger.warn('[Ledger] Disconnected'); }); return this.transport; diff --git a/packages/extension-koni-ui/src/contexts/DataContext.tsx b/packages/extension-koni-ui/src/contexts/DataContext.tsx index b8918af49ee..266308b0fd4 100644 --- a/packages/extension-koni-ui/src/contexts/DataContext.tsx +++ b/packages/extension-koni-ui/src/contexts/DataContext.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { ping } from '@subwallet/extension-koni-ui/messaging'; import { persistor, store, StoreName } from '@subwallet/extension-koni-ui/stores'; import { getMissionPoolData, getOldChainPrefixData, subscribeAccountsData, subscribeAddressBook, subscribeAliveProcess, subscribeAssetLogoMaps, subscribeAssetRegistry, subscribeAssetSettings, subscribeAuthorizeRequests, subscribeAuthUrls, subscribeBalance, subscribeBuyServices, subscribeBuyTokens, subscribeCampaignBannerData, subscribeCampaignConfirmationData, subscribeCampaignPopupData, subscribeCampaignPopupVisibility, subscribeChainInfoMap, subscribeChainLogoMaps, subscribeChainStakingMetadata, subscribeChainStateMap, subscribeChainStatusMap, subscribeConfirmationRequests, subscribeConfirmationRequestsBitcoin, subscribeConfirmationRequestsCardano, subscribeConfirmationRequestsTon, subscribeConnectWCRequests, subscribeCrowdloan, subscribeKeyringState, subscribeLedgerGenericAllowNetworks, subscribeMantaPayConfig, subscribeMantaPaySyncingState, subscribeMetadataRequests, subscribeMultiChainAssetMap, subscribeNftCollections, subscribeNftItems, subscribePrice, subscribePriorityTokens, subscribeProcessingCampaign, subscribeRewardHistory, subscribeSigningRequests, subscribeStaking, subscribeStakingNominatorMetadata, subscribeStakingReward, subscribeSwapPairs, subscribeTransactionRequests, subscribeTxHistory, subscribeUiSettings, subscribeUnreadNotificationCount, subscribeWalletConnectSessions, subscribeWCNotSupportRequests, subscribeXcmRefMap, subscribeYieldMinAmountPercent, subscribeYieldPoolInfo, subscribeYieldPositionInfo, subscribeYieldReward } from '@subwallet/extension-koni-ui/stores/utils'; @@ -9,6 +10,8 @@ import React from 'react'; import { Provider } from 'react-redux'; import { PersistGate } from 'redux-persist/integration/react'; +const logger = createLogger('DataContext'); + interface DataContextProviderProps { children?: React.ReactElement; } @@ -185,7 +188,7 @@ export function initBasicData () { export const DataContext = React.createContext(_DataContext); export const DataContextProvider = ({ children }: DataContextProviderProps) => { - ping().catch(console.error); + ping().catch((error) => logger.error('Failed to ping', error)); // Init basic data initBasicData(); diff --git a/packages/extension-koni-ui/src/contexts/InjectContext.tsx b/packages/extension-koni-ui/src/contexts/InjectContext.tsx index 31a25a7851a..d3acb138867 100644 --- a/packages/extension-koni-ui/src/contexts/InjectContext.tsx +++ b/packages/extension-koni-ui/src/contexts/InjectContext.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { SubWalletEvmProvider } from '@subwallet/extension-base/page/evm'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { addLazy } from '@subwallet/extension-base/utils'; import { EvmProvider, Injected, InjectedAccountWithMeta, InjectedWindowProvider, Unsubcall } from '@subwallet/extension-inject/types'; import { DisconnectExtensionModal } from '@subwallet/extension-koni-ui/components'; @@ -204,7 +205,7 @@ export const InjectContextProvider: React.FC = ({ children }: Props) => { setSubstrateWallet(inject); }) .catch((e) => { - console.error(e); + defaultLogger.error('Failed to enable substrate wallet', e); promiseMapRef.current = { ...promiseMapRef.current, 'subwallet-js': 'FAIL' }; handleConnectFail(); checkLoading(); @@ -225,7 +226,7 @@ export const InjectContextProvider: React.FC = ({ children }: Props) => { setEvmWallet(wallet); }) .catch((e) => { - console.error(e); + defaultLogger.error('Failed to enable EVM wallet', e); promiseMapRef.current = { ...promiseMapRef.current, SubWallet: 'FAIL' }; handleConnectFail(); checkLoading(); @@ -275,7 +276,7 @@ export const InjectContextProvider: React.FC = ({ children }: Props) => { if (evmWallet) { // Some wallet not fire event on first time - evmWallet.request({ method: 'eth_accounts' }).then(listener).catch(console.warn); + evmWallet.request({ method: 'eth_accounts' }).then(listener).catch((error) => defaultLogger.warn('Failed to request eth_accounts', error)); evmWallet.on('accountsChanged', listener); } diff --git a/packages/extension-koni-ui/src/contexts/MktCampaignModalContext.tsx b/packages/extension-koni-ui/src/contexts/MktCampaignModalContext.tsx index c16839ad5e7..1eb074290b1 100644 --- a/packages/extension-koni-ui/src/contexts/MktCampaignModalContext.tsx +++ b/packages/extension-koni-ui/src/contexts/MktCampaignModalContext.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { APP_POPUP_MODAL, EARNING_WARNING_ANNOUNCEMENT } from '@subwallet/extension-koni-ui/constants'; import { toggleCampaignPopup } from '@subwallet/extension-koni-ui/messaging/campaigns'; import { RootState } from '@subwallet/extension-koni-ui/stores'; @@ -8,6 +9,8 @@ import { ModalContext } from '@subwallet/react-ui'; import React, { useCallback, useContext, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; +const logger = createLogger('MktCampaignModalContext'); + import AppPopupModal from '../components/Modal/Campaign/AppPopupModal'; import { AppContentButton, PopupFrequency } from '../types/staticContent'; @@ -54,7 +57,7 @@ export const MktCampaignModalContextProvider = ({ children }: MktCampaignModalCo }, [activeModal, isPopupVisible, mktCampaignModal?.type, storageEarningPosition]); const hideModal = useCallback(() => { - toggleCampaignPopup({ value: false }).catch((e) => console.error(e)).finally(() => { + toggleCampaignPopup({ value: false }).catch((e) => logger.error('Failed to toggle campaign popup', e)).finally(() => { inactiveModal(APP_POPUP_MODAL); setMktCampaignModal(undefined); }); diff --git a/packages/extension-koni-ui/src/contexts/ScannerContext.tsx b/packages/extension-koni-ui/src/contexts/ScannerContext.tsx index dc2892242e3..14537398a8c 100644 --- a/packages/extension-koni-ui/src/contexts/ScannerContext.tsx +++ b/packages/extension-koni-ui/src/contexts/ScannerContext.tsx @@ -3,6 +3,7 @@ import { ResponseParseTransactionSubstrate, ResponseQrParseRLP, SignerDataType } from '@subwallet/extension-base/background/KoniTypes'; import { _isChainEnabled } from '@subwallet/extension-base/services/chain-service/utils'; +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { createTransactionFromRLP, Transaction } from '@subwallet/extension-base/utils/eth'; import { MULTIPART, SCANNER_QR_STEP } from '@subwallet/extension-koni-ui/constants'; import { useTranslation } from '@subwallet/extension-koni-ui/hooks'; @@ -416,7 +417,7 @@ export const ScannerContextProvider = ({ children }: ScannerContextProviderProps return hexStripPrefix(signature); } catch (e) { - console.error(e); + defaultLogger.error('Failed to process signature', e); throw new Error((e as Error).message); } } diff --git a/packages/extension-koni-ui/src/contexts/ThemeContext.tsx b/packages/extension-koni-ui/src/contexts/ThemeContext.tsx index 1353e80a574..ee5c88ba267 100644 --- a/packages/extension-koni-ui/src/contexts/ThemeContext.tsx +++ b/packages/extension-koni-ui/src/contexts/ThemeContext.tsx @@ -3,6 +3,7 @@ import type { ThemeProps } from '../types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { GLOBAL_ALERT_MODAL } from '@subwallet/extension-koni-ui/constants'; import { DataContext } from '@subwallet/extension-koni-ui/contexts/DataContext'; import { useExtensionDisplayModes } from '@subwallet/extension-koni-ui/hooks'; @@ -16,6 +17,8 @@ import styled, { createGlobalStyle, ThemeProvider as StyledComponentThemeProvide import { Theme } from '../types'; +const logger = createLogger('ThemeContext'); + interface Props { children: React.ReactNode; themeConfig: SwThemeConfig @@ -486,7 +489,7 @@ export function ThemeProvider ({ children }: ThemeProviderProps): React.ReactEle useEffect(() => { dataContext.awaitStores(['settings']).then(() => { setThemeReady(true); - }).catch(console.error); + }).catch((error) => logger.error('Failed to await stores', error)); }, [dataContext]); // Reduce number of re-rendering diff --git a/packages/extension-koni-ui/src/contexts/WalletModalContextProvider.tsx b/packages/extension-koni-ui/src/contexts/WalletModalContextProvider.tsx index 1c638aa134c..621e589441b 100644 --- a/packages/extension-koni-ui/src/contexts/WalletModalContextProvider.tsx +++ b/packages/extension-koni-ui/src/contexts/WalletModalContextProvider.tsx @@ -1,6 +1,7 @@ // Copyright 2019-2022 @polkadot/extension-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { createLogger } from '@subwallet/extension-base/utils/logger'; import { AccountMigrationInProgressWarningModal, AccountTokenAddressModal, AddressQrModal, AlertModal, AttachAccountModal, ClaimDappStakingRewardsModal, CreateAccountModal, DeriveAccountActionModal, DeriveAccountListModal, ImportAccountModal, ImportSeedModal, NewSeedModal, RemindBackupSeedPhraseModal, RemindDuplicateAccountNameModal, RequestCameraAccessModal, RequestCreatePasswordModal, SelectAddressFormatModal, SwitchNetworkAuthorizeModal, TransactionProcessDetailModal, TransactionStepsModal } from '@subwallet/extension-koni-ui/components'; import { CustomizeModal } from '@subwallet/extension-koni-ui/components/Modal/Customize/CustomizeModal'; import { AccountDeriveActionProps } from '@subwallet/extension-koni-ui/components/Modal/DeriveAccountActionModal'; @@ -21,6 +22,8 @@ import React, { useCallback, useContext, useEffect, useMemo, useState } from 're import { useSelector } from 'react-redux'; import { useSearchParams } from 'react-router-dom'; +const logger = createLogger('WalletModalContextProvider'); + import { AddressQrModalProps } from '../components/Modal/Global/AddressQrModal'; import { UnlockModal } from '../components/Modal/UnlockModal'; @@ -351,7 +354,7 @@ export const WalletModalContextProvider = ({ children }: Props) => { }, [activeModal, inactiveModals, searchParams]); useEffect(() => { - getConfig().then(setTimeBackUp).catch(console.error); + getConfig().then(setTimeBackUp).catch((error) => logger.error('Failed to get config', error)); }, [getConfig, setTimeBackUp]); useEffect(() => { diff --git a/packages/extension-koni-ui/src/hooks/account/useHandleMantaPaySync.tsx b/packages/extension-koni-ui/src/hooks/account/useHandleMantaPaySync.tsx index d32419ded71..d438f70deaf 100644 --- a/packages/extension-koni-ui/src/hooks/account/useHandleMantaPaySync.tsx +++ b/packages/extension-koni-ui/src/hooks/account/useHandleMantaPaySync.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { NotificationType } from '@subwallet/extension-base/background/KoniTypes'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import useTranslation from '@subwallet/extension-koni-ui/hooks/common/useTranslation'; import { initSyncMantaPay, windowOpen } from '@subwallet/extension-koni-ui/messaging'; import { Button } from '@subwallet/react-ui'; @@ -11,6 +12,8 @@ import { useNavigate } from 'react-router-dom'; import useNotification from '../common/useNotification'; import useIsPopup from '../dom/useIsPopup'; +const logger = createLogger('useHandleMantaPaySync'); + export default function useHandleMantaPaySync () { const notify = useNotification(); const { t } = useTranslation(); @@ -27,14 +30,14 @@ export default function useHandleMantaPaySync () { return useCallback((address: string) => { const onOk = () => { initSyncMantaPay(address) - .catch(console.error); + .catch((error) => logger.error('Failed to init sync MantaPay', error)); if (isPopup) { windowOpen({ allowedPath: '/accounts/detail', subPath: `/${address}` }) - .catch(console.warn); + .catch((error) => logger.warn('Failed to open window', error)); } else { navigate(`/accounts/detail/${address}`); } diff --git a/packages/extension-koni-ui/src/hooks/balance/useGetBalance.ts b/packages/extension-koni-ui/src/hooks/balance/useGetBalance.ts index 5ab82b87447..da2b0293e4d 100644 --- a/packages/extension-koni-ui/src/hooks/balance/useGetBalance.ts +++ b/packages/extension-koni-ui/src/hooks/balance/useGetBalance.ts @@ -5,12 +5,15 @@ import { _ChainInfo } from '@subwallet/chain-list/types'; import { AmountData, AmountDataWithId, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes'; import { _getChainNativeTokenSlug } from '@subwallet/extension-base/services/chain-service/utils'; import { BalanceType } from '@subwallet/extension-base/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import useTranslation from '@subwallet/extension-koni-ui/hooks/common/useTranslation'; import { cancelSubscription, getAvailableBalanceByType, getFreeBalance, subscribeAvailableBalanceByType, subscribeFreeBalance, updateAssetSetting } from '@subwallet/extension-koni-ui/messaging'; import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react'; import { useSelector } from '../common'; +const logger = createLogger('useGetBalance'); + const DEFAULT_BALANCE = { value: '0', symbol: '', decimals: 18 }; const useGetBalance = (chain = '', address = '', tokenSlug = '', isSubscribe = false, extrinsicType?: ExtrinsicType, balanceType?: BalanceType) => { @@ -93,7 +96,7 @@ const useGetBalance = (chain = '', address = '', tokenSlug = '', isSubscribe = f return (e: Error) => { !cancel && setError(t('ui.BALANCE.hook.balance.useGetBalance.unableToGetBalanceReEnableNetwork')); !cancel && setter(DEFAULT_BALANCE); - console.error(e); + logger.error('Unable to get balance', e); }; }; @@ -160,7 +163,7 @@ const useGetBalance = (chain = '', address = '', tokenSlug = '', isSubscribe = f setIsLoading(true); setError(null); Object.keys(idMap).forEach((id) => { - cancelSubscription(id).catch(console.error); + cancelSubscription(id).catch((error) => logger.error('Failed to cancel subscription', error)); }); }; }, [isRefresh, address, assetRegistry, chain, chainInfo?.name, isChainActive, isSubscribe, isTokenActive, nativeTokenActive, nativeTokenSlug, t, tokenSlug, extrinsicType, balanceType]); diff --git a/packages/extension-koni-ui/src/hooks/browser/useUpgradeFireFoxVersion.ts b/packages/extension-koni-ui/src/hooks/browser/useUpgradeFireFoxVersion.ts index 86938da4d24..521bebf82d6 100644 --- a/packages/extension-koni-ui/src/hooks/browser/useUpgradeFireFoxVersion.ts +++ b/packages/extension-koni-ui/src/hooks/browser/useUpgradeFireFoxVersion.ts @@ -1,6 +1,7 @@ // Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { defaultLogger } from '@subwallet/extension-base/utils/logger'; import { UPGRADE_FIREFOX_VERSION } from '@subwallet/extension-koni-ui/constants'; import { getVersionBrowser } from '@subwallet/extension-koni-ui/utils'; import { Dispatch, SetStateAction, useCallback, useMemo } from 'react'; @@ -27,7 +28,7 @@ const useUpgradeFireFoxVersion = (): SetStateUpgradeFireFoxVersion => { return state_ && !!permissions_.origins && permissions_.origins.length > 0; } catch (e) { - console.error(e); + defaultLogger.error('Failed to check permission access', e); return false; } diff --git a/packages/extension-koni-ui/src/hooks/chain/useAssetChecker.tsx b/packages/extension-koni-ui/src/hooks/chain/useAssetChecker.tsx index 4ecdac2d879..dd364418773 100644 --- a/packages/extension-koni-ui/src/hooks/chain/useAssetChecker.tsx +++ b/packages/extension-koni-ui/src/hooks/chain/useAssetChecker.tsx @@ -3,6 +3,7 @@ import { NotificationType } from '@subwallet/extension-base/background/KoniTypes'; import { _ChainConnectionStatus } from '@subwallet/extension-base/services/chain-service/types'; +import { createLogger } from '@subwallet/extension-base/utils/logger'; import useNotification from '@subwallet/extension-koni-ui/hooks/common/useNotification'; import useTranslation from '@subwallet/extension-koni-ui/hooks/common/useTranslation'; import { enableChain, updateAssetSetting } from '@subwallet/extension-koni-ui/messaging'; @@ -11,6 +12,8 @@ import { Button } from '@subwallet/react-ui'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useSelector } from 'react-redux'; +const logger = createLogger('useAssetChecker'); + export default function useAssetChecker () { const { t } = useTranslation(); const { chainInfoMap, chainStateMap, chainStatusMap } = useSelector((root: RootState) => root.chainStore); @@ -57,7 +60,7 @@ export default function useAssetChecker () { }).then(() => { setEnablingAsset(assetSlug); notify({ message: t('ui.NETWORK.hook.chain.useAssetChecker.nameIsTurningOn', { replace: { name: assetInfo?.symbol } }), duration: 1.5 }); - }).catch(console.error); + }).catch((error) => logger.error('Failed to update asset setting', error)); }; const btn =