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

feat: use injected web3 rpc if available #16

Open
wants to merge 2 commits into
base: eternalsafe
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 2 additions & 3 deletions src/components/settings/EnvironmentVariables/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const EnvironmentVariables = () => {
const formMethods = useForm<EnvVariablesFormData>({
mode: 'onChange',
values: {
[EnvVariablesField.rpc]: settings.env?.rpc[chainId] ?? chain?.publicRpcUri.value ?? '',
[EnvVariablesField.rpc]: settings.env?.rpc[chainId] ?? '',
[EnvVariablesField.ipfs]: settings.env?.ipfs ?? '',
[EnvVariablesField.tenderlyOrgName]: settings.env?.tenderly.orgName ?? '',
[EnvVariablesField.tenderlyProjectName]: settings.env?.tenderly.projectName ?? '',
Expand Down Expand Up @@ -149,7 +149,7 @@ const EnvironmentVariables = () => {
</Typography>

<TextField
{...register(EnvVariablesField.rpc, { required: true })}
{...register(EnvVariablesField.rpc)}
variant="outlined"
type="url"
InputProps={{
Expand All @@ -174,7 +174,6 @@ const EnvironmentVariables = () => {
),
}}
fullWidth
required
/>

<Typography fontWeight={700} mb={2} mt={3}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('FallbackHandler', () => {
beforeEach(() => {
jest.clearAllMocks()

// TODO(devanon): Re-enable when the Transaction Builder is ready
// TODO(eternalsafe): Re-enable when the Transaction Builder is ready
// jest.spyOn(useTxBuilderHook, 'useTxBuilderApp').mockImplementation(() => ({
// link: { href: 'https://mock.link/tx-builder' },
// }))
Expand Down Expand Up @@ -123,12 +123,12 @@ describe('FallbackHandler', () => {
new RegExp('Eternal Safe may not work correctly as no fallback handler is currently set.'),
),
).toBeInTheDocument()
// TODO(devanon): Re-enable when the Transaction Builder is ready
// TODO(eternalsafe): Re-enable when the Transaction Builder is ready
// expect(fbHandler.queryByText('Transaction Builder')).toBeInTheDocument()
})
})

// TODO(devanon): Re-enable when the Transaction Builder is ready
// TODO(eternalsafe): Re-enable when the Transaction Builder is ready
// it('should conditionally append the Transaction Builder link', async () => {
// jest.spyOn(useTxBuilderHook, 'useTxBuilderApp').mockImplementation(() => undefined)

Expand Down Expand Up @@ -184,7 +184,7 @@ describe('FallbackHandler', () => {

await waitFor(() => {
expect(fbHandler.queryByText(new RegExp('An unofficial fallback handler is currently set.')))
// TODO(devanon): Re-enable when the Transaction Builder is ready
// TODO(eternalsafe): Re-enable when the Transaction Builder is ready
// expect(fbHandler.queryByText('Transaction Builder')).toBeInTheDocument()
})
})
Expand Down
2 changes: 1 addition & 1 deletion src/components/sidebar/PendingActions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import css from './styles.module.css'
// import classnames from 'classnames'
import { AppRoutes } from '@/config/routes'

// TODO(devanon): Re-add this after refactoring the stored queue to load all transactions at the same time
// TODO(eternalsafe): Re-add this after refactoring the stored queue to load all transactions at the same time
const PendingActionButtons = ({
totalQueued,
totalToSign,
Expand Down
2 changes: 1 addition & 1 deletion src/components/sidebar/SafeList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const SafeList = ({ closeDrawer }: { closeDrawer?: () => void }): ReactElement =

{!isWelcomePage && (
<Link
href={{ pathname: AppRoutes.welcome.index, query: { chain: currentChain?.shortName } }}
href={{ pathname: AppRoutes.newSafe.load, query: { chain: currentChain?.shortName } }}
passHref
legacyBehavior
>
Expand Down
18 changes: 10 additions & 8 deletions src/components/welcome/WelcomeLogin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { selectRpc } from '@/store/settingsSlice'
import LoadRPCUrl from '@/components/welcome/WelcomeLogin/LoadRPCUrl'
import { CHAINLIST_URL } from '@/config/constants'
import { useEffect, useState } from 'react'
import { useWeb3 } from '@/hooks/wallets/web3'

const WelcomeLogin = () => {
const web3 = useWeb3()
const chain = useCurrentChain()
const customRpc = useAppSelector(selectRpc)
const customRpcUrl = chain ? customRpc?.[chain.chainId] : undefined
Expand All @@ -29,18 +31,20 @@ const WelcomeLogin = () => {
<Typography variant="h3" mt="auto" pt={5} fontWeight={700}>
Eternal Safe
</Typography>
{customRpcUrl && !forceShowRpcInput ? (
{/* TODO(eternalsafe): Gracefully handle the web3 variable loading in after sometime */}
{(web3 || customRpcUrl) && !forceShowRpcInput ? (
<>
<Typography mb={2} textAlign="center">
Eternal Safe does not yet support creating a Safe, you must have one already created.
</Typography>
<LoadSafe />
{/* TODO(devanon): Allow import of data here */}
{/* TODO(eternalsafe): Allow import of data here */}
</>
) : chain ? (
<>
<Typography textAlign="center">
To get started you must provide a RPC URL for the {chain.chainName} network.
To get started you must connect a wallet on {chain.chainName} or provide a RPC URL for the{' '}
{chain.chainName} network.
<br />
<br />
For best performance we recommend using a private RPC URL. Public URLs can be found on{' '}
Expand All @@ -61,11 +65,9 @@ const WelcomeLogin = () => {
)}

<Typography variant="subtitle2" textAlign="center" mt="auto" pt={3}>
{customRpcUrl && (
<Link type="button" component="button" onClick={toggleShowRpcInput} color="primary">
{forceShowRpcInput ? 'Close' : 'Open'} RPC URL input
</Link>
)}
<Link type="button" component="button" onClick={toggleShowRpcInput} color="primary">
{forceShowRpcInput ? 'Close' : 'Open'} RPC URL input
</Link>
</Typography>
</Box>
</Paper>
Expand Down
38 changes: 21 additions & 17 deletions src/hooks/wallets/useInitWeb3.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useEffect } from 'react'

import { useCurrentChain } from '@/hooks/useChains'
import useWallet from '@/hooks/wallets/useWallet'
import {
Expand All @@ -9,12 +8,14 @@ import {
setMultiWeb3ReadOnly,
setWeb3,
setWeb3ReadOnly,
useWeb3,
} from '@/hooks/wallets/web3'
import { useAppDispatch, useAppSelector } from '@/store'
import { selectRpc, setRpc } from '@/store/settingsSlice'
import { useRouter } from 'next/router'
import { AppRoutes } from '@/config/routes'
import { closeByGroupKey, showNotification } from '@/store/notificationsSlice'
import { MulticallWrapper } from 'ethers-multicall-provider'

const RPC_URL_ERROR_KEY = 'rpc-url-error'

Expand All @@ -26,30 +27,33 @@ export const useInitWeb3 = () => {
const wallet = useWallet()
const customRpc = useAppSelector(selectRpc)
const customRpcUrl = chain ? customRpc?.[chain.chainId] : undefined

useEffect(() => {
if (wallet && wallet.chainId === chainId) {
const web3 = createWeb3(wallet.provider)
setWeb3(web3)
} else {
setWeb3(undefined)
}
}, [wallet, chainId])
const web3 = useWeb3()

useEffect(() => {
if (!customRpcUrl || !chainId) {
setWeb3ReadOnly(undefined)
setMultiWeb3ReadOnly(undefined)

if (chain && router.pathname !== AppRoutes.welcome.index && router.pathname !== AppRoutes.index) {
if (!wallet && !web3) {
setWeb3(undefined)
return
}
if (wallet && wallet.chainId !== chainId) {
dispatch(
showNotification({
message: `No RPC URL saved for ${chain.chainName ?? 'this'} network. You must provide one to continue.`,
message: `Your wallet seems to be connected to the wrong network. You must change your wallet network to ${
chain?.chainName ?? 'the same network'
}.`,
groupKey: RPC_URL_ERROR_KEY,
variant: 'error',
}),
)
router.push({ pathname: AppRoutes.welcome.index, query: { chain: chain.shortName } })
return
}
if (wallet && wallet.chainId === chainId) {
const internalWeb3 = createWeb3(wallet.provider)
setWeb3(MulticallWrapper.wrap(internalWeb3, 50))
if (internalWeb3) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add dispatch(closeByGroupKey({ groupKey: RPC_URL_ERROR_KEY })) above this line please so that the "Your wallet seems to be connected to the wrong network" notification is automatically dismissed after the user does set their wallet to the right network? Thanks!

setWeb3ReadOnly(internalWeb3)
setMultiWeb3ReadOnly(MulticallWrapper.wrap(internalWeb3, 50))
}
}
return
}
Expand Down Expand Up @@ -83,5 +87,5 @@ export const useInitWeb3 = () => {
router.push({ pathname: AppRoutes.welcome.index, query: { chain: chain.shortName } })
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [customRpcUrl, chain, router, dispatch])
}, [customRpcUrl, chain, wallet, chainId, router, dispatch])
}
6 changes: 3 additions & 3 deletions src/hooks/wallets/web3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ export const createWeb3ReadOnly = (customRpc: string): JsonRpcProvider => {
return new JsonRpcProvider({ url: customRpc, timeout: 10_000 })
}

export const createMultiWeb3ReadOnly = (customRpc: string, network: Network): MulticallProvider => {
export const createMultiWeb3ReadOnly = (customRpc: string, network: Network): MulticallProvider<JsonRpcProvider> => {
return MulticallWrapper.wrap(new JsonRpcProvider(customRpc, network), 50)
}

export const createWeb3 = (walletProvider: EIP1193Provider): Web3Provider => {
return new Web3Provider(walletProvider)
}

export const { setStore: setWeb3, useStore: useWeb3 } = new ExternalStore<Web3Provider>()
export const { setStore: setWeb3, useStore: useWeb3 } = new ExternalStore<MulticallProvider<Web3Provider>>()

export const {
getStore: getWeb3ReadOnly,
Expand All @@ -28,7 +28,7 @@ export const {
getStore: getMultiWeb3ReadOnly,
setStore: setMultiWeb3ReadOnly,
useStore: useMultiWeb3ReadOnly,
} = new ExternalStore<MulticallProvider>()
} = new ExternalStore<MulticallProvider<Web3Provider | JsonRpcProvider>>()

export const getUserNonce = async (userAddress: string): Promise<number> => {
const web3 = getWeb3ReadOnly()
Expand Down
Loading