diff --git a/eslint.config.mjs b/eslint.config.mjs index c7ad6bc5..e486f3f1 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -108,6 +108,17 @@ export default [ message: 'DOM APIs are not available in background scripts', }, ], + 'no-restricted-imports': [ + 'error', + { + patterns: [ + { + group: ['ui/*', '**/ui/**'], + message: 'UI components/modules cannot be imported into background scripts', + }, + ], + }, + ], }, }, ]; diff --git a/src/background/controller/provider/controller.ts b/src/background/controller/provider/controller.ts index 47ce4179..48948f27 100644 --- a/src/background/controller/provider/controller.ts +++ b/src/background/controller/provider/controller.ts @@ -2,14 +2,12 @@ import { TypedDataUtils, SignTypedDataVersion, normalize } from '@metamask/eth-s import * as fcl from '@onflow/fcl'; import BigNumber from 'bignumber.js'; import { ethErrors } from 'eth-rpc-errors'; -import { isHexString, intToHex } from 'ethereumjs-util'; +import { intToHex } from 'ethereumjs-util'; import { ethers } from 'ethers'; import RLP from 'rlp'; import Web3 from 'web3'; -import { stringToHex } from 'web3-utils'; -import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/ui/utils/address'; -import { signWithKey } from '@/ui/utils/modules/passkey.js'; +import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { permissionService, sessionService, @@ -23,6 +21,9 @@ import { storage } from '../../webapi'; import BaseController from '../base'; import Wallet from '../wallet'; +// eslint-disable-next-line import/order,no-restricted-imports +import { signWithKey } from '@/ui/utils/modules/passkey.js'; + interface Web3WalletPermission { // The name of the method corresponding to the permission parentCapability: string; @@ -69,6 +70,7 @@ function createAndEncodeCOAOwnershipProof( return encodedData; // Convert the encoded data to a hexadecimal string for easy display or transmission } +// Should not be in controller async function signMessage(msgParams, opts = {}) { const web3 = new Web3(); const textData = msgParams.data; @@ -386,7 +388,8 @@ class ProviderController extends BaseController { }); } }; - + /* + // Should not be in controller personalSign = async ({ data, approvalRes, session }) => { if (!data.params) return; const [string, from] = data.params; @@ -400,7 +403,7 @@ class ProviderController extends BaseController { }); return result; }; - + */ private _checkAddress = async (address) => { return normalize(address).toLowerCase(); }; diff --git a/src/background/controller/provider/rpcFlow.ts b/src/background/controller/provider/rpcFlow.ts index 8540079b..0c553e95 100644 --- a/src/background/controller/provider/rpcFlow.ts +++ b/src/background/controller/provider/rpcFlow.ts @@ -1,7 +1,7 @@ import { ethErrors } from 'eth-rpc-errors'; import eventBus from '@/eventBus'; -import { isValidEthereumAddress } from '@/ui/utils/address'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { keyringService, notificationService, diff --git a/src/background/controller/wallet.ts b/src/background/controller/wallet.ts index ef863905..5a902533 100644 --- a/src/background/controller/wallet.ts +++ b/src/background/controller/wallet.ts @@ -11,6 +11,7 @@ import { getAuth } from 'firebase/auth'; import web3, { TransactionError } from 'web3'; import eventBus from '@/eventBus'; +import { isValidEthereumAddress, withPrefix } from '@/shared/utils/address'; import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; import { keyringService, @@ -43,13 +44,9 @@ import fetchConfig from 'background/utils/remoteConfig'; import { notification, storage } from 'background/webapi'; import { openIndexPage } from 'background/webapi/tab'; import { INTERNAL_REQUEST_ORIGIN, EVENTS, KEYRING_TYPE } from 'consts'; -import placeholder from 'ui/FRWAssets/image/placeholder.png'; -import { getStoragedAccount } from 'ui/utils'; -import { isValidEthereumAddress, withPrefix } from 'ui/utils/address'; -import { openInternalPageInTab } from 'ui/utils/webapi'; -import { pk2PubKey, seed2PubKey, formPubKey } from '../../ui/utils/modules/passkey'; import { fclTestnetConfig, fclMainnetConfig } from '../fclConfig'; +import placeholder from '../images/placeholder.png'; import { type CoinItem } from '../service/coinList'; import DisplayKeyring from '../service/keyring/display'; import type { NFTData, NFTModel, StorageInfo, WalletResponse } from '../service/networkModel'; @@ -58,10 +55,14 @@ import type { Account } from '../service/preference'; import { StorageEvaluator } from '../service/storage-evaluator'; import type { UserInfoStore } from '../service/user'; import defaultConfig from '../utils/defaultConfig.json'; +import { getStoragedAccount } from '../utils/getStoragedAccount'; import BaseController from './base'; import provider from './provider'; +// eslint-disable-next-line import/order,no-restricted-imports +import { pk2PubKey, seed2PubKey, formPubKey } from '@/ui/utils/modules/passkey.js'; + interface Keyring { type: string; getAccounts(): Promise; @@ -287,7 +288,7 @@ export class WalletController extends BaseController { await passwordService.clear(); sessionService.broadcastEvent('accountsChanged', []); sessionService.broadcastEvent('lock'); - openInternalPageInTab('addwelcome', true); + openIndexPage('addwelcome'); await this.switchNetwork(switchingTo); }; @@ -301,7 +302,7 @@ export class WalletController extends BaseController { await passwordService.clear(); sessionService.broadcastEvent('accountsChanged', []); sessionService.broadcastEvent('lock'); - openInternalPageInTab('reset', true); + openIndexPage('reset'); await this.switchNetwork(switchingTo); }; @@ -316,7 +317,7 @@ export class WalletController extends BaseController { sessionService.broadcastEvent('accountsChanged', []); sessionService.broadcastEvent('lock'); - openInternalPageInTab('restore', true); + openIndexPage('restore'); await this.switchNetwork(switchingTo); }; diff --git a/src/background/images/placeholder.png b/src/background/images/placeholder.png new file mode 100644 index 00000000..9ed0370f Binary files /dev/null and b/src/background/images/placeholder.png differ diff --git a/src/background/index.ts b/src/background/index.ts index ef7179d1..89dbe84e 100644 --- a/src/background/index.ts +++ b/src/background/index.ts @@ -10,9 +10,9 @@ import { } from 'firebase/auth'; import eventBus from '@/eventBus'; +import { Message } from '@/shared/utils/messaging'; import type { WalletController } from 'background/controller/wallet'; import { EVENTS } from 'consts'; -import { Message } from 'utils'; import { providerController, walletController } from './controller'; import { preAuthzServiceDefinition } from './controller/serviceDefinition'; diff --git a/src/background/service/mixpanel.ts b/src/background/service/mixpanel.ts index 10c2e158..ed0e2c6e 100644 --- a/src/background/service/mixpanel.ts +++ b/src/background/service/mixpanel.ts @@ -25,14 +25,16 @@ class MixpanelService { this.initialized = true; } track(eventName: T, properties?: TrackingEvents[T]) { - eventBus.emit('track_event', { + chrome.runtime.sendMessage({ + msg: 'track_event', eventName, properties, }); } time(eventName: T) { - eventBus.emit('track_time', { + chrome.runtime.sendMessage({ + msg: 'track_time', eventName, }); } @@ -40,7 +42,8 @@ class MixpanelService { identify(userId: string) { if (!this.initialized) return; - eventBus.emit('track_user', { + chrome.runtime.sendMessage({ + msg: 'track_user', userId, }); } @@ -48,7 +51,9 @@ class MixpanelService { reset() { if (!this.initialized) return; - eventBus.emit('track_reset'); + chrome.runtime.sendMessage({ + msg: 'track_reset', + }); } } diff --git a/src/background/service/openapi.ts b/src/background/service/openapi.ts index eb687647..a5d6e8ca 100644 --- a/src/background/service/openapi.ts +++ b/src/background/service/openapi.ts @@ -16,14 +16,14 @@ import type { TokenInfo } from 'flow-native-token-registry'; import log from 'loglevel'; import { storage } from '@/background/webapi'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { getStringFromHashAlgo, getStringFromSignAlgo } from '@/shared/utils/algo'; +import { getPeriodFrequency } from '@/shared/utils/getPeriodFrequency'; import { createPersistStore, getScripts, findKeyAndInfo } from 'background/utils'; import { getFirbaseConfig, getFirbaseFunctionUrl } from 'background/utils/firebaseConfig'; import fetchConfig from 'background/utils/remoteConfig'; import { INITIAL_OPENAPI_URL, WEB_NEXT_URL } from 'consts'; -import { isValidEthereumAddress } from 'ui/utils/address'; -import { getPeriodFrequency } from '../../utils'; import { fclMainnetConfig, fclTestnetConfig } from '../fclConfig'; import { diff --git a/src/background/service/userWallet.ts b/src/background/service/userWallet.ts index 71333ebc..2ac6545b 100644 --- a/src/background/service/userWallet.ts +++ b/src/background/service/userWallet.ts @@ -3,14 +3,16 @@ import * as fcl from '@onflow/fcl'; import { getApp } from 'firebase/app'; import { getAuth, signInAnonymously } from 'firebase/auth'; +import { withPrefix } from '@/shared/utils/address'; import { getHashAlgo, getSignAlgo } from '@/shared/utils/algo'; -import { withPrefix } from '@/ui/utils/address'; +// eslint-disable-next-line no-restricted-imports import { findAddressWithSeed, findAddressWithPK } from '@/ui/utils/modules/findAddressWithPK'; +// eslint-disable-next-line no-restricted-imports import { signWithKey, seed2PubKey } from '@/ui/utils/modules/passkey.js'; import wallet from 'background/controller/wallet'; import { keyringService, mixpanelTrack, openapiService } from 'background/service'; import { createPersistStore } from 'background/utils'; -import { getStoragedAccount } from 'ui/utils'; +import { getStoragedAccount } from 'background/utils/getStoragedAccount'; import { storage } from '../webapi'; diff --git a/src/background/utils/getStoragedAccount.ts b/src/background/utils/getStoragedAccount.ts new file mode 100644 index 00000000..200db6b3 --- /dev/null +++ b/src/background/utils/getStoragedAccount.ts @@ -0,0 +1,30 @@ +import { storage } from '@/background/webapi'; + +export const getStoragedAccount = async () => { + const accountIndex = (await storage.get('currentAccountIndex')) || 0; + const currentId = (await storage.get('currentId')) || null; + const loggedInAccounts = (await storage.get('loggedInAccounts')) || []; + let account; + + // Check if currentId is provided and valid + if (currentId !== null) { + // Find account with the currentId + account = loggedInAccounts.find((acc) => acc.id === currentId); + + // If no account is found with currentId, default to accountIndex + if (!account) { + account = loggedInAccounts[accountIndex]; + } + } else { + // If currentId is not provided, use accountIndex + account = loggedInAccounts[accountIndex]; + } + + if (!account) { + // Handle the case when no account is found + throw new Error('Account info not found.'); + } else { + // Return account + return account; + } +}; diff --git a/src/content-script/index.ts b/src/content-script/index.ts index b5a5793d..0eebe0dd 100644 --- a/src/content-script/index.ts +++ b/src/content-script/index.ts @@ -1,7 +1,7 @@ import { nanoid } from 'nanoid'; import { v4 as uuid } from 'uuid'; -import { Message } from 'utils'; +import { Message } from '@/shared/utils/messaging'; const channelName = nanoid(); diff --git a/src/eventBus.ts b/src/eventBus.ts index c6598bde..0ef4ae48 100644 --- a/src/eventBus.ts +++ b/src/eventBus.ts @@ -1,5 +1,9 @@ type Listener = (params?: any) => void; - +/** + * EventBus is a singleton class that allows for event-based communication between different parts of the application. + * It provides methods for emitting events, listening for events, and removing event listeners. + * IMPORTANT: This only works in one thread - either the background, content script, or UI. It does not work across threads. + */ class EventBus { events: Record = {}; diff --git a/src/shared/types/tracking-types.ts b/src/shared/types/tracking-types.ts index 29e032cc..4a8bbf2f 100644 --- a/src/shared/types/tracking-types.ts +++ b/src/shared/types/tracking-types.ts @@ -101,3 +101,29 @@ export type TrackingEvents = { methods: KeyType[]; // Array of providers used in the multi-backup, GoogleDrive, iCloud, Seed }; }; + +export type TrackEventMessage = { + msg: 'track_event'; + eventName: T; + properties?: TrackingEvents[T]; +}; + +export type TrackUserMessage = { + msg: 'track_user'; + userId: string; +}; + +export type TrackResetMessage = { + msg: 'track_reset'; +}; + +export type TrackTimeMessage = { + msg: 'track_time'; + eventName: keyof TrackingEvents; +}; + +export type TrackMessage = + | TrackEventMessage + | TrackUserMessage + | TrackResetMessage + | TrackTimeMessage; diff --git a/src/ui/utils/address.ts b/src/shared/utils/address.ts similarity index 89% rename from src/ui/utils/address.ts rename to src/shared/utils/address.ts index 5d32d334..827544bb 100644 --- a/src/ui/utils/address.ts +++ b/src/shared/utils/address.ts @@ -1,13 +1,14 @@ -import { AccountKey } from 'background/service/networkModel'; import HDWallet from 'ethereum-hdwallet'; +import { type AccountKey } from 'background/service/networkModel'; + export function sansPrefix(address) { - if (address == null) return null; + if (address === null) return null; return address.replace(/^0x/, '').replace(/^Fx/, ''); } export function withPrefix(address): string | null { - if (address == null) return null; + if (address === null) return null; return '0x' + sansPrefix(address); } diff --git a/src/shared/utils/getPeriodFrequency.ts b/src/shared/utils/getPeriodFrequency.ts new file mode 100644 index 00000000..94db5532 --- /dev/null +++ b/src/shared/utils/getPeriodFrequency.ts @@ -0,0 +1,20 @@ +import { Period, PeriodFrequency } from '@/background/service/networkModel'; + +export const getPeriodFrequency = (period: Period): PeriodFrequency => { + switch (period) { + case Period.oneDay: + return PeriodFrequency.halfHour; + case Period.oneWeek: + return PeriodFrequency.oneHour; + case Period.oneMonth: + return PeriodFrequency.oneDay; + case Period.threeMonth: + return PeriodFrequency.oneDay; + case Period.oneYear: + return PeriodFrequency.threeDay; + case Period.all: + return PeriodFrequency.oneWeek; + default: + return PeriodFrequency.oneDay; + } +}; diff --git a/src/utils/message/broadcastChannelMessage.ts b/src/shared/utils/message/broadcastChannelMessage.ts similarity index 100% rename from src/utils/message/broadcastChannelMessage.ts rename to src/shared/utils/message/broadcastChannelMessage.ts diff --git a/src/utils/message/index.ts b/src/shared/utils/message/index.ts similarity index 100% rename from src/utils/message/index.ts rename to src/shared/utils/message/index.ts diff --git a/src/utils/message/portMessage.ts b/src/shared/utils/message/portMessage.ts similarity index 100% rename from src/utils/message/portMessage.ts rename to src/shared/utils/message/portMessage.ts diff --git a/src/shared/utils/messaging.ts b/src/shared/utils/messaging.ts new file mode 100644 index 00000000..8e3ad4a2 --- /dev/null +++ b/src/shared/utils/messaging.ts @@ -0,0 +1,9 @@ +import BroadcastChannelMessage from './message/broadcastChannelMessage'; +import PortMessage from './message/portMessage'; + +const Message = { + BroadcastChannelMessage, + PortMessage, +}; + +export { Message }; diff --git a/src/ui/FRWComponent/FRWChildProfile.tsx b/src/ui/FRWComponent/FRWChildProfile.tsx index 99b8592f..3dbf1a8d 100644 --- a/src/ui/FRWComponent/FRWChildProfile.tsx +++ b/src/ui/FRWComponent/FRWChildProfile.tsx @@ -1,8 +1,8 @@ import { Box, Typography, Avatar } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; const tempEmoji = { emoji: '🥥', diff --git a/src/ui/FRWComponent/FRWDropdownProfileCard.tsx b/src/ui/FRWComponent/FRWDropdownProfileCard.tsx index 293667bb..19536df1 100644 --- a/src/ui/FRWComponent/FRWDropdownProfileCard.tsx +++ b/src/ui/FRWComponent/FRWDropdownProfileCard.tsx @@ -11,8 +11,8 @@ import { import { makeStyles } from '@mui/styles'; import React, { useState, useEffect, useCallback } from 'react'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet, formatAddress, isEmoji } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; const tempEmoji = { emoji: '🥥', diff --git a/src/ui/FRWComponent/FRWProfileCard.tsx b/src/ui/FRWComponent/FRWProfileCard.tsx index 1be00f3d..51af2c9d 100644 --- a/src/ui/FRWComponent/FRWProfileCard.tsx +++ b/src/ui/FRWComponent/FRWProfileCard.tsx @@ -2,8 +2,8 @@ import { Box, Typography, Avatar, Skeleton } from '@mui/material'; import { makeStyles } from '@mui/styles'; import React, { useState, useEffect, useCallback } from 'react'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; const tempEmoji = { emoji: '🥥', diff --git a/src/ui/FRWComponent/FWDropDownProfile.tsx b/src/ui/FRWComponent/FWDropDownProfile.tsx index 258bf4cb..745a37be 100644 --- a/src/ui/FRWComponent/FWDropDownProfile.tsx +++ b/src/ui/FRWComponent/FWDropDownProfile.tsx @@ -11,8 +11,8 @@ import { import { makeStyles } from '@mui/styles'; import React, { useState, useEffect, useCallback } from 'react'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet, isEmoji, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; const tempEmoji = { emoji: '🥥', diff --git a/src/ui/FRWComponent/FWMoveDropdown.tsx b/src/ui/FRWComponent/FWMoveDropdown.tsx index 5062c2e7..01cbf813 100644 --- a/src/ui/FRWComponent/FWMoveDropdown.tsx +++ b/src/ui/FRWComponent/FWMoveDropdown.tsx @@ -11,8 +11,8 @@ import { import { makeStyles } from '@mui/styles'; import React, { useState, useEffect, useCallback } from 'react'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet, isEmoji, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; const tempEmoji = { emoji: '🥥', diff --git a/src/ui/index.tsx b/src/ui/index.tsx index 38a41aac..86f8df56 100644 --- a/src/ui/index.tsx +++ b/src/ui/index.tsx @@ -2,7 +2,7 @@ import React, { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import eventBus from '@/eventBus'; -import { Message } from '@/utils'; +import { Message } from '@/shared/utils/messaging'; import { EVENTS } from 'consts'; import { getUITypeName } from 'ui/utils'; diff --git a/src/ui/utils/mixpanelBrowserService.ts b/src/ui/utils/mixpanelBrowserService.ts index 1b08f09a..0a362d23 100644 --- a/src/ui/utils/mixpanelBrowserService.ts +++ b/src/ui/utils/mixpanelBrowserService.ts @@ -1,9 +1,9 @@ import mixpanel from 'mixpanel-browser'; -import eventBus from '@/eventBus'; -import type { TrackingEvents } from '@/shared/types/tracking-types'; +import type { TrackingEvents, TrackMessage } from '@/shared/types/tracking-types'; -import { version } from '../../../package.json'; +import packageJson from '../../../package.json'; +const { version } = packageJson; // Super properties that will be sent with every event type SuperProperties = { @@ -16,42 +16,52 @@ type SuperProperties = { class MixpanelBrowserService { private static instance: MixpanelBrowserService; private initialized = false; - private boundTrackEventHandler: (params: { - eventName: T; - properties?: TrackingEvents[T]; - }) => void; - private boundTrackUserHandler: (params: { userId: string }) => void; - private boundTrackResetHandler: () => void; - private boundTrackTimeHandler: (params: { eventName: keyof TrackingEvents }) => void; + + private mixpanelEventMessageHandler: (message: TrackMessage) => void; + private constructor() { this.initMixpanel(); - // Store bound handlers so we can remove them later - this.boundTrackEventHandler = (params: { - eventName: T; - properties?: TrackingEvents[T]; - }) => { - this.track(params.eventName, params.properties); - }; - this.boundTrackUserHandler = (params: { userId: string }) => { - this.identify(params.userId); - }; - this.boundTrackResetHandler = () => { - this.reset(); - }; - this.boundTrackTimeHandler = (params: { eventName: keyof TrackingEvents }) => { - this.time(params.eventName); + this.mixpanelEventMessageHandler = (message: TrackMessage) => { + switch (message.msg) { + case 'track_event': + // TypeScript knows eventName and properties are available here + this.track(message.eventName, message.properties); + break; + case 'track_user': + // TypeScript knows userId is available here + this.identify(message.userId); + break; + case 'track_reset': + // TypeScript knows this is just a reset message + this.reset(); + break; + case 'track_time': + // TypeScript knows eventName is available here + this.time(message.eventName); + break; + } }; this.setupEventListener(); } private setupEventListener() { - // Bind event handlers to the event bus - eventBus.addEventListener('track_event', this.boundTrackEventHandler); - eventBus.addEventListener('track_user', this.boundTrackUserHandler); - eventBus.addEventListener('track_reset', this.boundTrackResetHandler); - eventBus.addEventListener('track_time', this.boundTrackTimeHandler); + // Listen for messages from the background script + // This feels blunt as we have to switch on the message type + // TODO: We should use a more elegant approach to filter messages based on the sender + chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { + switch (message.msg) { + case 'track_event': + case 'track_user': + case 'track_reset': + case 'track_time': + this.mixpanelEventMessageHandler(message); + sendResponse({ success: true }); + break; + } + return true; // Keep the message channel open for asynchronous response + }); } init() { @@ -59,18 +69,8 @@ class MixpanelBrowserService { // Mixpanel is initialized in the constructor } cleanup() { - if (this.boundTrackEventHandler) { - eventBus.removeEventListener('track_event', this.boundTrackEventHandler); - } - if (this.boundTrackUserHandler) { - eventBus.removeEventListener('track_user', this.boundTrackUserHandler); - } - if (this.boundTrackResetHandler) { - eventBus.removeEventListener('track_reset', this.boundTrackResetHandler); - } - if (this.boundTrackTimeHandler) { - eventBus.removeEventListener('track_time', this.boundTrackTimeHandler); - } + // Remove the event listener + chrome.runtime.onMessage.removeListener(this.mixpanelEventMessageHandler); } static getInstance(): MixpanelBrowserService { @@ -102,7 +102,7 @@ class MixpanelBrowserService { mixpanel.init(token, { debug: process.env.NODE_ENV !== 'production', - track_pageview: true, + track_pageview: 'full-url', // track the full url including the hash persistence: 'localStorage', batch_requests: true, batch_size: 10, diff --git a/src/ui/utils/saveStorage.ts b/src/ui/utils/saveStorage.ts index 415a99d2..0f5196ee 100644 --- a/src/ui/utils/saveStorage.ts +++ b/src/ui/utils/saveStorage.ts @@ -24,34 +24,3 @@ export const saveIndex = async (username = '', userId = null) => { await storage.set('currentId', userId); } }; - -export const getStoragedAccount = async () => { - const accountIndex = (await storage.get('currentAccountIndex')) || 0; - const currentId = (await storage.get('currentId')) || null; - const loggedInAccounts = (await storage.get('loggedInAccounts')) || []; - console.log('loggedInAccounts ', loggedInAccounts); - console.log('currentId ', currentId); - let account; - - // Check if currentId is provided and valid - if (currentId !== null) { - // Find account with the currentId - account = loggedInAccounts.find((acc) => acc.id === currentId); - - // If no account is found with currentId, default to accountIndex - if (!account) { - account = loggedInAccounts[accountIndex]; - } - } else { - // If currentId is not provided, use accountIndex - account = loggedInAccounts[accountIndex]; - } - - if (!account) { - // Handle the case when no account is found - throw new Error('Account info not found.'); - } else { - // Return account - return account; - } -}; diff --git a/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx b/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx index 7f1f7662..05650d38 100644 --- a/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthConnect/index.tsx @@ -3,12 +3,12 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import enableBg from 'ui/FRWAssets/image/enableBg.png'; import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; import { LLPrimaryButton, LLSecondaryButton, LLSpinner, LLConnectLoading } from 'ui/FRWComponent'; import { useApproval, useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; import CheckCircleIcon from '../../../../../../components/iconfont/IconCheckmark'; diff --git a/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx b/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx index a6481b1d..26ef2447 100644 --- a/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthEnable/index.tsx @@ -3,12 +3,12 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocation, useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import enableBg from 'ui/FRWAssets/image/enableBg.png'; import flowgrey from 'ui/FRWAssets/svg/flow-grey.svg'; import linkGlobe from 'ui/FRWAssets/svg/linkGlobe.svg'; import { LLPrimaryButton, LLSecondaryButton, LLSpinner, LLConnectLoading } from 'ui/FRWComponent'; import { useApproval, useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; // import { CHAINS_ENUM } from 'consts'; interface ConnectProps { diff --git a/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx index a6a9c4d9..478b94be 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSignType/index.tsx @@ -4,11 +4,11 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; // import { CHAINS_ENUM } from 'consts'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLConnectLoading, LLLinkingLoading } from '@/ui/FRWComponent'; import { type UserInfoResponse } from 'background/service/networkModel'; import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; import { useApproval, useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; interface ConnectProps { params: any; diff --git a/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx index be81817d..66f1f088 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSignV1/index.tsx @@ -4,11 +4,11 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; // import { CHAINS_ENUM } from 'consts'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLConnectLoading, LLLinkingLoading } from '@/ui/FRWComponent'; import { type UserInfoResponse } from 'background/service/networkModel'; import { LLPrimaryButton, LLSecondaryButton } from 'ui/FRWComponent'; import { useApproval, useWallet } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; interface ConnectProps { params: any; diff --git a/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx b/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx index 99e94e30..c5d58e1f 100644 --- a/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx +++ b/src/ui/views/Approval/components/EthApproval/EthSuggest/index.tsx @@ -5,10 +5,10 @@ import { useTranslation } from 'react-i18next'; import { useLocation } from 'react-router-dom'; import { storage } from '@/background/webapi'; +import { withPrefix } from '@/shared/utils/address'; import { EVM_ENDPOINT } from 'consts'; import { LLPrimaryButton, LLSecondaryButton, LLConnectLoading } from 'ui/FRWComponent'; import { useApproval, useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; // import EthMove from '../EthMove'; const EthSuggest = (data) => { diff --git a/src/ui/views/Dashboard/Components/MenuDrawer.tsx b/src/ui/views/Dashboard/Components/MenuDrawer.tsx index 82b4e556..d600b5e2 100644 --- a/src/ui/views/Dashboard/Components/MenuDrawer.tsx +++ b/src/ui/views/Dashboard/Components/MenuDrawer.tsx @@ -17,11 +17,11 @@ import { makeStyles } from '@mui/styles'; import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import type { UserInfoResponse } from 'background/service/networkModel'; import importIcon from 'ui/FRWAssets/svg/importIcon.svg'; import popLock from 'ui/FRWAssets/svg/popLock.svg'; import { useWallet } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; import rightarrow from '../../../FRWAssets/svg/rightarrow.svg'; import sideMore from '../../../FRWAssets/svg/sideMore.svg'; diff --git a/src/ui/views/Dashboard/Header.tsx b/src/ui/views/Dashboard/Header.tsx index 7d5b9e97..9087bbd0 100644 --- a/src/ui/views/Dashboard/Header.tsx +++ b/src/ui/views/Dashboard/Header.tsx @@ -25,12 +25,11 @@ import { useHistory } from 'react-router-dom'; import { storage } from '@/background/webapi'; import eventBus from '@/eventBus'; +import { withPrefix, ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; -import { withPrefix, ensureEvmAddressPrefix } from '@/ui/utils/address'; import { useNews } from '@/ui/utils/NewsContext'; import type { UserInfoResponse, WalletResponse } from 'background/service/networkModel'; import { useWallet, formatAddress } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; import IconCopy from '../../../components/iconfont/IconCopy'; import EyeOff from '../../FRWAssets/svg/EyeOff.svg'; diff --git a/src/ui/views/Deposit/index.tsx b/src/ui/views/Deposit/index.tsx index 445a2447..ef06b4ca 100644 --- a/src/ui/views/Deposit/index.tsx +++ b/src/ui/views/Deposit/index.tsx @@ -1,17 +1,17 @@ -import React, { useState, useEffect, useRef } from 'react'; -import { Box, MenuItem, Select, Typography, Tooltip, Button } from '@mui/material'; +import { MenuItem, Select, Typography, Tooltip, Button } from '@mui/material'; +import { useTheme, styled, StyledEngineProvider } from '@mui/material/styles'; +import { makeStyles } from '@mui/styles'; import QRCodeStyling from 'qr-code-styling'; -import { useWallet } from 'ui/utils'; -import { useTheme, styled } from '@mui/material/styles'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import React, { useState, useEffect, useRef, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { makeStyles } from '@mui/styles'; -import { StyledEngineProvider } from '@mui/material/styles'; + +import { withPrefix } from '@/shared/utils/address'; +import { LLTestnetIndicator, LLHeader } from 'ui/FRWComponent'; +import { useWallet } from 'ui/utils'; + import IconCopy from '../../../components/iconfont/IconCopy'; -import { LLTestnetIndicator } from 'ui/FRWComponent'; + import TestnetWarning from './TestnetWarning'; -import { withPrefix } from '@/ui/utils/address'; -import { LLHeader } from 'ui/FRWComponent'; const useStyles = makeStyles((theme) => ({ page: { @@ -123,7 +123,7 @@ const Deposit = () => { const [userInfo, setUserInfo] = useState(null); const [active, setIsActive] = useState(false); - const fetch = async () => { + const fetchStuff = useCallback(async () => { const isChild = await wallet.getActiveWallet(); let childresp = {}; try { @@ -179,7 +179,7 @@ const Deposit = () => { setNetwork(network); const user = await wallet.getUserInfo(false); setUserInfo(user); - }; + }, [currentNetwork, wallet]); useEffect(() => { if (userWallets && userInfo) { @@ -191,8 +191,8 @@ const Deposit = () => { }, [userWallets, currentWallet, userInfo]); useEffect(() => { - fetch(); - }, []); + fetchStuff(); + }, [fetchStuff]); useEffect(() => { if (ref.current) { diff --git a/src/ui/views/EvmMove/MoveFromChild/index.tsx b/src/ui/views/EvmMove/MoveFromChild/index.tsx index a665fd8f..04a9d720 100644 --- a/src/ui/views/EvmMove/MoveFromChild/index.tsx +++ b/src/ui/views/EvmMove/MoveFromChild/index.tsx @@ -4,13 +4,13 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; diff --git a/src/ui/views/EvmMove/MoveFromEvm/index.tsx b/src/ui/views/EvmMove/MoveFromEvm/index.tsx index 53f1c915..af8a3b04 100644 --- a/src/ui/views/EvmMove/MoveFromEvm/index.tsx +++ b/src/ui/views/EvmMove/MoveFromEvm/index.tsx @@ -4,13 +4,13 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; diff --git a/src/ui/views/EvmMove/MoveFromFlow/index.tsx b/src/ui/views/EvmMove/MoveFromFlow/index.tsx index a0a4d1b2..2a832969 100644 --- a/src/ui/views/EvmMove/MoveFromFlow/index.tsx +++ b/src/ui/views/EvmMove/MoveFromFlow/index.tsx @@ -4,13 +4,13 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix, isValidEthereumAddress } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; diff --git a/src/ui/views/EvmMove/MoveFromParent/index.tsx b/src/ui/views/EvmMove/MoveFromParent/index.tsx index 58d39317..0c7c50dd 100644 --- a/src/ui/views/EvmMove/MoveFromParent/index.tsx +++ b/src/ui/views/EvmMove/MoveFromParent/index.tsx @@ -4,13 +4,13 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; import wallet from '@/background/controller/wallet'; +import { withPrefix } from '@/shared/utils/address'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import type { CoinItem } from 'background/service/coinList'; import type { Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../../components/iconfont/IconSwitch'; import theme from '../../../style/LLTheme'; diff --git a/src/ui/views/MoveBoard/AccountBox.tsx b/src/ui/views/MoveBoard/AccountBox.tsx index a2023958..8bc924c2 100644 --- a/src/ui/views/MoveBoard/AccountBox.tsx +++ b/src/ui/views/MoveBoard/AccountBox.tsx @@ -1,28 +1,30 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles } from '@mui/styles'; -import { useWallet, formatAddress } from 'ui/utils'; -import { ensureEvmAddressPrefix, formatString } from 'ui/utils/address'; import { Typography, Box, CardMedia } from '@mui/material'; -import { FRWProfileCard, FWMoveDropdown } from 'ui/FRWComponent'; -import accountMove from 'ui/FRWAssets/svg/accountMove.svg'; -import emoji from 'background/utils/emoji.json'; +import { makeStyles } from '@mui/styles'; +import React, { useCallback, useEffect, useState } from 'react'; + import { storage } from '@/background/webapi'; +import { ensureEvmAddressPrefix, formatString } from '@/shared/utils/address'; +import emoji from 'background/utils/emoji.json'; +import accountMove from 'ui/FRWAssets/svg/accountMove.svg'; +import { FRWProfileCard, FWMoveDropdown } from 'ui/FRWComponent'; +import { useWallet, formatAddress } from 'ui/utils'; + +const USER_CONTACT = { + contact_name: '', + avatar: '', +}; function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = false }) { const usewallet = useWallet(); - const userContact = { - contact_name: '', - avatar: '', - }; const [first, setFirst] = useState(''); const [second, setSecond] = useState(''); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [firstEmoji, setFirstEmoji] = useState(null); const [secondEmoji, setSecondEmoji] = useState(null); const [childWallets, setChildWallets] = useState({}); - const requestAddress = async () => { + const requestAddress = useCallback(async () => { const parentAddress = await usewallet.getMainAddress(); const address = await usewallet.getCurrentAddress(); const childResp = await usewallet.checkUserChildAccount(); @@ -49,8 +51,10 @@ function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = const wallet = walletList[firstWalletAddress]; setChildWallets(walletList); - userContact.avatar = wallet.thumbnail.url; - userContact.contact_name = wallet.name; + const userContact = { + avatar: wallet.thumbnail.url, + contact_name: wallet.name, + }; if (firstWalletAddress) { setSelectedChildAccount(walletList[firstWalletAddress]); } @@ -63,11 +67,11 @@ function AccountBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = } setSecond(parentAddress!); setSecondEmoji(emojires[0]); - }; + }, [isEvm, usewallet, setSelectedChildAccount]); useEffect(() => { requestAddress(); - }, []); + }, [requestAddress]); return ( diff --git a/src/ui/views/MoveBoard/AccountMainBox.tsx b/src/ui/views/MoveBoard/AccountMainBox.tsx index 4dc71eba..5e905976 100644 --- a/src/ui/views/MoveBoard/AccountMainBox.tsx +++ b/src/ui/views/MoveBoard/AccountMainBox.tsx @@ -1,26 +1,28 @@ -import React, { useEffect, useState } from 'react'; -import { makeStyles } from '@mui/styles'; -import { useWallet, formatAddress } from 'ui/utils'; -import { ensureEvmAddressPrefix } from 'ui/utils/address'; import { Typography, Box, CardMedia } from '@mui/material'; -import { FRWProfileCard, FWMoveDropdown } from 'ui/FRWComponent'; -import accountMove from 'ui/FRWAssets/svg/accountMove.svg'; -import emoji from 'background/utils/emoji.json'; +import { makeStyles } from '@mui/styles'; +import React, { useCallback, useEffect, useState } from 'react'; + import { storage } from '@/background/webapi'; +import { ensureEvmAddressPrefix } from '@/shared/utils/address'; +import emoji from 'background/utils/emoji.json'; +import accountMove from 'ui/FRWAssets/svg/accountMove.svg'; +import { FRWProfileCard, FWMoveDropdown } from 'ui/FRWComponent'; +import { useWallet, formatAddress } from 'ui/utils'; + +const USER_CONTACT = { + contact_name: '', + avatar: '', +}; function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isEvm = false }) { const usewallet = useWallet(); - const userContact = { - contact_name: '', - avatar: '', - }; const [first, setFirst] = useState(''); - const [userInfo, setUser] = useState(userContact); + const [userInfo, setUser] = useState(USER_CONTACT); const [firstEmoji, setFirstEmoji] = useState(null); const [childWallets, setChildWallets] = useState({}); - const requestAddress = async () => { + const requestAddress = useCallback(async () => { const parentAddress = await usewallet.getMainAddress(); const address = await usewallet.getCurrentAddress(); const childResp = await usewallet.checkUserChildAccount(); @@ -62,8 +64,10 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE const wallet = childResp[address!]; setChildWallets(walletList); - userContact.avatar = wallet.thumbnail.url; - userContact.contact_name = wallet.name; + const userContact = { + avatar: wallet.thumbnail.url, + contact_name: wallet.name, + }; if (firstWalletAddress) { setSelectedChildAccount(walletList[firstWalletAddress]); } @@ -91,11 +95,11 @@ function AccountMainBox({ isChild, setSelectedChildAccount, selectedAccount, isE setFirst(parentAddress!); setFirstEmoji(emojires[0]); } - }; + }, [usewallet, isChild, setSelectedChildAccount]); useEffect(() => { requestAddress(); - }, []); + }, [requestAddress]); return ( diff --git a/src/ui/views/MoveBoard/MoveFromChild/index.tsx b/src/ui/views/MoveBoard/MoveFromChild/index.tsx index 966b874a..beea86d7 100644 --- a/src/ui/views/MoveBoard/MoveFromChild/index.tsx +++ b/src/ui/views/MoveBoard/MoveFromChild/index.tsx @@ -3,9 +3,9 @@ import { Box, Button, Skeleton, Typography, Drawer, IconButton, CardMedia } from import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import WarningSnackbar from '@/ui/FRWComponent/WarningSnackbar'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; -import { isValidEthereumAddress } from '@/ui/utils/address'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import alertMark from 'ui/FRWAssets/svg/alertMark.svg'; import moveSelectDrop from 'ui/FRWAssets/svg/moveSelectDrop.svg'; diff --git a/src/ui/views/MoveBoard/MoveToChild/index.tsx b/src/ui/views/MoveBoard/MoveToChild/index.tsx index c8f10de0..e4d0e091 100644 --- a/src/ui/views/MoveBoard/MoveToChild/index.tsx +++ b/src/ui/views/MoveBoard/MoveToChild/index.tsx @@ -3,6 +3,7 @@ import { Box, Button, Skeleton, Typography, Drawer, IconButton, CardMedia } from import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import WarningSnackbar from '@/ui/FRWComponent/WarningSnackbar'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; @@ -11,7 +12,6 @@ import moveSelectDrop from 'ui/FRWAssets/svg/moveSelectDrop.svg'; import selected from 'ui/FRWAssets/svg/selected.svg'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { isValidEthereumAddress } from 'ui/utils/address'; import AccountMainBox from '../AccountMainBox'; import MoveCollectionSelect from '../MoveCollectionSelect'; diff --git a/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx b/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx index 00382ef6..27541b8b 100644 --- a/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx +++ b/src/ui/views/NFT/SendNFT/MoveNftConfirmation.tsx @@ -4,6 +4,7 @@ import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } f import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; @@ -11,7 +12,6 @@ import { MatchMediaType } from '@/ui/utils/url'; import { useStorageCheck } from '@/ui/utils/useStorageCheck'; import { LLSpinner, FRWChildProfile, FRWDropdownProfileCard } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { ensureEvmAddressPrefix, isValidEthereumAddress } from 'ui/utils/address'; import IconFlow from '../../../../components/iconfont/IconFlow'; diff --git a/src/ui/views/NFT/SendNFT/MovefromParent.tsx b/src/ui/views/NFT/SendNFT/MovefromParent.tsx index 83bddd08..8d00f843 100644 --- a/src/ui/views/NFT/SendNFT/MovefromParent.tsx +++ b/src/ui/views/NFT/SendNFT/MovefromParent.tsx @@ -4,10 +4,10 @@ import { Box, Typography, Drawer, Stack, Grid, CardMedia, IconButton, Button } f import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import StorageExceededAlert from '@/ui/FRWComponent/StorageExceededAlert'; import { WarningStorageLowSnackbar } from '@/ui/FRWComponent/WarningStorageLowSnackbar'; -import { ensureEvmAddressPrefix, isValidEthereumAddress } from '@/ui/utils/address'; import { MatchMediaType } from '@/ui/utils/url'; import { LLSpinner, FRWProfileCard, FRWDropdownProfileCard } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; diff --git a/src/ui/views/NFT/SendNFT/SendToAddress.tsx b/src/ui/views/NFT/SendNFT/SendToAddress.tsx index 6c50effb..008d0a77 100644 --- a/src/ui/views/NFT/SendNFT/SendToAddress.tsx +++ b/src/ui/views/NFT/SendNFT/SendToAddress.tsx @@ -18,8 +18,8 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import SwipeableViews from 'react-swipeable-views'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; import { type MatchMedia } from '@/ui/utils/url'; import { type Contact } from 'background/service/networkModel'; import { useWallet } from 'ui/utils'; diff --git a/src/ui/views/NftEvm/SendNFT/SendToAddress.tsx b/src/ui/views/NftEvm/SendNFT/SendToAddress.tsx index 29d6bfe7..0c49ee7d 100644 --- a/src/ui/views/NftEvm/SendNFT/SendToAddress.tsx +++ b/src/ui/views/NftEvm/SendNFT/SendToAddress.tsx @@ -18,8 +18,8 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import SwipeableViews from 'react-swipeable-views'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; import { type MatchMedia } from '@/ui/utils/url'; import { type Contact } from 'background/service/networkModel'; import { useWallet } from 'ui/utils'; diff --git a/src/ui/views/NftEvm/index.tsx b/src/ui/views/NftEvm/index.tsx index 3a8a7658..93046bd8 100644 --- a/src/ui/views/NftEvm/index.tsx +++ b/src/ui/views/NftEvm/index.tsx @@ -7,7 +7,7 @@ import { styled } from '@mui/system'; import React, { useState, useEffect, useRef, useCallback } from 'react'; import { storage } from '@/background/webapi'; -import { ensureEvmAddressPrefix } from '@/ui/utils/address'; +import { ensureEvmAddressPrefix } from '@/shared/utils/address'; import { useWallet } from 'ui/utils'; import GridTab from './GridTab'; diff --git a/src/ui/views/Send/AccountsList.tsx b/src/ui/views/Send/AccountsList.tsx index 622674e5..b218539a 100644 --- a/src/ui/views/Send/AccountsList.tsx +++ b/src/ui/views/Send/AccountsList.tsx @@ -3,7 +3,7 @@ import { groupBy, isEmpty } from 'lodash'; import React, { useEffect, useState, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { useWallet } from 'ui/utils'; import { LLContactCard, LLContactEth, FWContactCard } from '../../FRWComponent'; diff --git a/src/ui/views/Send/SendAmount.tsx b/src/ui/views/Send/SendAmount.tsx index 4b167ad9..87c82bbc 100644 --- a/src/ui/views/Send/SendAmount.tsx +++ b/src/ui/views/Send/SendAmount.tsx @@ -3,13 +3,13 @@ import { Box, Button, Typography, IconButton, CardMedia } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; +import { withPrefix } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { type CoinItem } from 'background/service/coinList'; import { type Contact } from 'background/service/networkModel'; import { LLContactCard } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import CancelIcon from '../../../components/iconfont/IconClose'; diff --git a/src/ui/views/Send/SendEth/index.tsx b/src/ui/views/Send/SendEth/index.tsx index c3e89e50..29c331bb 100644 --- a/src/ui/views/Send/SendEth/index.tsx +++ b/src/ui/views/Send/SendEth/index.tsx @@ -3,6 +3,7 @@ import React, { useState, useEffect, useCallback } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import Web3 from 'web3'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; import SlideRelative from '@/ui/FRWComponent/SlideRelative'; import { type CoinItem } from 'background/service/coinList'; @@ -11,7 +12,6 @@ import erc20ABI from 'background/utils/erc20.abi.json'; import { EVM_ENDPOINT } from 'consts'; import { LLContactCard } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix, isValidEthereumAddress } from 'ui/utils/address'; import CancelIcon from '../../../../components/iconfont/IconClose'; import TransferAmount from '../TransferAmount'; diff --git a/src/ui/views/Send/index.tsx b/src/ui/views/Send/index.tsx index 45fe2e72..c81a1cb3 100644 --- a/src/ui/views/Send/index.tsx +++ b/src/ui/views/Send/index.tsx @@ -1,4 +1,6 @@ -import React, { useState, useEffect } from 'react'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; +import SearchIcon from '@mui/icons-material/Search'; import { Box, InputBase, @@ -15,24 +17,24 @@ import { IconButton, Tooltip, } from '@mui/material'; -import { useWallet } from 'ui/utils'; -import { useTheme, styled } from '@mui/material/styles'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; -import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded'; -import SearchIcon from '@mui/icons-material/Search'; -import { useHistory } from 'react-router-dom'; -import AddressBookList from './AddressBookList'; -import AccountsList from './AccountsList'; -import SearchList from './SearchList'; -import RecentList from './RecentList'; -import { Contact } from 'background/service/networkModel'; -import { isEmpty } from 'lodash'; +import { useTheme, styled, StyledEngineProvider } from '@mui/material/styles'; import { makeStyles } from '@mui/styles'; -import { StyledEngineProvider } from '@mui/material/styles'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; +import { isEmpty } from 'lodash'; +import React, { useState, useEffect, useCallback } from 'react'; +import { useHistory } from 'react-router-dom'; import SwipeableViews from 'react-swipeable-views'; + +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; +import { type Contact } from 'background/service/networkModel'; +import { useWallet } from 'ui/utils'; + import IconAbout from '../../../components/iconfont/IconAbout'; +import AccountsList from './AccountsList'; +import AddressBookList from './AddressBookList'; +import RecentList from './RecentList'; +import SearchList from './SearchList'; + export enum SendPageTabOptions { Recent = 'Recent', AddressBook = 'AddressBook', @@ -163,7 +165,7 @@ const Send = () => { const [searched, setSearched] = useState(false); const [hasNoFilteredContacts, setHasNoFilteredContacts] = useState(false); - const fetchAddressBook = async () => { + const fetchAddressBook = useCallback(async () => { await wallet.setDashIndex(0); try { const response = await wallet.getAddressBook(); @@ -202,11 +204,11 @@ const Send = () => { } catch (err) { console.log('err: ', err); } - }; + }, [wallet]); useEffect(() => { fetchAddressBook(); - }, []); + }, [fetchAddressBook]); const checkContain = (searchResult: Contact) => { if (sortedContacts.some((e) => e.contact_name === searchResult.username)) { @@ -403,8 +405,6 @@ const Send = () => { }; const handleClick = (eachgroup) => { - const history = useHistory(); - const isEvmAddress = isValidEthereumAddress(eachgroup.address); const pathname = isEvmAddress ? '/dashboard/wallet/sendEth' : '/dashboard/wallet/sendAmount'; diff --git a/src/ui/views/Setting/Account/EditAccount.tsx b/src/ui/views/Setting/Account/EditAccount.tsx index 439c4cd3..9fe1c5e5 100644 --- a/src/ui/views/Setting/Account/EditAccount.tsx +++ b/src/ui/views/Setting/Account/EditAccount.tsx @@ -1,12 +1,12 @@ -import React, { useState, useEffect } from 'react'; +import CloseIcon from '@mui/icons-material/Close'; import { Typography, Box, Drawer, Grid, Stack, InputBase, CircularProgress } from '@mui/material'; import { styled } from '@mui/material/styles'; -import CloseIcon from '@mui/icons-material/Close'; -import { LLPrimaryButton, LLSecondaryButton, LLFormHelperText } from '../../../FRWComponent'; +import React, { useState, useEffect } from 'react'; +import { useForm, type FieldValues } from 'react-hook-form'; + import { useWallet } from 'ui/utils'; -import { useForm, FieldValues } from 'react-hook-form'; -import { withPrefix } from '../../../utils/address'; -import { Contact } from 'background/service/networkModel'; + +import { LLPrimaryButton, LLSecondaryButton, LLFormHelperText } from '../../../FRWComponent'; const StyledInput = styled(InputBase)(({ theme }) => ({ zIndex: 1, @@ -75,7 +75,7 @@ const EditAccount = (props: EditAccountProps) => { keepSubmitCount: true, } ); - }, [props.avatar, props.nickname]); + }, [props.avatar, props.nickname, reset]); const renderContent = () => ( ({ zIndex: 1, diff --git a/src/ui/views/Setting/Wallet/EditProfile.tsx b/src/ui/views/Setting/Wallet/EditProfile.tsx index 9ec99e40..524990a7 100644 --- a/src/ui/views/Setting/Wallet/EditProfile.tsx +++ b/src/ui/views/Setting/Wallet/EditProfile.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import CloseIcon from '@mui/icons-material/Close'; import { Box, Button, @@ -12,13 +12,14 @@ import { Avatar, CardMedia, } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; -import { useWallet } from 'ui/utils'; +import React, { useState, useEffect, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; -import { isValidEthereumAddress } from 'ui/utils/address'; + +import { isValidEthereumAddress } from '@/shared/utils/address'; +import emojis from 'background/utils/emoji.json'; import homeMoveFt from 'ui/FRWAssets/svg/homeMoveFt.svg'; import moveSvg from 'ui/FRWAssets/svg/moveSvg.svg'; -import emojis from 'background/utils/emoji.json'; +import { useWallet } from 'ui/utils'; import { profileHooks } from 'ui/utils/profileHooks'; interface MoveBoardProps { @@ -41,9 +42,9 @@ const EditProfile = (props: MoveBoardProps) => { // console.log('props.loggedInAccounts', props.current) - const requestChildType = async () => { + const requestChildType = useCallback(async () => { setSelectEmoji(props.emoji); - }; + }, [props.emoji]); const changeProfile = async () => { const address = props.userWallet[0].blockchain[0].address; @@ -64,7 +65,7 @@ const EditProfile = (props: MoveBoardProps) => { useEffect(() => { requestChildType(); - }, [props.emoji]); + }, [props.emoji, requestChildType]); return ( ({ arrowback: { @@ -111,16 +113,16 @@ const RemoveWallet = ({ hideBackButton = false }) => { const [walletList, setWalletList] = useState([]); - const setUserWallet = async () => { + const setUserWallet = useCallback(async () => { const userInfo = await usewallet.getUserInfo(true); const wallet = await usewallet.getUserWallets(); await setWallet(wallet); await setUserInfo(userInfo); - }; + }, [usewallet]); useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); useEffect(() => { const list = wallets(userWallet); diff --git a/src/ui/views/Setting/Wallet/WalletDetail.tsx b/src/ui/views/Setting/Wallet/WalletDetail.tsx index 433dca57..9f85a541 100644 --- a/src/ui/views/Setting/Wallet/WalletDetail.tsx +++ b/src/ui/views/Setting/Wallet/WalletDetail.tsx @@ -20,8 +20,8 @@ import React, { useState, useEffect, useCallback } from 'react'; import { Link } from 'react-router-dom'; import { storage } from '@/background/webapi'; +import { withPrefix, isValidEthereumAddress } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; -import { withPrefix, isValidEthereumAddress } from '@/ui/utils/address'; import type { StorageInfo } from 'background/service/networkModel'; import { useWallet } from 'ui/utils'; diff --git a/src/ui/views/Setting/Wallet/index.tsx b/src/ui/views/Setting/Wallet/index.tsx index 256ddce3..44547fb6 100644 --- a/src/ui/views/Setting/Wallet/index.tsx +++ b/src/ui/views/Setting/Wallet/index.tsx @@ -1,5 +1,3 @@ -import React, { useEffect, useState } from 'react'; -import { Link, useRouteMatch } from 'react-router-dom'; import { Typography, List, @@ -11,13 +9,17 @@ import { CardMedia, Box, } from '@mui/material'; -import { isValidEthereumAddress } from 'ui/utils/address'; -import { storage } from 'background/webapi'; -import IconEnd from '../../../../components/iconfont/IconAVector11Stroke'; +import React, { useCallback, useEffect, useState } from 'react'; +import { Link, useRouteMatch } from 'react-router-dom'; + +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; import { useWallet } from '@/ui/utils'; +import { storage } from 'background/webapi'; import { formatAddress } from 'ui/utils'; +import IconEnd from '../../../../components/iconfont/IconAVector11Stroke'; + const tempEmoji = [ { emoji: '🥥', @@ -46,7 +48,46 @@ const Wallet = () => { storage.set('walletDetail', JSON.stringify(walletDetailInfo)); } - const setUserWallet = async () => { + const fetchBalances = useCallback( + async (wallet) => { + const updatedData = await Promise.all( + wallet.map(async (item) => { + const blockchainData = await Promise.all( + item.blockchain.map(async (bc) => { + const balance = await usewallet.getFlowBalance(bc.address); + return { ...bc, balance }; + }) + ); + return { ...item, blockchain: blockchainData }; + }) + ); + return updatedData; + }, + [usewallet] + ); + + const fetchEvmBalances = useCallback( + async (wallet) => { + const updatedData = await Promise.all( + wallet.map(async (item) => { + const blockchainData = await Promise.all( + item.blockchain.map(async (bc) => { + let balance = ''; + if (isValidEthereumAddress(bc.address)) { + balance = await usewallet.getBalance(bc.address); + } + return { ...bc, balance }; + }) + ); + return { ...item, blockchain: blockchainData }; + }) + ); + return updatedData; + }, + [usewallet] + ); + + const setUserWallet = useCallback(async () => { await usewallet.setDashIndex(3); const emojires = await usewallet.getEmoji(); const wallet = await usewallet.getUserWallets(); @@ -60,7 +101,7 @@ const Wallet = () => { } setEmojis(emojires); setWallet(fectechdWallet); - }; + }, [usewallet, fetchBalances, fetchEvmBalances]); const transformData = (data) => { return data.map((item, index) => ({ @@ -81,42 +122,9 @@ const Wallet = () => { })); }; - const fetchBalances = async (wallet) => { - const updatedData = await Promise.all( - wallet.map(async (item) => { - const blockchainData = await Promise.all( - item.blockchain.map(async (bc) => { - const balance = await usewallet.getFlowBalance(bc.address); - return { ...bc, balance }; - }) - ); - return { ...item, blockchain: blockchainData }; - }) - ); - return updatedData; - }; - - const fetchEvmBalances = async (wallet) => { - const updatedData = await Promise.all( - wallet.map(async (item) => { - const blockchainData = await Promise.all( - item.blockchain.map(async (bc) => { - let balance = ''; - if (isValidEthereumAddress(bc.address)) { - balance = await usewallet.getBalance(bc.address); - } - return { ...bc, balance }; - }) - ); - return { ...item, blockchain: blockchainData }; - }) - ); - return updatedData; - }; - useEffect(() => { setUserWallet(); - }, []); + }, [setUserWallet]); return (
diff --git a/src/ui/views/Staking/NodeDetail.tsx b/src/ui/views/Staking/NodeDetail.tsx index ea1d8cb9..34083b72 100644 --- a/src/ui/views/Staking/NodeDetail.tsx +++ b/src/ui/views/Staking/NodeDetail.tsx @@ -3,9 +3,9 @@ import { Box, Button, Typography, IconButton, ButtonBase } from '@mui/material'; import React, { useState, useEffect, useCallback } from 'react'; import { useHistory, useParams, useLocation } from 'react-router-dom'; +import { withPrefix } from '@/shared/utils/address'; import { type CoinItem } from 'background/service/coinList'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconChevronRight from '../../../components/iconfont/IconChevronRight'; diff --git a/src/ui/views/Staking/TransferList.tsx b/src/ui/views/Staking/TransferList.tsx index 4e1356e8..da1e6587 100644 --- a/src/ui/views/Staking/TransferList.tsx +++ b/src/ui/views/Staking/TransferList.tsx @@ -18,9 +18,9 @@ import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import React, { useCallback, useEffect, useState } from 'react'; +import { formatString } from '@/shared/utils/address'; import activity from 'ui/FRWAssets/svg/activity.svg'; import { useWallet } from 'ui/utils'; -import { formatString } from 'ui/utils/address'; import IconExec from '../../../components/iconfont/IconExec'; diff --git a/src/ui/views/Swap/index.tsx b/src/ui/views/Swap/index.tsx index 1a5f4581..be5c375f 100644 --- a/src/ui/views/Swap/index.tsx +++ b/src/ui/views/Swap/index.tsx @@ -3,12 +3,12 @@ import React, { useState, useEffect, useCallback } from 'react'; // import { useHistory, useLocation } from 'react-router-dom'; // import ArrowBackIcon from '@mui/icons-material/ArrowBack'; +import { withPrefix } from '@/shared/utils/address'; import { LLHeader } from '@/ui/FRWComponent'; import { type CoinItem } from 'background/service/coinList'; import { type Contact } from 'background/service/networkModel'; import { LLSpinner } from 'ui/FRWComponent'; import { useWallet } from 'ui/utils'; -import { withPrefix } from 'ui/utils/address'; import IconSwitch from '../../../components/iconfont/IconSwitch'; import Increment from '../../FRWAssets/svg/increment.svg'; diff --git a/src/ui/views/TokenDetail/PriceCard.tsx b/src/ui/views/TokenDetail/PriceCard.tsx index 55ad153c..64cc6f54 100644 --- a/src/ui/views/TokenDetail/PriceCard.tsx +++ b/src/ui/views/TokenDetail/PriceCard.tsx @@ -1,6 +1,24 @@ -import React, { useEffect, useState, useRef } from 'react'; +import ArrowDropDownRoundedIcon from '@mui/icons-material/ArrowDropDownRounded'; +import ArrowDropUpRoundedIcon from '@mui/icons-material/ArrowDropUpRounded'; +import KeyboardArrowDownRoundedIcon from '@mui/icons-material/KeyboardArrowDownRounded'; +import { + ToggleButtonGroup, + ToggleButton, + Menu, + MenuItem, + Typography, + Box, + ButtonBase, +} from '@mui/material'; +import { styled } from '@mui/material/styles'; +import dayjs from 'dayjs'; +import React, { useEffect, useState, useRef, useCallback } from 'react'; +import { AreaChart, Area, YAxis, Tooltip, ResponsiveContainer } from 'recharts'; + +import { getPeriodFrequency } from '@/shared/utils/getPeriodFrequency'; +import { Period, type PriceProvider } from 'background/service/networkModel'; import { useWallet } from 'ui/utils'; -import { Typography, Box, ButtonBase } from '@mui/material'; + import { IconKraken, IconBinance, @@ -8,16 +26,6 @@ import { IconKucoin, IconHuobi, } from '../../../components/iconfont'; -import { ToggleButtonGroup, ToggleButton, Menu, MenuItem } from '@mui/material'; -import { AreaChart, Area, YAxis, Tooltip, ResponsiveContainer } from 'recharts'; -import ArrowDropUpRoundedIcon from '@mui/icons-material/ArrowDropUpRounded'; -import ArrowDropDownRoundedIcon from '@mui/icons-material/ArrowDropDownRounded'; -import KeyboardArrowDownRoundedIcon from '@mui/icons-material/KeyboardArrowDownRounded'; -import { styled } from '@mui/material/styles'; -import { getPeriodFrequency } from 'utils'; - -import dayjs from 'dayjs'; -import { Period, PriceProvider } from 'background/service/networkModel'; const StyledToggleButtonGroup = styled(ToggleButtonGroup)(({ theme }) => ({ '& .MuiToggleButtonGroup-grouped': { @@ -139,52 +147,59 @@ const PriceCard = ({ token, price, setPrice, providers }) => { setAnchorEl(null); }; - const fetchPrice = async (provider: PriceProvider) => { - const response = await wallet.openapi.getTokenPrice(token, provider); - if (mountedRef.current) { - setPrice(response['price']['last']); - const percentage = response['price']['change']['percentage'] * 100; - setChange(percentage); - } - }; + const fetchPrice = useCallback( + async (provider: PriceProvider) => { + const response = await wallet.openapi.getTokenPrice(token, provider); + if (mountedRef.current) { + setPrice(response['price']['last']); + const percentage = response['price']['change']['percentage'] * 100; + setChange(percentage); + } + }, + [token, wallet.openapi, setPrice] + ); - const fetchPriceHistory = async (period: Period, provider: PriceProvider) => { - wallet.openapi.getTokenPriceHistory(token, period, provider).then((response) => { - const frequency = getPeriodFrequency(period); - const data = response[frequency].map((item) => ({ - closeTime: item[0], - openPrice: item[1], - highPrice: item[2], - lowPrice: item[3], - price: item[4], - volume: item[5], - quoteVolume: item[6], - })); - setData(data); - }); - }; + const fetchPriceHistory = useCallback( + async (period: Period, provider: PriceProvider) => { + wallet.openapi.getTokenPriceHistory(token, period, provider).then((response) => { + const frequency = getPeriodFrequency(period); + const data = response[frequency].map((item) => ({ + closeTime: item[0], + openPrice: item[1], + highPrice: item[2], + lowPrice: item[3], + price: item[4], + volume: item[5], + quoteVolume: item[6], + })); + setData(data); + }); + }, + [token, wallet.openapi] + ); + const currentProvider = useCallback((): PriceProvider => { + return priceProviders[selectedIndex] as PriceProvider; + }, [selectedIndex, priceProviders]); useEffect(() => { // FIX ME: Memory leak const timerId = setTimeout(() => { - fetchPrice(currentProvider()), fetchPriceHistory(period, currentProvider()); + fetchPrice(currentProvider()); + fetchPriceHistory(period, currentProvider()); }, 400); return () => clearTimeout(timerId); - }, []); + }, [fetchPrice, fetchPriceHistory, period, currentProvider]); useEffect(() => { - fetchPrice(currentProvider()), fetchPriceHistory(period, currentProvider()); - }, [selectedIndex]); + fetchPrice(currentProvider()); + fetchPriceHistory(period, currentProvider()); + }, [selectedIndex, period, fetchPrice, fetchPriceHistory, currentProvider]); const isUp = (): boolean => { return change >= 0; }; - const currentProvider = (): PriceProvider => { - return priceProviders[selectedIndex] as PriceProvider; - }; - const handlePeriod = (event: React.MouseEvent, newPeriod: string) => { const period = newPeriod as Period; if (period) { @@ -382,7 +397,6 @@ const PriceCard = ({ token, price, setPrice, providers }) => { } diff --git a/src/ui/views/TokenDetail/TokenInfoCard.tsx b/src/ui/views/TokenDetail/TokenInfoCard.tsx index 7e18fc4e..ae87e265 100644 --- a/src/ui/views/TokenDetail/TokenInfoCard.tsx +++ b/src/ui/views/TokenDetail/TokenInfoCard.tsx @@ -3,8 +3,8 @@ import { type TokenInfo } from 'flow-native-token-registry'; import React, { useEffect, useState, useRef, useCallback } from 'react'; import { useHistory } from 'react-router-dom'; +import { isValidEthereumAddress } from '@/shared/utils/address'; import { LLPrimaryButton } from '@/ui/FRWComponent'; -import { isValidEthereumAddress } from '@/ui/utils/address'; import iconMove from 'ui/FRWAssets/svg/moveIcon.svg'; import { useWallet } from 'ui/utils'; import { addDotSeparators } from 'ui/utils/number'; diff --git a/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx b/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx index 724f4af8..789a9134 100644 --- a/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx +++ b/src/ui/views/Wallet/AddCustom/AddCustomEvmToken.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { Typography, Box, @@ -9,16 +9,19 @@ import { FormControl, } from '@mui/material'; import { styled } from '@mui/material/styles'; -import { useHistory } from 'react-router-dom'; -import { LLPrimaryButton, LLFormHelperText } from '../../../FRWComponent'; -import { useWallet } from 'ui/utils'; -import { useForm } from 'react-hook-form'; -import { withPrefix, isValidEthereumAddress } from '../../../utils/address'; -import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import { Contract, ethers } from 'ethers'; +import React, { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { useHistory } from 'react-router-dom'; + import { storage } from '@/background/webapi'; -import AddCustomEvmForm from './CustomEvmForm'; import { EVM_ENDPOINT } from 'consts'; +import { useWallet } from 'ui/utils'; + +import { withPrefix, isValidEthereumAddress } from '../../../../shared/utils/address'; +import { LLPrimaryButton, LLFormHelperText } from '../../../FRWComponent'; + +import AddCustomEvmForm from './CustomEvmForm'; const StyledInput = styled(InputBase)(({ theme }) => ({ zIndex: 1, diff --git a/src/ui/views/Wallet/TransferList.tsx b/src/ui/views/Wallet/TransferList.tsx index f28ce82a..a46675ec 100644 --- a/src/ui/views/Wallet/TransferList.tsx +++ b/src/ui/views/Wallet/TransferList.tsx @@ -17,9 +17,9 @@ import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import React, { useCallback, useEffect, useState } from 'react'; +import { formatString } from '@/shared/utils/address'; import activity from 'ui/FRWAssets/svg/activity.svg'; import { useWallet } from 'ui/utils'; -import { formatString } from 'ui/utils/address'; // import IconExec from '../../../components/iconfont/IconExec'; // import ExpandLessRoundedIcon from '@mui/icons-material/ExpandLessRounded'; dayjs.extend(relativeTime); diff --git a/src/ui/views/Wallet/index.tsx b/src/ui/views/Wallet/index.tsx index 6a586047..bf7b4f10 100644 --- a/src/ui/views/Wallet/index.tsx +++ b/src/ui/views/Wallet/index.tsx @@ -17,8 +17,8 @@ import swapIcon from 'ui/FRWAssets/svg/swapIcon.svg'; import { useWallet } from 'ui/utils'; import { formatLargeNumber } from 'ui/utils/number'; +import { withPrefix } from '../../../shared/utils/address'; import theme from '../../style/LLTheme'; -import { withPrefix } from '../../utils/address'; import MoveBoard from '../MoveBoard'; import CoinList from './Coinlist'; diff --git a/src/ui/views/index.tsx b/src/ui/views/index.tsx index 75c1d21e..9b18799a 100644 --- a/src/ui/views/index.tsx +++ b/src/ui/views/index.tsx @@ -27,7 +27,6 @@ function Main() { }, []); return ( - //@ts-ignore @@ -48,8 +47,6 @@ function Main() { } const App = ({ wallet }: { wallet: any }) => { - console.log('Theme:', theme); // Add this to debug - return ( diff --git a/src/utils/index.ts b/src/utils/index.ts deleted file mode 100644 index 95a76a68..00000000 --- a/src/utils/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Period, PeriodFrequency } from 'background/service/networkModel'; - -import BroadcastChannelMessage from './message/broadcastChannelMessage'; -import PortMessage from './message/portMessage'; - -const Message = { - BroadcastChannelMessage, - PortMessage, -}; - -declare global { - const langLocales: Record>; -} - -const t = (name) => chrome.i18n.getMessage(name); - -const format = (str, ...args) => { - return args.reduce((m, n) => m.replace('_s_', n), str); -}; - -export { Message, t, format }; - -// const chainsDict = keyBy(CHAINS, 'serverId'); -// export const getChain = (chainId?: string) => { -// if (!chainId) { -// return null; -// } -// return chainsDict[chainId]; -// }; - -export const getPeriodFrequency = (period: Period): PeriodFrequency => { - switch (period) { - case Period.oneDay: - return PeriodFrequency.halfHour; - case Period.oneWeek: - return PeriodFrequency.oneHour; - case Period.oneMonth: - return PeriodFrequency.oneDay; - case Period.threeMonth: - return PeriodFrequency.oneDay; - case Period.oneYear: - return PeriodFrequency.threeDay; - case Period.all: - return PeriodFrequency.oneWeek; - default: - return PeriodFrequency.oneDay; - } -};