Skip to content

Commit

Permalink
Merge pull request #157 from lidofinance/develop
Browse files Browse the repository at this point in the history
Develop to main
  • Loading branch information
itaven authored Jun 28, 2023
2 parents c1a0f12 + 39e1e24 commit ba9eb54
Show file tree
Hide file tree
Showing 35 changed files with 1,427 additions and 376 deletions.
6 changes: 4 additions & 2 deletions .env → .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ INFURA_API_KEY=
ALCHEMY_API_KEY=

# supported networks for connecting wallet
SUPPORTED_CHAINS=1,4,5
SUPPORTED_CHAINS=1,5

# this chain uses when a wallet is not connected
DEFAULT_CHAIN=4
DEFAULT_CHAIN=5

# comma-separated trusted hosts for Content Security Policy
CSP_TRUSTED_HOSTS=
Expand All @@ -26,3 +26,5 @@ SUBGRAPH_RINKEBY=
SUBGRAPH_GOERLI=https://api.thegraph.com/subgraphs/name/lidofinance/lido-testnet
SUBGRAPH_KOVAN=
SUBGRAPH_KINTSUGI=

WALLETCONNECT_PROJECT_ID=
2 changes: 1 addition & 1 deletion .eslintrc.js → .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const tsRules = {

// Import
const importRules = {
'import/no-unresolved': ['error', { ignore: ['.svg'] }],
'import/no-unresolved': 'off',
'import/no-dynamic-require': 'error',
'import/no-self-import': 'error',
'import/no-useless-path-segments': ['error', { noUselessIndex: true }],
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
TARGET_REPO: "lidofinance/infra-mainnet"
TAG: "${{ github.event.release.tag_name }}"
TARGET_WORKFLOW: "build_mainnet_easytrack_ui.yaml"
TARGET_WORKFLOW: "build_critical_easytrack_ui.yaml"
2 changes: 1 addition & 1 deletion .github/workflows/ci-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ jobs:
APP_ID: ${{ secrets.APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
TARGET_REPO: "lidofinance/infra-mainnet"
TARGET_WORKFLOW: "deploy_staging_mainnet_easytrack_ui.yaml"
TARGET_WORKFLOW: "deploy_staging_critical_easytrack_ui.yaml"
TARGET: "main"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

# generated
/generated
tsconfig.tsbuildinfo

# next.js
/.next/
Expand Down
File renamed without changes.
21 changes: 21 additions & 0 deletions modules/appProviderWeb3/appProviderWeb3.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { backendRPC } from 'modules/blockChain/utils/getBackendRpcUrl'
import { useConfig } from 'modules/config/hooks/useConfig'
import getConfig from 'next/config'
import { ProviderWeb3 } from 'reef-knot/web3-react'

const { publicRuntimeConfig } = getConfig()

export function AppProviderWeb3({ children }: { children: React.ReactNode }) {
const { supportedChainIds, defaultChain } = useConfig()

return (
<ProviderWeb3
defaultChainId={defaultChain}
supportedChainIds={supportedChainIds}
rpc={backendRPC}
walletconnectProjectId={publicRuntimeConfig.walletconnectProjectId}
>
{children}
</ProviderWeb3>
)
}
1 change: 1 addition & 0 deletions modules/appProviderWeb3/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './appProviderWeb3'
67 changes: 67 additions & 0 deletions modules/appWagmiConfig/appWagmiConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { FC } from 'react'
import { WagmiConfig, configureChains, createClient } from 'wagmi'
import * as wagmiChains from 'wagmi/chains'
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
import { getConnectors } from 'reef-knot/core-react'
import getConfig from 'next/config'
import { CHAINS } from '@lido-sdk/constants'
import { getBackendRpcUrl } from 'modules/blockChain/utils/getBackendRpcUrl'

const { publicRuntimeConfig } = getConfig()

let supportedChainIds: number[] = []
if (publicRuntimeConfig.supportedChains != null) {
supportedChainIds = publicRuntimeConfig.supportedChains
.split(',')
.map((chainId: string) => parseInt(chainId))
.filter((chainId: number) => !Number.isNaN(chainId))
} else if (publicRuntimeConfig.defaultChain != null) {
supportedChainIds = [parseInt(publicRuntimeConfig.defaultChain)]
}

const wagmiChainsArray = Object.values(wagmiChains)
const supportedChains = wagmiChainsArray.filter(
chain =>
// Temporary wagmi fix, need to hardcode it to not affect non-wagmi wallets
supportedChainIds.includes(chain.id) || chain.id === 80001,
)
const defaultChain = wagmiChainsArray.find(
chain => chain.id === parseInt(publicRuntimeConfig.defaultChain),
)

const backendRPC = supportedChainIds.reduce<Record<number, string>>(
(res, curr) => ({ ...res, [curr]: getBackendRpcUrl(curr) }),
{
// Required by reef-knot
[CHAINS.Mainnet]: getBackendRpcUrl(CHAINS.Mainnet),
},
)

const { chains, provider, webSocketProvider } = configureChains(
supportedChains,
[
jsonRpcProvider({
rpc: chain => ({
http: backendRPC[chain.id],
}),
}),
],
)

const connectors = getConnectors({
chains,
defaultChain,
rpc: backendRPC,
walletconnectProjectId: publicRuntimeConfig.walletconnectProjectId,
})

const client = createClient({
connectors,
autoConnect: true,
provider,
webSocketProvider,
})

export const AppWagmiConfig: FC = ({ children }) => {
return <WagmiConfig client={client}>{children}</WagmiConfig>
}
1 change: 1 addition & 0 deletions modules/appWagmiConfig/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './appWagmiConfig'
2 changes: 1 addition & 1 deletion modules/blockChain/hooks/useErrorMessage.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useSupportedChains, useConnectorError } from '@reef-knot/web3-react'
import { useSupportedChains, useConnectorError } from 'reef-knot/web3-react'
import { CHAINS } from '@lido-sdk/constants'
import { useMemo } from 'react'

Expand Down
28 changes: 28 additions & 0 deletions modules/blockChain/hooks/useIsContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useEthereumSWR } from '@lido-sdk/react'

export const useIsContract = (
account?: string | null,
): { loading: boolean; isContract: boolean } => {
// eth_getCode returns hex string of bytecode at address
// for accounts it's "0x"
// for contract it's potentially very long hex (can't be safely&quickly parsed)
const result = useEthereumSWR({
shouldFetch: !!account,
method: 'getCode',
params: [account, 'latest'],
config: {
// this is very stable request
refreshWhenHidden: false,
revalidateOnFocus: false,
revalidateIfStale: false,
revalidateOnMount: true,
revalidateOnReconnect: false,
refreshInterval: 0,
},
})

return {
loading: result.loading,
isContract: result.data ? result.data !== '0x' : false,
}
}
8 changes: 8 additions & 0 deletions modules/blockChain/hooks/useIsMultisig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useWeb3 } from 'reef-knot/web3-react'
import { useIsContract } from './useIsContract'

export const useIsMultisig = () => {
const { account } = useWeb3()
const { isContract, loading } = useIsContract(account ?? undefined)
return [isContract, loading]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@ import { useCallback } from 'react'
import { useWeb3 } from 'modules/blockChain/hooks/useWeb3'
import { PopulatedTransaction } from '@ethersproject/contracts'
import { sendTransactionGnosisWorkaround } from '../utils/sendTransactionGnosisWorkaround'
import { useIsMultisig } from './useIsMultisig'

export function useSendTransactionGnosisWorkaround() {
const { library } = useWeb3()
// TODO: track loading state of this swr in the ui on yes/no/enact button
const [isMultisig] = useIsMultisig()

return useCallback(
(tx: PopulatedTransaction) =>
sendTransactionGnosisWorkaround(library.getSigner(), tx),
[library],
sendTransactionGnosisWorkaround(library?.getSigner(), tx, isMultisig),
[library, isMultisig],
)
}
2 changes: 1 addition & 1 deletion modules/blockChain/hooks/useTransactionSender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function useTransactionSender(
if (!resultTx) return
const link =
resultTx.type === 'safe'
? getGnosisSafeLink(chainId, `${walletAddress}/transaction`)
? getGnosisSafeLink(chainId, `${walletAddress}`)
: getEtherscanLink(chainId, resultTx.tx.hash, 'tx')
openWindow(link)
}, [chainId, resultTx, walletAddress])
Expand Down
5 changes: 4 additions & 1 deletion modules/blockChain/hooks/useWeb3.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useMemo } from 'react'
import { useWeb3 as useWeb3ReefKnot } from '@reef-knot/web3-react'
import { useWeb3 as useWeb3ReefKnot } from 'reef-knot/web3-react'
import { useConfig } from 'modules/config/hooks/useConfig'
import { parseChainId } from '../chains'
import { useSDK } from '@lido-sdk/react'

export function useWeb3() {
const web3 = useWeb3ReefKnot()
const { providerWeb3 } = useSDK()
const { defaultChain } = useConfig()
const { chainId } = web3

Expand All @@ -18,5 +20,6 @@ export function useWeb3() {
isWalletConnected: web3.active,
walletAddress: web3.account,
chainId: currentChain,
library: providerWeb3,
}
}
5 changes: 0 additions & 5 deletions modules/blockChain/utils/checkConnectedToSafe.ts

This file was deleted.

7 changes: 5 additions & 2 deletions modules/blockChain/utils/createContractHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useGlobalMemo } from 'modules/shared/hooks/useGlobalMemo'
import { useContractSwr } from '../hooks/useContractSwr'

import type { Signer, providers } from 'ethers'
import type { JsonRpcSigner } from '@ethersproject/providers'
import { getStaticRpcBatchProvider } from '@lido-sdk/providers'
import { getBackendRpcUrl } from 'modules/blockChain/utils/getBackendRpcUrl'
import { getChainName } from 'modules/blockChain/chains'
Expand All @@ -15,7 +16,7 @@ import {
AsyncMethodReturns,
} from 'modules/types/filter-async-methods'

type Library = Signer | providers.Provider
type Library = JsonRpcSigner | Signer | providers.Provider

interface Factory {
name: string
Expand Down Expand Up @@ -79,11 +80,13 @@ export function createContractHelpers<F extends Factory>({
() =>
connect({
chainId,
library: library?.getSigner(),
// TODO: find a way to remove ! here
library: library?.getSigner()!,
}),
[
'contract-web3-',
active ? 'active' : 'inactive',
library ? 'with-signer' : 'no-signer',
chainId,
address[chainId],
account,
Expand Down
10 changes: 4 additions & 6 deletions modules/blockChain/utils/getBackendRpcUrl.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { CHAINS } from '@lido-sdk/constants'
import { parseChainId } from '../chains'
import getConfig from 'next/config'

const { serverRuntimeConfig } = getConfig()
const { basePath } = serverRuntimeConfig

export const getBackendRpcUrl = (chainId: CHAINS) =>
`${basePath ?? ''}/api/rpc?chainId=${parseChainId(chainId)}`
export const getBackendRpcUrl = (chainId: CHAINS) => {
const BASE_URL = typeof window === 'undefined' ? '' : window.location.origin
return `${BASE_URL}/api/rpc?chainId=${parseChainId(chainId)}`
}

export const backendRPC = {
[CHAINS.Mainnet]: getBackendRpcUrl(CHAINS.Mainnet),
Expand Down
6 changes: 5 additions & 1 deletion modules/blockChain/utils/getGnosisSafeLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ const PREFIXES = {
} as const

export const getGnosisSafeLink = (chainId: CHAINS, address: string) =>
`https://app.safe.global/${get(PREFIXES, chainId, 'eth')}:${address}`
`https://app.safe.global/transactions/history?safe=${get(
PREFIXES,
chainId,
'?',
)}:${address}`
10 changes: 10 additions & 0 deletions modules/blockChain/utils/isContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { type Provider } from '@ethersproject/abstract-provider'

export const isContract = async (
address: string,
provider: Provider,
): Promise<boolean> => {
const code = await provider.getCode(address)
if (code != '0x') return true
return false
}
12 changes: 7 additions & 5 deletions modules/blockChain/utils/sendTransactionGnosisWorkaround.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { Signer } from '@ethersproject/abstract-signer'
import { PopulatedTransaction } from '@ethersproject/contracts'
import { ToastInfo, toast } from '@lidofinance/lido-ui'
import { ResultTx } from '../types'
import { checkConnectedToSafe } from './checkConnectedToSafe'
import type { Signer } from '@ethersproject/abstract-signer'
import type { JsonRpcSigner } from '@ethersproject/providers'

// This workaround exists because gnosis safe return making regular `sendTransaction` endlessly waiting
// https://github.com/ethers-io/ethers.js/blob/7274cd06cf3f6f31c6df3fd6636706d8536b7ee2/packages/providers/src.ts/json-rpc-provider.ts#L226-L246

export async function sendTransactionGnosisWorkaround(
signer: Signer,
signer: Signer | JsonRpcSigner | undefined,
transaction: PopulatedTransaction,
isMultisig: boolean,
): Promise<ResultTx> {
const isGnosisSafe = checkConnectedToSafe(signer.provider as any)
if (!signer) throw Error('signer is required')

const pendingToastId = ToastInfo(`Confirm transaction in your wallet`, {})

if (isGnosisSafe) {
if (isMultisig) {
const hash: string = await (signer as any).sendUncheckedTransaction(
transaction,
)
Expand Down
9 changes: 7 additions & 2 deletions modules/modal/ModalProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ function ModalProviderRaw({ children }: Props) {
)

const closeModal = useCallback(() => {
stateRef.current = null
update()
// setTimeout helps to get rid of this error:
// "Can't perform a react state update on an unmounted component"
// after WalletConnect connection
setTimeout(() => {
stateRef.current = null
update()
}, 0)
}, [update])

const context = useMemo(
Expand Down
Loading

0 comments on commit ba9eb54

Please sign in to comment.