Commit 3c371af3 authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

fix: only try SafeApp connection in an iframe (#2340)

* fix: only try SafeApp connection in an iframe

Improves non-iframe pageload by 300ms. Fixes #2338.

The Gnosis check for a SafeApp races a postMessage and a 300ms timeout [1]. The SafeApp embeds the interface in an iframe, so this avoids the check when not in iframes.

[1]: https://github.com/gnosis/safe-apps-sdk/blob/f224869dd5ae810db8cecad08fbbcfaa6c046d9d/packages/safe-apps-web3-react/src/connector.ts#L52

* refactor: IS_IN_IFRAME const
parent 5797a622
...@@ -5,6 +5,8 @@ export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' ...@@ -5,6 +5,8 @@ export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
export const NetworkContextName = 'NETWORK' export const NetworkContextName = 'NETWORK'
export const IS_IN_IFRAME = window.parent !== window
// 30 minutes, denominated in seconds // 30 minutes, denominated in seconds
export const DEFAULT_DEADLINE_FROM_NOW = 60 * 30 export const DEFAULT_DEADLINE_FROM_NOW = 60 * 30
export const L2_DEADLINE_FROM_NOW = 60 * 5 export const L2_DEADLINE_FROM_NOW = 60 * 5
......
import { Web3Provider } from '@ethersproject/providers' import { Web3Provider } from '@ethersproject/providers'
import { useSafeAppConnection } from '@gnosis.pm/safe-apps-web3-react' import { useWeb3React } from '@web3-react/core'
import { useWeb3React as useWeb3ReactCore } from '@web3-react/core'
import { Web3ReactContextInterface } from '@web3-react/core/dist/types' import { Web3ReactContextInterface } from '@web3-react/core/dist/types'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { gnosisSafe, injected } from '../connectors' import { gnosisSafe, injected } from '../connectors'
import { NetworkContextName } from '../constants/misc' import { IS_IN_IFRAME, NetworkContextName } from '../constants/misc'
export function useActiveWeb3React(): Web3ReactContextInterface<Web3Provider> { export function useActiveWeb3React(): Web3ReactContextInterface<Web3Provider> {
const context = useWeb3ReactCore<Web3Provider>() const context = useWeb3React<Web3Provider>()
const contextNetwork = useWeb3ReactCore<Web3Provider>(NetworkContextName) const contextNetwork = useWeb3React<Web3Provider>(NetworkContextName)
return context.active ? context : contextNetwork return context.active ? context : contextNetwork
} }
export function useEagerConnect() { export function useEagerConnect() {
const { activate, active } = useWeb3ReactCore() // specifically using useWeb3ReactCore because of what this hook does const { activate, active } = useWeb3React()
const [tried, setTried] = useState(false) const [tried, setTried] = useState(false)
const triedToConnectToSafe = useSafeAppConnection(gnosisSafe) // gnosisSafe.isSafeApp() races a timeout against postMessage, so it delays pageload if we are not in a safe app;
// if we are not embedded in an iframe, it is not worth checking
const [triedSafe, setTriedSafe] = useState(!IS_IN_IFRAME)
// first, try connecting to a gnosis safe
useEffect(() => { useEffect(() => {
if (triedToConnectToSafe && !active) { if (!triedSafe) {
gnosisSafe.isSafeApp().then((loadedInSafe) => {
if (loadedInSafe) {
activate(gnosisSafe, undefined, true).catch(() => {
setTriedSafe(true)
})
} else {
setTriedSafe(true)
}
})
}
}, [activate, setTriedSafe]) // intentionally only running on mount
// then, if that fails, try connecting to an injected connector
useEffect(() => {
if (!active && triedSafe) {
injected.isAuthorized().then((isAuthorized) => { injected.isAuthorized().then((isAuthorized) => {
if (isAuthorized) { if (isAuthorized) {
activate(injected, undefined, true).catch(() => { activate(injected, undefined, true).catch(() => {
...@@ -37,14 +54,14 @@ export function useEagerConnect() { ...@@ -37,14 +54,14 @@ export function useEagerConnect() {
} }
}) })
} }
}, [activate, active, triedToConnectToSafe]) // intentionally only running on mount (make sure it's only mounted once :)) }, [activate, active, triedSafe])
// if the connection worked, wait until we get confirmation of that to flip the flag // wait until we get confirmation of a connection to flip the flag
useEffect(() => { useEffect(() => {
if (active && triedToConnectToSafe) { if (active) {
setTried(true) setTried(true)
} }
}, [active, triedToConnectToSafe]) }, [active])
return tried return tried
} }
...@@ -54,7 +71,7 @@ export function useEagerConnect() { ...@@ -54,7 +71,7 @@ export function useEagerConnect() {
* and out after checking what network theyre on * and out after checking what network theyre on
*/ */
export function useInactiveListener(suppress = false) { export function useInactiveListener(suppress = false) {
const { active, error, activate } = useWeb3ReactCore() // specifically using useWeb3React because of what this hook does const { active, error, activate } = useWeb3React()
useEffect(() => { useEffect(() => {
const { ethereum } = window const { ethereum } = window
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment