Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: avoid fetching Safe Apps on all pages #3254

Merged
merged 9 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,50 +1,23 @@
import * as nextRouter from 'next/router'
import * as nextNav from 'next/navigation'
import useChainId from '@/hooks/useChainId'
import { render, waitFor } from '@/tests/test-utils'
import { SafeAppAccessPolicyTypes } from '@safe-global/safe-gateway-typescript-sdk'
import SafeTokenWidget from '..'
import { toBeHex } from 'ethers'
import { AppRoutes } from '@/config/routes'
import useSafeTokenAllocation, { useSafeVotingPower } from '@/hooks/useSafeTokenAllocation'

const MOCK_GOVERNANCE_APP_URL = 'https://mock.governance.safe.global'

jest.mock('@/hooks/useChainId', () => jest.fn(() => '1'))

jest.mock('@/hooks/useSafeTokenAllocation')

jest.mock(
'@/hooks/safe-apps/useRemoteSafeApps',
jest.fn(() => ({
useRemoteSafeApps: () => [
[
{
id: 61,
url: MOCK_GOVERNANCE_APP_URL,
chainIds: ['4'],
name: 'Safe {DAO} Governance',
description: '',
iconUrl: '',
tags: ['safe-dao-governance-app'],
accessControl: {
type: SafeAppAccessPolicyTypes.NoRestrictions,
},
},
],
],
})),
)

describe('SafeTokenWidget', () => {
const fakeSafeAddress = toBeHex('0x1', 20)
beforeEach(() => {
jest.restoreAllMocks()
jest.spyOn(nextRouter, 'useRouter').mockImplementation(
jest.spyOn(nextNav, 'useSearchParams').mockImplementation(
() =>
({
query: {
safe: fakeSafeAddress,
},
get: () => fakeSafeAddress,
} as any),
)
})
Expand Down Expand Up @@ -90,7 +63,9 @@ describe('SafeTokenWidget', () => {
const result = render(<SafeTokenWidget />)
await waitFor(() => {
expect(result.baseElement).toContainHTML(
`href="${AppRoutes.apps.open}?safe=${fakeSafeAddress}&appUrl=${encodeURIComponent(MOCK_GOVERNANCE_APP_URL)}"`,
`href="${AppRoutes.apps.open}?safe=${fakeSafeAddress}&appUrl=${encodeURIComponent(
'https://safe-dao-governance.dev.5afe.dev',
)}`,
)
})
})
Expand Down
34 changes: 10 additions & 24 deletions src/components/common/SafeTokenWidget/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { SafeAppsTag, SAFE_TOKEN_ADDRESSES } from '@/config/constants'
import { IS_PRODUCTION, SAFE_TOKEN_ADDRESSES } from '@/config/constants'
import { AppRoutes } from '@/config/routes'
import { useRemoteSafeApps } from '@/hooks/safe-apps/useRemoteSafeApps'
import useChainId from '@/hooks/useChainId'
import useSafeTokenAllocation, { useSafeVotingPower, type Vesting } from '@/hooks/useSafeTokenAllocation'
import { OVERVIEW_EVENTS } from '@/services/analytics'
import { formatVisualAmount } from '@/utils/formatters'
import { Box, Button, ButtonBase, Skeleton, Tooltip, Typography } from '@mui/material'
import Link from 'next/link'
import { useRouter } from 'next/router'
import type { UrlObject } from 'url'
import { useSearchParams } from 'next/navigation'
import Track from '../Track'
import SafeTokenIcon from '@/public/images/common/safe-token.svg'
import css from './styles.module.css'
Expand Down Expand Up @@ -36,13 +34,11 @@ const canRedeemSep5Airdrop = (allocation?: Vesting[]): boolean => {
return !sep5Allocation.isRedeemed && !sep5Allocation.isExpired
}

const SEP5_DEADLINE = '27.10'
const GOVERNANCE_APP_URL = IS_PRODUCTION ? 'https://governance.safe.global' : 'https://safe-dao-governance.dev.5afe.dev'

const SafeTokenWidget = () => {
const chainId = useChainId()
const router = useRouter()
const [apps] = useRemoteSafeApps(SafeAppsTag.SAFE_GOVERNANCE_APP)
const governanceApp = apps?.[0]
const query = useSearchParams()

const [allocationData, , allocationDataLoading] = useSafeTokenAllocation()
const [allocation, , allocationLoading] = useSafeVotingPower(allocationData)
Expand All @@ -52,30 +48,20 @@ const SafeTokenWidget = () => {
return null
}

const url: UrlObject | undefined = governanceApp
? {
pathname: AppRoutes.apps.open,
query: { safe: router.query.safe, appUrl: governanceApp.url },
}
: undefined
const url = {
pathname: AppRoutes.apps.open,
query: { safe: query.get('safe'), appUrl: GOVERNANCE_APP_URL },
}

const canRedeemSep5 = canRedeemSep5Airdrop(allocationData)
const flooredSafeBalance = formatVisualAmount(allocation || BigInt(0), TOKEN_DECIMALS, 2)

return (
<Box className={css.container}>
<Tooltip
title={
url
? canRedeemSep5
? `Claim any amount until ${SEP5_DEADLINE} to be eligible!`
: `Open ${governanceApp?.name}`
: ''
}
>
<Tooltip title="Go to Safe{DAO} Governance">
<span>
<Track {...OVERVIEW_EVENTS.SAFE_TOKEN_WIDGET}>
<Link href={url || ''} passHref legacyBehavior>
<Link href={url} passHref legacyBehavior>
<ButtonBase
aria-describedby="safe-token-widget"
className={classnames(css.tokenButton, { [css.sep5]: canRedeemSep5 })}
Expand Down
11 changes: 9 additions & 2 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ export const CYPRESS_MNEMONIC = process.env.NEXT_PUBLIC_CYPRESS_MNEMONIC || ''
// Safe Token
export const SAFE_TOKEN_ADDRESSES: { [chainId: string]: string } = {
[chains.eth]: '0x5aFE3855358E112B5647B952709E6165e1c1eEEe',
[chains.rin]: '0xCFf1b0FdE85C102552D1D96084AF148f478F964A',
[chains.gor]: '0x61fD3b6d656F39395e32f46E2050953376c3f5Ff',
}

// Safe Apps
Expand Down Expand Up @@ -60,6 +58,15 @@ export enum SafeAppsTag {
ONRAMP = 'onramp',
}

export const WC_APP_PROD = {
id: 111,
url: 'https://apps-portal.safe.global/wallet-connect',
}
export const WC_APP_DEV = {
id: 25,
url: 'https://safe-apps.dev.5afe.dev/wallet-connect',
}

// Safe Gelato relay service
export const SAFE_RELAY_SERVICE_URL_PRODUCTION =
process.env.NEXT_PUBLIC_SAFE_RELAY_SERVICE_URL_PRODUCTION || 'https://safe-client.safe.global/v1/relay'
Expand Down
20 changes: 2 additions & 18 deletions src/features/walletconnect/__tests__/WalletConnectContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,6 @@ import * as useSafeWalletProvider from '@/services/safe-wallet-provider/useSafeW
jest.mock('../services/WalletConnectWallet')
jest.mock('@/services/safe-wallet-provider/useSafeWalletProvider')

jest.mock('@/hooks/safe-apps/useRemoteSafeApps', () => ({
useRemoteSafeApps: () => [
[
{
id: 111,
url: 'https://apps-portal.safe.global/wallet-connect',
name: 'WC App',
iconUrl: 'https://test.com/icon.png',
description: 'Test App Description',
},
],
undefined,
false,
],
}))

const TestComponent = () => {
const { walletConnect, error } = useContext(WalletConnectContext)
return (
Expand Down Expand Up @@ -426,10 +410,10 @@ describe('WalletConnectProvider', () => {
1,
{ method: 'fake', params: [] },
{
id: 111,
id: 25,
name: 'name',
description: 'description',
url: 'https://apps-portal.safe.global/wallet-connect',
url: 'https://safe-apps.dev.5afe.dev/wallet-connect',
iconUrl: 'iconUrl',
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import { formatJsonRpcError } from '@walletconnect/jsonrpc-utils'
import useSafeInfo from '@/hooks/useSafeInfo'
import useSafeWalletProvider from '@/services/safe-wallet-provider/useSafeWalletProvider'
import { asError } from '@/services/exceptions/utils'
import { IS_PRODUCTION } from '@/config/constants'
import { SafeAppsTag } from '@/config/constants'
import { useRemoteSafeApps } from '@/hooks/safe-apps/useRemoteSafeApps'
import { IS_PRODUCTION, WC_APP_DEV, WC_APP_PROD } from '@/config/constants'
import { getPeerName, stripEip155Prefix } from '@/features/walletconnect/services/utils'
import { trackRequest } from '@/features/walletconnect//services/tracking'
import { wcPopupStore } from '@/features/walletconnect/components'
Expand All @@ -18,18 +16,15 @@ enum Errors {
WRONG_CHAIN = '%%dappName%% made a request on a different chain than the one you are connected to',
}

const WalletConnectSafeApp = IS_PRODUCTION ? WC_APP_PROD : WC_APP_DEV

const walletConnectSingleton = new WalletConnectWallet()

const getWrongChainError = (dappName: string): Error => {
const message = Errors.WRONG_CHAIN.replace('%%dappName%%', dappName)
return new Error(message)
}

const useWalletConnectApp = () => {
const [matchingApps] = useRemoteSafeApps(SafeAppsTag.WALLET_CONNECT)
return matchingApps?.[0]
}

export const WalletConnectProvider = ({ children }: { children: ReactNode }) => {
const {
safe: { chainId },
Expand All @@ -40,7 +35,6 @@ export const WalletConnectProvider = ({ children }: { children: ReactNode }) =>
const setOpen = wcPopupStore.setStore
const [error, setError] = useState<Error | null>(null)
const safeWalletProvider = useSafeWalletProvider()
const wcApp = useWalletConnectApp()

// Init WalletConnect
useEffect(() => {
Expand Down Expand Up @@ -88,8 +82,8 @@ export const WalletConnectProvider = ({ children }: { children: ReactNode }) =>

// Get response from Safe Wallet Provider
return safeWalletProvider.request(event.id, event.params.request, {
id: wcApp?.id || -1,
url: wcApp?.url || '',
id: WalletConnectSafeApp.id,
url: WalletConnectSafeApp.url,
name: getPeerName(session.peer) || 'Unknown dApp',
description: session.peer.metadata.description,
iconUrl: session.peer.metadata.icons[0],
Expand All @@ -105,7 +99,7 @@ export const WalletConnectProvider = ({ children }: { children: ReactNode }) =>
setError(asError(e))
}
})
}, [walletConnect, chainId, safeWalletProvider, wcApp])
}, [walletConnect, chainId, safeWalletProvider])

return (
<WalletConnectContext.Provider value={{ walletConnect, error, setError, open, setOpen }}>
Expand Down
2 changes: 1 addition & 1 deletion src/services/analytics/__tests__/tx-tracking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ describe('getTransactionTrackingType', () => {
type: TransactionInfoType.CUSTOM,
},
safeAppInfo: {
url: 'https://apps-portal.safe.global/wallet-connect',
url: 'https://safe-apps.dev.5afe.dev/wallet-connect',
},
} as unknown)

Expand Down
7 changes: 2 additions & 5 deletions src/utils/gateway.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { WC_APP_PROD, WC_APP_DEV } from '@/config/constants'
import type { ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'

export const _replaceTemplate = (uri: string, data: Record<string, string>): string => {
Expand Down Expand Up @@ -28,9 +29,5 @@ export const getExplorerLink = (
}

export const isWalletConnectSafeApp = (url: string): boolean => {
const WC_APP_URLS = [
'https://apps-portal.safe.global/wallet-connect',
'https://safe-apps.dev.5afe.dev/wallet-connect',
]
return WC_APP_URLS.includes(url)
return url === WC_APP_PROD.url || url === WC_APP_DEV.url
}
Loading