diff --git a/packages/mask/popups/components/WalletAvatar/index.tsx b/packages/mask/popups/components/WalletAvatar/index.tsx new file mode 100644 index 00000000000..aee4e33942b --- /dev/null +++ b/packages/mask/popups/components/WalletAvatar/index.tsx @@ -0,0 +1,45 @@ +import { Icons } from '@masknet/icons' +import { Image } from '@masknet/shared' +import { PersistentStorages } from '@masknet/shared-base' +import { makeStyles } from '@masknet/theme' +import { isSameAddress } from '@masknet/web3-shared-base' +import { useWallets } from '@privy-io/react-auth' +import { memo, useMemo } from 'react' +import { useSubscription } from 'use-subscription' + +const useStyles = makeStyles()((theme) => ({ + container: { + position: 'relative', + }, + badgeIcon: { + position: 'absolute', + right: -3, + bottom: -1, + border: `1px solid ${theme.palette.common.white}`, + borderRadius: '50%', + }, +})) + +interface Props { + size?: number + address: string +} +export const WalletAvatar = memo(function WalletAvatar({ size = 30, address }) { + const { classes } = useStyles() + const { wallets: fireflyWallets } = useWallets() + + const isFireflyWallet = useMemo( + () => fireflyWallets.some((w) => isSameAddress(w.address, address)), + [fireflyWallets, address], + ) + const fireflyAccount = useSubscription(PersistentStorages.Settings.storage.firefly_account.subscription) + + if (isFireflyWallet && fireflyAccount) + return ( +
+ + +
+ ) + return +}) diff --git a/packages/mask/popups/components/WalletItem/index.tsx b/packages/mask/popups/components/WalletItem/index.tsx index 1f307728c8c..b926ac112de 100644 --- a/packages/mask/popups/components/WalletItem/index.tsx +++ b/packages/mask/popups/components/WalletItem/index.tsx @@ -1,9 +1,8 @@ -import { memo, useCallback } from 'react' +import { memo, useCallback, useMemo } from 'react' import { makeStyles } from '@masknet/theme' import { formatDomainName, formatEthereumAddress } from '@masknet/web3-shared-evm' -import { NetworkPluginID, ImportSource, type Wallet } from '@masknet/shared-base' +import { NetworkPluginID, ImportSource, type Wallet, PersistentStorages } from '@masknet/shared-base' import { useReverseAddress } from '@masknet/web3-hooks-base' -import { Icons } from '@masknet/icons' import { Box, ListItem, @@ -16,6 +15,10 @@ import { import { FormattedAddress } from '@masknet/shared' import { WalletBalance } from '../index.js' import { Trans } from '@lingui/react/macro' +import { WalletAvatar } from '../WalletAvatar/index.js' +import { useWallets } from '@privy-io/react-auth' +import { isSameAddress } from '@masknet/web3-shared-base' +import { useSubscription } from 'use-subscription' const useStyles = makeStyles()((theme) => ({ item: { @@ -106,6 +109,12 @@ export const WalletItem = memo(function WalletItem({ }, [wallet]) const extraName = domain && domain !== wallet.name ? ` (${formatDomainName(domain)})` : '' + const { wallets: fireflyWallets } = useWallets() + const isFireflyWallet = useMemo( + () => fireflyWallets.some((w) => isSameAddress(w.address, wallet.address)), + [fireflyWallets, wallet.address], + ) + const fireflyAccount = useSubscription(PersistentStorages.Settings.storage.firefly_account.subscription) return ( (function WalletItem({ onClick={handleSelect} secondaryAction={} {...rest}> - + - {`${wallet.name}${extraName}`} + + {isFireflyWallet ? fireflyAccount.displayName : `${wallet.name}${extraName}`} + {wallet.source === ImportSource.LocalGenerated || hiddenTag ? null : ( Imported diff --git a/packages/mask/popups/modals/WalletRenameModal/index.tsx b/packages/mask/popups/modals/WalletRenameModal/index.tsx index 226703e5124..0b306f79337 100644 --- a/packages/mask/popups/modals/WalletRenameModal/index.tsx +++ b/packages/mask/popups/modals/WalletRenameModal/index.tsx @@ -13,11 +13,12 @@ import { Trans } from '@lingui/react/macro' interface WalletRenameDrawerProps extends BottomDrawerProps { wallet?: Wallet + walletName?: string } -function WalletRenameDrawer({ wallet, ...rest }: WalletRenameDrawerProps) { +function WalletRenameDrawer({ wallet, walletName, ...rest }: WalletRenameDrawerProps) { const theme = useTheme() - const [name, setName] = useState('') + const [name, setName] = useState(walletName || '') const [error, setError] = useState() const contacts = useContacts() @@ -60,7 +61,7 @@ function WalletRenameDrawer({ wallet, ...rest }: WalletRenameDrawerProps) { sx={{ mt: 2 }} fullWidth autoFocus - placeholder={wallet?.name} + placeholder={walletName || wallet?.name} error={!!error} value={name} onChange={(e) => { diff --git a/packages/mask/popups/pages/Wallet/WalletSettings/Rename.tsx b/packages/mask/popups/pages/Wallet/WalletSettings/Rename.tsx index 29bd94941a3..a59d2a4bc12 100644 --- a/packages/mask/popups/pages/Wallet/WalletSettings/Rename.tsx +++ b/packages/mask/popups/pages/Wallet/WalletSettings/Rename.tsx @@ -4,10 +4,21 @@ import { Box, ListItem, Typography } from '@mui/material' import { useStyles } from './useStyles.js' import { WalletRenameModal } from '../../../modals/modal-controls.js' import { Trans } from '@lingui/react/macro' +import { useWallets } from '@privy-io/react-auth' +import { useMemo } from 'react' +import { isSameAddress } from '@masknet/web3-shared-base' +import { useSubscription } from 'use-subscription' +import { PersistentStorages } from '@masknet/shared-base' export function Rename() { const wallet = useWallet() const { classes, theme } = useStyles() + const { wallets: fireflyWallets } = useWallets() + const isFireflyWallet = useMemo( + () => fireflyWallets.some((w) => isSameAddress(w.address, wallet?.address)), + [fireflyWallets, wallet?.address], + ) + const fireflyAccount = useSubscription(PersistentStorages.Settings.storage.firefly_account.subscription) if (!wallet) return null @@ -17,6 +28,7 @@ export function Rename() { onClick={() => WalletRenameModal.open({ wallet, + walletName: wallet.name || (isFireflyWallet ? fireflyAccount.displayName : wallet.name), title: Rename, }) }> @@ -27,7 +39,9 @@ export function Rename() { - {wallet.name} + + {isFireflyWallet ? fireflyAccount.displayName : wallet.name} + diff --git a/packages/mask/popups/pages/Wallet/WalletSettings/ShowPrivateKey.tsx b/packages/mask/popups/pages/Wallet/WalletSettings/ShowPrivateKey.tsx index cca6b0aea4d..22de8b6ea67 100644 --- a/packages/mask/popups/pages/Wallet/WalletSettings/ShowPrivateKey.tsx +++ b/packages/mask/popups/pages/Wallet/WalletSettings/ShowPrivateKey.tsx @@ -1,20 +1,25 @@ +import { Trans } from '@lingui/react/macro' import { Icons } from '@masknet/icons' import { Box, ListItem, Typography } from '@mui/material' -import { useStyles } from './useStyles.js' import { ShowPrivateKeyModal } from '../../../modals/modal-controls.js' -import { Trans } from '@lingui/react/macro' +import { useStyles } from './useStyles.js' -export function ShowPrivateKey() { +interface Props { + disabled?: boolean +} +export const ShowPrivateKey = function ShowPrivateKey({ disabled }: Props) { const { classes, theme } = useStyles() return ( + sx={disabled ? { opacity: 0.5, cursor: 'not-allowed' } : undefined} + onClick={() => { + if (disabled) return ShowPrivateKeyModal.open({ title: Enter Payment Password, }) - }> + }}> diff --git a/packages/mask/popups/pages/Wallet/WalletSettings/index.tsx b/packages/mask/popups/pages/Wallet/WalletSettings/index.tsx index cfe96a0ac3f..2fc7e08eb73 100644 --- a/packages/mask/popups/pages/Wallet/WalletSettings/index.tsx +++ b/packages/mask/popups/pages/Wallet/WalletSettings/index.tsx @@ -1,7 +1,8 @@ import { Icons } from '@masknet/icons' -import { EMPTY_LIST, PopupModalRoutes } from '@masknet/shared-base' +import { EMPTY_LIST, PersistentStorages, PopupModalRoutes } from '@masknet/shared-base' import { ActionButton } from '@masknet/theme' import { useWallet, useWallets } from '@masknet/web3-hooks-base' +import { useWallets as usePrivyWallets } from '@privy-io/react-auth' import { isSameAddress } from '@masknet/web3-shared-base' import { Box, List, Typography } from '@mui/material' import { first } from 'lodash-es' @@ -21,6 +22,8 @@ import { useStyles } from './useStyles.js' import { HidingScamTx } from './HidingScamTx.js' import { Trans, useLingui } from '@lingui/react/macro' import { DisablePermit } from './DisablePermit.js' +import { useSubscription } from 'use-subscription' +import { WalletAvatar } from '../../../components/WalletAvatar/index.js' function getPathIndex(path?: string) { const rawIndex = path?.split('/').pop() @@ -33,6 +36,12 @@ export const Component = memo(function WalletSettings() { const modalNavigate = useModalNavigate() const wallet = useWallet() const allWallets = useWallets() + const { wallets: fireflyWallets } = usePrivyWallets() + const isFireflyWallet = useMemo( + () => fireflyWallets.some((w) => isSameAddress(w.address, wallet?.address)), + [fireflyWallets, wallet?.address], + ) + const fireflyAccount = useSubscription(PersistentStorages.Settings.storage.firefly_account.subscription) const handleSwitchWallet = useCallback(() => { modalNavigate(PopupModalRoutes.WalletAccount) @@ -65,9 +74,11 @@ export const Component = memo(function WalletSettings() {
- +
- {wallet.name} + + {isFireflyWallet ? fireflyAccount.displayName : wallet.name} + {wallet.address}
@@ -82,7 +93,7 @@ export const Component = memo(function WalletSettings() { - + diff --git a/packages/mask/popups/pages/Wallet/components/WalletHeader/UI.tsx b/packages/mask/popups/pages/Wallet/components/WalletHeader/UI.tsx index e21ca39bc2b..eaebd8b3ee9 100644 --- a/packages/mask/popups/pages/Wallet/components/WalletHeader/UI.tsx +++ b/packages/mask/popups/pages/Wallet/components/WalletHeader/UI.tsx @@ -1,16 +1,19 @@ +import { Trans } from '@lingui/react/macro' import { Icons } from '@masknet/icons' import { ChainIcon, CopyButton, FormattedAddress, ImageIcon, ProgressiveText } from '@masknet/shared' -import type { Wallet } from '@masknet/shared-base' +import { PersistentStorages, type Wallet } from '@masknet/shared-base' import { makeStyles, TextOverflowTooltip } from '@masknet/theme' import { EVMExplorerResolver } from '@masknet/web3-providers' -import type { ReasonableNetwork } from '@masknet/web3-shared-base' +import { isSameAddress, type ReasonableNetwork } from '@masknet/web3-shared-base' import { formatEthereumAddress, type ChainId, type NetworkType, type SchemaType } from '@masknet/web3-shared-evm' import { Box, Link, Typography } from '@mui/material' -import { memo, type MouseEvent } from 'react' +import { memo, useMemo, type MouseEvent } from 'react' import { useConnectedWallets } from '../../hooks/useConnected.js' import { ActionGroup } from '../ActionGroup/index.js' import { WalletAssetsValue } from './WalletAssetsValue.js' -import { Trans } from '@lingui/react/macro' +import { useWallets } from '@privy-io/react-auth' +import { useSubscription } from 'use-subscription' +import { WalletAvatar } from '../../../../components/WalletAvatar/index.js' const useStyles = makeStyles<{ disabled: boolean }>()((theme, { disabled }) => { const isDark = theme.palette.mode === 'dark' @@ -144,7 +147,13 @@ export const WalletHeaderUI = memo(function WalletHeaderUI( }) { const { classes, cx } = useStyles({ disabled }) const { data: connectedWallets, isPending } = useConnectedWallets(origin) + const { wallets: fireflyWallets } = useWallets() const connected = connectedWallets?.has(wallet.address) + const isFireflyWallet = useMemo( + () => fireflyWallets.some((w) => isSameAddress(w.address, wallet.address)), + [fireflyWallets, wallet.address], + ) + const fireflyAccount = useSubscription(PersistentStorages.Settings.storage.firefly_account.subscription) const addressLink = EVMExplorerResolver.addressLink(chainId, wallet.address) const networkName = currentNetwork?.name || currentNetwork?.fullName @@ -199,10 +208,12 @@ export const WalletHeaderUI = memo(function WalletHeaderUI( if (disabled) return onActionClick() }}> - + - {wallet.name} + + {isFireflyWallet ? fireflyAccount.displayName : wallet.name} + diff --git a/packages/web3-providers/src/Web3/EVM/providers/MaskWallet.ts b/packages/web3-providers/src/Web3/EVM/providers/MaskWallet.ts index d0f5d192148..2847cc09770 100644 --- a/packages/web3-providers/src/Web3/EVM/providers/MaskWallet.ts +++ b/packages/web3-providers/src/Web3/EVM/providers/MaskWallet.ts @@ -52,7 +52,7 @@ export class MaskWalletProvider extends BaseHostedProvider { const privyWallets = await Privy.getEvmWallets() const formattedPrivyWallets: Wallet[] = privyWallets.map((wallet) => ({ id: wallet.address, - name: 'Privy Wallet', + name: '', source: ImportSource.Privy, address: wallet.address, configurable: false,