From 06a35f595d77512b51904ebac3060fbb826a6c8c Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Tue, 13 Feb 2024 10:20:31 +0100
Subject: [PATCH] Feat: My Accounts page (#3233)
---
cypress/e2e/pages/create_wallet.pages.js | 7 +-
.../e2e/regression/create_safe_simple.cy.js | 9 +++
cypress/e2e/safe-apps/tx-builder.spec.cy.js | 6 +-
cypress/e2e/smoke/create_safe_simple.cy.js | 4 +
.../common/ChainIndicator/index.tsx | 11 ++-
.../common/ChainIndicator/styles.module.css | 13 +++-
src/components/common/EthHashInfo/index.tsx | 2 +-
.../common/NetworkSelector/index.tsx | 6 +-
.../welcome/MyAccounts/AccountItem.tsx | 66 ++++++++++++++++
.../welcome/MyAccounts/CreateButton.tsx | 28 +++++++
src/components/welcome/MyAccounts/index.tsx | 77 +++++++++++++++++++
.../welcome/MyAccounts/styles.module.css | 37 +++++++++
.../welcome/MyAccounts/useAllOwnedSafes.ts | 11 +++
.../welcome/MyAccounts/useAllSafes.ts | 57 ++++++++++++++
.../welcome/WelcomeLogin/WalletLogin.tsx | 4 +-
src/components/welcome/WelcomeLogin/index.tsx | 33 ++++----
src/config/routes.ts | 3 +-
src/hooks/__tests__/useChainId.test.ts | 42 +---------
src/hooks/useChainId.ts | 27 +++----
src/hooks/useIsSidebarRoute.ts | 1 +
src/pages/welcome/accounts.tsx | 17 ++++
.../analytics/events/createLoadSafe.ts | 5 ++
src/services/analytics/events/overview.ts | 9 +++
23 files changed, 387 insertions(+), 88 deletions(-)
create mode 100644 src/components/welcome/MyAccounts/AccountItem.tsx
create mode 100644 src/components/welcome/MyAccounts/CreateButton.tsx
create mode 100644 src/components/welcome/MyAccounts/index.tsx
create mode 100644 src/components/welcome/MyAccounts/styles.module.css
create mode 100644 src/components/welcome/MyAccounts/useAllOwnedSafes.ts
create mode 100644 src/components/welcome/MyAccounts/useAllSafes.ts
create mode 100644 src/pages/welcome/accounts.tsx
diff --git a/cypress/e2e/pages/create_wallet.pages.js b/cypress/e2e/pages/create_wallet.pages.js
index 4d458ddd43..77c4e945ef 100644
--- a/cypress/e2e/pages/create_wallet.pages.js
+++ b/cypress/e2e/pages/create_wallet.pages.js
@@ -10,7 +10,8 @@ const ownerAddress = 'input[name^="owners"][name$="address"]'
const thresholdInput = 'input[name="threshold"]'
export const removeOwnerBtn = 'button[aria-label="Remove owner"]'
const connectingContainer = 'div[class*="connecting-container"]'
-const createNewSafeBtn = 'span[data-track="create-safe: Continue to creation"]'
+const createNewSafeBtn = '[data-testid="create-safe-btn"]'
+const continueWithWalletBtn = 'span[data-track="create-safe: Continue to my accounts"]'
const connectWalletBtn = 'Connect wallet'
const googleConnectBtn = '[data-testid="google-connect-btn"]'
const googleSignedinBtn = '[data-testid="signed-in-account-btn"]'
@@ -110,6 +111,10 @@ export function clickOnCreateNewSafeBtn() {
cy.get(createNewSafeBtn).click().wait(1000)
}
+export function clickOnContinueWithWalletBtn() {
+ cy.get(continueWithWalletBtn).click().wait(1000)
+}
+
export function clickOnConnectWalletBtn() {
cy.get(welcomeLoginScreen).within(() => {
cy.get('button').contains(connectWalletBtn).should('be.visible').should('be.enabled').click().wait(1000)
diff --git a/cypress/e2e/regression/create_safe_simple.cy.js b/cypress/e2e/regression/create_safe_simple.cy.js
index f8627e89d9..327179d93e 100644
--- a/cypress/e2e/regression/create_safe_simple.cy.js
+++ b/cypress/e2e/regression/create_safe_simple.cy.js
@@ -14,6 +14,7 @@ describe('Safe creation tests', () => {
it('Verify Next button is disabled until switching to network is done', () => {
owner.waitForConnectionStatus()
createwallet.selectNetwork(constants.networks.ethereum)
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.checkNetworkChangeWarningMsg()
createwallet.verifyNextBtnIsDisabled()
@@ -24,6 +25,7 @@ describe('Safe creation tests', () => {
// TODO: Check unit tests
it('Verify error message is displayed if wallet name input exceeds 50 characters', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.typeWalletName(main.generateRandomString(51))
owner.verifyErrorMsgInvalidAddress(constants.addressBookErrrMsg.exceedChars)
@@ -34,6 +36,7 @@ describe('Safe creation tests', () => {
// TODO: Check unit tests
it('Verify there is no error message is displayed if wallet name input contains less than 50 characters', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.typeWalletName(main.generateRandomString(50))
owner.verifyValidWalletName(constants.addressBookErrrMsg.exceedChars)
@@ -41,6 +44,7 @@ describe('Safe creation tests', () => {
it('Verify current connected account is shown as default owner', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.clickOnNextBtn()
owner.verifyExistingOwnerAddress(0, constants.DEFAULT_OWNER_ADDRESS)
@@ -49,6 +53,7 @@ describe('Safe creation tests', () => {
// TODO: Check unit tests
it('Verify error message is displayed if owner name input exceeds 50 characters', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
owner.typeExistingOwnerName(main.generateRandomString(51))
owner.verifyErrorMsgInvalidAddress(constants.addressBookErrrMsg.exceedChars)
@@ -57,6 +62,7 @@ describe('Safe creation tests', () => {
// TODO: Check unit tests
it('Verify there is no error message is displayed if owner name input contains less than 50 characters', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
owner.typeExistingOwnerName(main.generateRandomString(50))
owner.verifyValidWalletName(constants.addressBookErrrMsg.exceedChars)
@@ -65,6 +71,7 @@ describe('Safe creation tests', () => {
it('Verify data persistence', () => {
const ownerName = 'David'
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
@@ -97,6 +104,7 @@ describe('Safe creation tests', () => {
it('Verify tip is displayed on right side for threshold 1/1', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.clickOnNextBtn()
createwallet.verifyPolicy1_1()
@@ -105,6 +113,7 @@ describe('Safe creation tests', () => {
// TODO: Check unit tests
it('Verify address input validation rules', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
diff --git a/cypress/e2e/safe-apps/tx-builder.spec.cy.js b/cypress/e2e/safe-apps/tx-builder.spec.cy.js
index c021504610..4179b8bf46 100644
--- a/cypress/e2e/safe-apps/tx-builder.spec.cy.js
+++ b/cypress/e2e/safe-apps/tx-builder.spec.cy.js
@@ -197,7 +197,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
})
})
- it('Verify a batch cannot be created without asset amount', () => {
+ it.skip('Verify a batch cannot be created without asset amount', () => {
cy.enter(iframeSelector).then((getBody) => {
getBody().findByLabelText(safeapps.enterAddressStr).type(constants.SEPOLIA_TEST_SAFE_10)
getBody().findByText(safeapps.addTransactionStr).click()
@@ -266,7 +266,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
})
})
- it('Verify a valid batch as successful can be simulated', () => {
+ it.skip('Verify a valid batch as successful can be simulated', () => {
cy.enter(iframeSelector).then((getBody) => {
getBody().findByLabelText(safeapps.enterAddressStr).type(constants.SEPOLIA_TEST_SAFE_10)
getBody().findByLabelText(safeapps.tokenAmount).type('0')
@@ -278,7 +278,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
})
})
- it('Verify an invalid batch as failed can be simulated', () => {
+ it.skip('Verify an invalid batch as failed can be simulated', () => {
cy.enter(iframeSelector).then((getBody) => {
getBody().findByLabelText(safeapps.enterAddressStr).type(constants.SEPOLIA_TEST_SAFE_10)
getBody().findByLabelText(safeapps.tokenAmount).type('100')
diff --git a/cypress/e2e/smoke/create_safe_simple.cy.js b/cypress/e2e/smoke/create_safe_simple.cy.js
index 3578417fce..54e1491739 100644
--- a/cypress/e2e/smoke/create_safe_simple.cy.js
+++ b/cypress/e2e/smoke/create_safe_simple.cy.js
@@ -11,6 +11,7 @@ describe('[SMOKE] Safe creation tests', () => {
main.acceptCookies()
})
it('[SMOKE] Verify a Wallet can be connected', () => {
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
owner.clickOnWalletExpandMoreIcon()
owner.clickOnDisconnectBtn()
@@ -20,12 +21,14 @@ describe('[SMOKE] Safe creation tests', () => {
it('[SMOKE] Verify that a new Wallet has default name related to the selected network', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.verifyDefaultWalletName(createwallet.defaltSepoliaPlaceholder)
})
it('[SMOKE] Verify Add and Remove Owner Row works as expected', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
@@ -40,6 +43,7 @@ describe('[SMOKE] Safe creation tests', () => {
it('[SMOKE] Verify Threshold Setup', () => {
owner.waitForConnectionStatus()
+ createwallet.clickOnContinueWithWalletBtn()
createwallet.clickOnCreateNewSafeBtn()
createwallet.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
diff --git a/src/components/common/ChainIndicator/index.tsx b/src/components/common/ChainIndicator/index.tsx
index ab84e47a71..f113146f16 100644
--- a/src/components/common/ChainIndicator/index.tsx
+++ b/src/components/common/ChainIndicator/index.tsx
@@ -15,6 +15,7 @@ type ChainIndicatorProps = {
className?: string
showUnknown?: boolean
showLogo?: boolean
+ responsive?: boolean
}
const fallbackChainConfig = {
@@ -32,6 +33,7 @@ const ChainIndicator = ({
inline = false,
showUnknown = true,
showLogo = true,
+ responsive = false,
}: ChainIndicatorProps): ReactElement | null => {
const currentChainId = useChainId()
const id = chainId || currentChainId
@@ -56,7 +58,12 @@ const ChainIndicator = ({
{showLogo && (
)}
- {chainConfig.chainName}
+ {chainConfig.chainName}
) : null
}
diff --git a/src/components/common/ChainIndicator/styles.module.css b/src/components/common/ChainIndicator/styles.module.css
index fee2c496dc..42f18a2504 100644
--- a/src/components/common/ChainIndicator/styles.module.css
+++ b/src/components/common/ChainIndicator/styles.module.css
@@ -1,9 +1,9 @@
.indicator {
display: flex;
align-items: center;
- justify-content: center;
min-width: 70px;
font-size: 12px;
+ justify-content: center;
}
.inlineIndicator {
@@ -21,5 +21,16 @@
align-items: center;
gap: var(--space-1);
padding: 0;
+ min-width: 115px;
font-size: 14px;
+ justify-content: start;
+}
+
+@media (max-width: 899.95px) {
+ .responsive .name {
+ display: none;
+ }
+.indicator {
+ min-width: 35px;
+}
}
diff --git a/src/components/common/EthHashInfo/index.tsx b/src/components/common/EthHashInfo/index.tsx
index 7d6821f2ba..18559af22e 100644
--- a/src/components/common/EthHashInfo/index.tsx
+++ b/src/components/common/EthHashInfo/index.tsx
@@ -16,7 +16,7 @@ const EthHashInfo = ({
const currentChainId = useChainId()
const chain = useAppSelector((state) => selectChainById(state, props.chainId || currentChainId))
const addressBook = useAddressBook()
- const link = chain ? getBlockExplorerLink(chain, props.address) : undefined
+ const link = chain && props.hasExplorer ? getBlockExplorerLink(chain, props.address) : undefined
const name = showName ? addressBook[props.address] || props.name : undefined
return (
diff --git a/src/components/common/NetworkSelector/index.tsx b/src/components/common/NetworkSelector/index.tsx
index 60d45f68bf..34981d95fc 100644
--- a/src/components/common/NetworkSelector/index.tsx
+++ b/src/components/common/NetworkSelector/index.tsx
@@ -19,8 +19,6 @@ import useWallet from '@/hooks/wallets/useWallet'
import { isSocialWalletEnabled } from '@/hooks/wallets/wallets'
import { isSocialLoginWallet } from '@/services/mpc/SocialLoginModule'
-const keepPathRoutes = [AppRoutes.welcome.index, AppRoutes.newSafe.create, AppRoutes.newSafe.load]
-
const MenuWithTooltip = forwardRef(function MenuWithTooltip(props: any, ref) {
return (
@@ -43,10 +41,10 @@ const NetworkSelector = (props: { onChainSelect?: () => void }): ReactElement =>
const getNetworkLink = useCallback(
(shortName: string) => {
- const shouldKeepPath = keepPathRoutes.includes(router.pathname)
+ const shouldKeepPath = !router.query.safe
const route = {
- pathname: shouldKeepPath ? router.pathname : '/',
+ pathname: shouldKeepPath ? router.pathname : AppRoutes.index,
query: {
chain: shortName,
} as {
diff --git a/src/components/welcome/MyAccounts/AccountItem.tsx b/src/components/welcome/MyAccounts/AccountItem.tsx
new file mode 100644
index 0000000000..06ef5412b3
--- /dev/null
+++ b/src/components/welcome/MyAccounts/AccountItem.tsx
@@ -0,0 +1,66 @@
+import { useMemo } from 'react'
+import { ListItemButton, Box, Typography } from '@mui/material'
+import Link from 'next/link'
+import SafeIcon from '@/components/common/SafeIcon'
+import Track from '@/components/common/Track'
+import { OPEN_SAFE_LABELS, OVERVIEW_EVENTS } from '@/services/analytics'
+import { AppRoutes } from '@/config/routes'
+import { useAppSelector } from '@/store'
+import { selectChainById } from '@/store/chainsSlice'
+import ChainIndicator from '@/components/common/ChainIndicator'
+import css from './styles.module.css'
+import { selectAllAddressBooks } from '@/store/addressBookSlice'
+import { shortenAddress } from '@/utils/formatters'
+import SafeListContextMenu from '@/components/sidebar/SafeListContextMenu'
+
+type AccountItemProps = {
+ chainId: string
+ address: string
+ threshold?: number
+ owners?: number
+}
+
+const getSafeHref = (prefix: string, address: string) => ({
+ pathname: AppRoutes.home,
+ query: { safe: `${prefix}:${address}` },
+})
+
+const AccountItem = ({ chainId, address, ...rest }: AccountItemProps) => {
+ const chain = useAppSelector((state) => selectChainById(state, chainId))
+
+ const href = useMemo(() => {
+ return chain ? getSafeHref(chain.shortName, address) : ''
+ }, [chain, address])
+
+ const name = useAppSelector(selectAllAddressBooks)[chainId]?.[address]
+
+ return (
+
+
+
+
+
+ )
+}
+
+export default AccountItem
diff --git a/src/components/welcome/MyAccounts/CreateButton.tsx b/src/components/welcome/MyAccounts/CreateButton.tsx
new file mode 100644
index 0000000000..6cef3dae4e
--- /dev/null
+++ b/src/components/welcome/MyAccounts/CreateButton.tsx
@@ -0,0 +1,28 @@
+import { Button } from '@mui/material'
+import Link from 'next/link'
+import { AppRoutes } from '@/config/routes'
+import { OVERVIEW_EVENTS, trackEvent } from '@/services/analytics'
+
+const buttonSx = { width: ['100%', 'auto'] }
+
+const onClick = () => {
+ trackEvent(OVERVIEW_EVENTS.CREATE_NEW_SAFE)
+}
+
+const CreateButton = () => (
+
+
+
+)
+
+export default CreateButton
diff --git a/src/components/welcome/MyAccounts/index.tsx b/src/components/welcome/MyAccounts/index.tsx
new file mode 100644
index 0000000000..2a19f8d582
--- /dev/null
+++ b/src/components/welcome/MyAccounts/index.tsx
@@ -0,0 +1,77 @@
+import { useMemo, useState } from 'react'
+import { Button, Box, Paper, Typography } from '@mui/material'
+import madProps from '@/utils/mad-props'
+import AccountItem from './AccountItem'
+import CreateButton from './CreateButton'
+import useAllSafes, { type SafeItems } from './useAllSafes'
+import Track from '@/components/common/Track'
+import { OVERVIEW_EVENTS } from '@/services/analytics'
+import { DataWidget } from '@/components/welcome/SafeListDrawer/DataWidget'
+import css from './styles.module.css'
+
+type AccountsListProps = {
+ safes: SafeItems
+}
+
+const DEFAULT_SHOWN = 5
+const MAX_DEFAULT_SHOWN = 7
+
+const AccountsList = ({ safes }: AccountsListProps) => {
+ const [maxShown, setMaxShown] = useState(DEFAULT_SHOWN)
+
+ const shownSafes = useMemo(() => {
+ if (safes.length <= MAX_DEFAULT_SHOWN) {
+ return safes
+ }
+ return safes.slice(0, maxShown)
+ }, [safes, maxShown])
+
+ const onShowMore = () => {
+ const pageSize = 100 // DEFAULT_SHOWN
+ setMaxShown((prev) => prev + pageSize)
+ }
+
+ return (
+
+
+
+
+ My Safe accounts
+
+ {' '}
+ ({safes.length})
+
+
+
+
+
+
+
+ {shownSafes.length ? (
+ shownSafes.map((item) => )
+ ) : (
+
+ You don't have any Safe Accounts yet
+
+ )}
+
+ {safes.length > shownSafes.length && (
+
+
+
+ )}
+
+
+
+
+
+ )
+}
+
+const MyAccounts = madProps(AccountsList, {
+ safes: useAllSafes,
+})
+
+export default MyAccounts
diff --git a/src/components/welcome/MyAccounts/styles.module.css b/src/components/welcome/MyAccounts/styles.module.css
new file mode 100644
index 0000000000..df7742fec5
--- /dev/null
+++ b/src/components/welcome/MyAccounts/styles.module.css
@@ -0,0 +1,37 @@
+.container {
+ width: 600px;
+}
+
+.listItem {
+ border: 1px solid var(--color-border-light);
+ border-radius: var(--space-1);
+ margin-bottom: 12px;
+ padding-top: var(--space-2);
+ padding-bottom: var(--space-2);
+}
+
+.listItem > :first-child {
+ flex: 1;
+}
+
+.safeLink {
+ display: flex;
+ align-items: center;
+ padding-right: var(--space-1);
+}
+
+.safeAddress {
+ flex: 1;
+ white-space: nowrap;
+ padding-left: var(--space-2);
+}
+
+@media (max-width: 899.95px) {
+ .container {
+ width: auto;
+ }
+
+ .safeLink {
+ padding-right: 0;
+ }
+}
diff --git a/src/components/welcome/MyAccounts/useAllOwnedSafes.ts b/src/components/welcome/MyAccounts/useAllOwnedSafes.ts
new file mode 100644
index 0000000000..023bc00b91
--- /dev/null
+++ b/src/components/welcome/MyAccounts/useAllOwnedSafes.ts
@@ -0,0 +1,11 @@
+import { getAllOwnedSafes } from '@safe-global/safe-gateway-typescript-sdk'
+import useAsync from '@/hooks/useAsync'
+
+const useAllOwnedSafes = (address: string) => {
+ return useAsync(() => {
+ if (!address) return
+ return getAllOwnedSafes(address)
+ }, [address])
+}
+
+export default useAllOwnedSafes
diff --git a/src/components/welcome/MyAccounts/useAllSafes.ts b/src/components/welcome/MyAccounts/useAllSafes.ts
new file mode 100644
index 0000000000..4b064818c3
--- /dev/null
+++ b/src/components/welcome/MyAccounts/useAllSafes.ts
@@ -0,0 +1,57 @@
+import { useMemo } from 'react'
+import uniq from 'lodash/uniq'
+import isEmpty from 'lodash/isEmpty'
+import { useAppSelector } from '@/store'
+import { selectAllAddedSafes } from '@/store/addedSafesSlice'
+import useAllOwnedSafes from './useAllOwnedSafes'
+import useChains from '@/hooks/useChains'
+import useChainId from '@/hooks/useChainId'
+import useWallet from '@/hooks/wallets/useWallet'
+
+export type SafeItems = Array<{
+ chainId: string
+ address: string
+ threshold?: number
+ owners?: number
+}>
+
+const useAddedSafes = () => {
+ const allAdded = useAppSelector(selectAllAddedSafes)
+ return allAdded
+}
+
+export const useHasSafes = () => {
+ const { address = '' } = useWallet() || {}
+ const allAdded = useAddedSafes()
+ const hasAdded = isEmpty(allAdded)
+ const [allOwned] = useAllOwnedSafes(!hasAdded ? address : '') // pass an empty string to not fetch owned safes
+ return hasAdded || !isEmpty(allOwned)
+}
+
+const useAllSafes = (): SafeItems => {
+ const { address = '' } = useWallet() || {}
+ const [allOwned = {}] = useAllOwnedSafes(address)
+ const allAdded = useAddedSafes()
+ const { configs } = useChains()
+ const currentChainId = useChainId()
+
+ return useMemo(() => {
+ const chains = uniq([currentChainId].concat(Object.keys(allAdded)).concat(Object.keys(allOwned)))
+
+ return chains.flatMap((chainId) => {
+ if (!configs.some((item) => item.chainId === chainId)) return []
+ const addedOnChain = Object.keys(allAdded[chainId] || {})
+ const ownedOnChain = allOwned[chainId]
+ const uniqueAddresses = uniq(addedOnChain.concat(ownedOnChain)).filter(Boolean)
+
+ return uniqueAddresses.map((address) => ({
+ address,
+ chainId,
+ threshold: allAdded[chainId]?.[address]?.threshold,
+ owners: allAdded[chainId]?.[address]?.owners.length,
+ }))
+ })
+ }, [configs, allAdded, allOwned, currentChainId])
+}
+
+export default useAllSafes
diff --git a/src/components/welcome/WelcomeLogin/WalletLogin.tsx b/src/components/welcome/WelcomeLogin/WalletLogin.tsx
index 8add385375..fa8138974f 100644
--- a/src/components/welcome/WelcomeLogin/WalletLogin.tsx
+++ b/src/components/welcome/WelcomeLogin/WalletLogin.tsx
@@ -2,9 +2,9 @@ import useConnectWallet from '@/components/common/ConnectWallet/useConnectWallet
import Track from '@/components/common/Track'
import useWallet from '@/hooks/wallets/useWallet'
import { isSocialLoginWallet } from '@/services/mpc/SocialLoginModule'
-import { CREATE_SAFE_EVENTS } from '@/services/analytics'
import { Box, Button, Typography } from '@mui/material'
import EthHashInfo from '@/components/common/EthHashInfo'
+import { CREATE_SAFE_EVENTS } from '@/services/analytics'
const WalletLogin = ({ onLogin }: { onLogin: () => void }) => {
const wallet = useWallet()
@@ -15,7 +15,7 @@ const WalletLogin = ({ onLogin }: { onLogin: () => void }) => {
if (wallet !== null && !isSocialLogin) {
return (
-