Skip to content

Commit

Permalink
Upgrade rainbowkit (#1062)
Browse files Browse the repository at this point in the history
* Upgrade rainbowkit

* fix unsupported network issues

* adjust wallets order

* support nestwallet

* upgrade rainbowkit

* add back package
  • Loading branch information
zzq0826 authored Jun 4, 2024
1 parent 31e6ba6 commit da01927
Show file tree
Hide file tree
Showing 20 changed files with 1,090 additions and 1,025 deletions.
10 changes: 10 additions & 0 deletions craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ module.exports = {
fullySpecified: false,
},
})

webpackConfig.module.rules.push({
test: /\.m?js$/,
include: /node_modules/,
type: "javascript/auto",
resolve: {
fullySpecified: false,
},
})

if (env === "production" && process.env.CI) {
const sentryPlugin = new SentryWebpackPlugin({
org: "scroll-zkp",
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@
"@mui/icons-material": "^5.8.4",
"@mui/lab": "^5.0.0-alpha.108",
"@mui/material": "^5.11.15",
"@rainbow-me/rainbowkit": "^1.2.0",
"@rainbow-me/rainbowkit": "^2.1.2",
"@sentry/react": "^7.43.0",
"@sentry/tracing": "^7.43.0",
"@tanstack/react-query": "^5.28.9",
"@types/jest": "^27.5.2",
"@types/node": "^20.10.6",
"@types/react": "^18.0.15",
Expand Down Expand Up @@ -75,8 +76,8 @@
"swiper": "^10.1.0",
"swr": "^2.1.3",
"tss-react": "^4.4.1",
"viem": "^1.10.1",
"wagmi": "^1.4.12",
"viem": "2.9.31",
"wagmi": "^2.9.2",
"web-vitals": "^2.1.4",
"zustand": "^4.1.3"
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/WalletToolkit/WalletDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ const WalletDropdown = props => {

return (
<>
{chainId ? (
{walletCurrentAddress ? (
<ButtonBase classes={{ root: classes.button }} sx={sx} onClick={handleClick}>
{truncateAddress(walletCurrentAddress as string)}
<SvgIcon className={cx(classes.endIcon, open && classes.reverseEndIcon)} component={DownTriangleSvg} inheritViewBox></SvgIcon>
Expand Down
4 changes: 2 additions & 2 deletions src/components/WalletToolkit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import WalletDropdown from "./WalletDropdown"
const WalletToolkit = props => {
const { dark } = props
const { isMobile } = useCheckViewport()
const { chainId } = useRainbowContext()
const { walletCurrentAddress } = useRainbowContext()

return (
<Stack direction="row" spacing="0.8rem">
{chainId && !isMobile && <NetworkIndicator dark={dark}></NetworkIndicator>}
{walletCurrentAddress && !isMobile && <NetworkIndicator dark={dark}></NetworkIndicator>}
<WalletDropdown dark={dark}></WalletDropdown>
</Stack>
)
Expand Down
34 changes: 17 additions & 17 deletions src/contexts/PriceFeeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AbiCoder, Transaction, ethers } from "ethers"
import React, { createContext, useContext, useMemo, useState } from "react"
import React, { createContext, useContext, useEffect, useMemo, useState } from "react"
import useStorage from "squirrel-gill"
import { useBlockNumber } from "wagmi"

Expand Down Expand Up @@ -130,21 +130,21 @@ export const PriceFeeProvider = ({ children }) => {
}
}

useBlockNumber({
// enabled: !!(networksAndSigners[CHAIN_ID.L1].signer && networksAndSigners[CHAIN_ID.L2].provider),
onBlock(blockNumber) {
fetchData()
.then(() => {
setErrorMessage("")
})
.catch(error => {
//TODO:
// setGasLimit(null)
// setGasPrice(null)
setErrorMessage(trimErrorMessage(error.message))
})
},
})
const { data: blockNumber } = useBlockNumber({ watch: true })

useEffect(() => {
fetchData()
.then(() => {
setErrorMessage("")
})
.catch(error => {
console.log("error", error)
//TODO:
// setGasLimit(null)
// setGasPrice(null)
setErrorMessage(trimErrorMessage(error.message))
})
}, [blockNumber])

const l1Token = useMemo(
() => tokenList.find(item => item.chainId === CHAIN_ID.L1 && item.symbol === tokenSymbol) ?? ({} as any as Token),
Expand All @@ -162,7 +162,7 @@ export const PriceFeeProvider = ({ children }) => {
const gasPrice = await L1MessageQueueWithGasPriceOracleContract.l2BaseFee()
return (gasPrice * BigInt(120)) / BigInt(100)
} catch (err) {
// console.log(err)
console.log("err", err)
throw new Error("Failed to get gas price")
}
}
Expand Down
142 changes: 25 additions & 117 deletions src/contexts/RainbowProvider/configs.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,37 @@
import { Chain, Wallet } from "@rainbow-me/rainbowkit"
import "@rainbow-me/rainbowkit/styles.css"
import { getDefaultConfig } from "@rainbow-me/rainbowkit"
import {
braveWallet,
bitgetWallet,
coinbaseWallet,
frameWallet,
imTokenWallet,
injectedWallet,
metaMaskWallet,
nestWallet,
okxWallet,
rabbyWallet,
rainbowWallet,
safeWallet,
trustWallet,
walletConnectWallet,
zerionWallet,
} from "@rainbow-me/rainbowkit/wallets"
import { Chain, mainnet, scroll, scrollSepolia, sepolia } from "@wagmi/core/chains"
import { parseUnits } from "ethers"
import produce from "immer"
import { configureChains, mainnet, sepolia } from "wagmi"
import { jsonRpcProvider } from "wagmi/providers/jsonRpc"
import { publicProvider } from "wagmi/providers/public"

import { CHAIN_ID, ETH_SYMBOL, L2_NAME, RPC_URL } from "@/constants"
import { networkType, requireEnv } from "@/utils"
import { RPC_URL } from "@/constants"
import { requireEnv } from "@/utils"

interface WalletConfig {
name: string
wallet: Wallet
visible: boolean
fixedWallet?: boolean
}

const createWalletConfig = (name: string, walletFunction: () => Wallet, condition: boolean, fixedWallet?: boolean): WalletConfig => {
return {
name,
wallet: walletFunction(),
visible: condition,
fixedWallet,
}
}
const projectId = requireEnv("REACT_APP_CONNECT_WALLET_PROJECT_ID")

export const scrollChain: Chain = {
id: CHAIN_ID.L2,
name: L2_NAME,
network: L2_NAME,
iconUrl: "https://scroll.io/logo.png",
iconBackground: "#fff",
nativeCurrency: {
decimals: 18,
name: L2_NAME,
symbol: ETH_SYMBOL,
const wallets = [
{
groupName: "Popular",
wallets: [metaMaskWallet, coinbaseWallet, rabbyWallet, okxWallet, zerionWallet, trustWallet],
},
rpcUrls: {
default: {
http: [RPC_URL.L2],
},
public: {
http: [RPC_URL.L2],
},
{
groupName: "More",
wallets: [bitgetWallet, nestWallet, walletConnectWallet],
},
blockExplorers: {
default: { name: "Scrollscan", url: requireEnv("REACT_APP_EXTERNAL_EXPLORER_URI_L2") },
},
}
]

const sepoliaChain = produce(sepolia, draft => {
draft.rpcUrls.public.http = [RPC_URL.L1 as any]
draft.rpcUrls.default.http = [RPC_URL.L1 as any]
draft.fees = {
// adopt MetaMask params
baseFeeMultiplier: 1,
Expand All @@ -74,7 +42,7 @@ const sepoliaChain = produce(sepolia, draft => {
})

const mainnetChain = produce(mainnet, draft => {
draft.rpcUrls.public.http = [RPC_URL.L1 as any]
draft.rpcUrls.default.http = [RPC_URL.L1 as any]
draft.fees = {
// adopt MetaMask params
baseFeeMultiplier: 1,
Expand All @@ -85,69 +53,9 @@ const mainnetChain = produce(mainnet, draft => {
}
})

const projectId = requireEnv("REACT_APP_CONNECT_WALLET_PROJECT_ID")

const { chains, publicClient } = configureChains(
// ankr
[mainnetChain, sepoliaChain, scrollChain],
[
publicProvider(),
jsonRpcProvider({
rpc: chain => ({ http: chain.rpcUrls.default.http[0] }),
}),
],
)

const walletConfigs: WalletConfig[] = [
createWalletConfig("MetaMask", () => metaMaskWallet({ chains, projectId }), window.ethereum?.isMetaMask === true, true),
createWalletConfig("Coinbase", () => coinbaseWallet({ appName: "Scroll", chains }), window.ethereum?.isCoinbaseWallet === true, true),
createWalletConfig("Brave", () => braveWallet({ chains }), window.ethereum?.isBraveWallet === true),
createWalletConfig("Rainbow", () => rainbowWallet({ chains, projectId }), window.ethereum?.isRainbow === true),
createWalletConfig("Safe", () => safeWallet({ chains }), window.ethereum?.isSafeWallet === true),
createWalletConfig("Frame", () => frameWallet({ chains }), window.ethereum?.isFrame === true),
createWalletConfig("imToken", () => imTokenWallet({ chains, projectId }), window.ethereum?.isImToken === true),
createWalletConfig("Okx Wallet", () => okxWallet({ chains, projectId }), window.okxwallet?.isOKExWallet || window.okxwallet?.isOkxWallet === true),
createWalletConfig("Rabby", () => rabbyWallet({ chains }), window.ethereum?.isRabby && !window.ethereum?.isMetaMask === true),
// Add any additional wallets here
]

const sortWallets = (a, b) => {
if (a.visible === b.visible) return 0
if (a.visible || a.fixedWallet) return -1
return 1
}

const activeWallets: Wallet[] = walletConfigs
.filter(wallet => wallet.visible || wallet.fixedWallet)
.sort(sortWallets)
.map(wallet => wallet.wallet)

const Wallets = [
// TODO: rainbowkit/injectedWallet.ts "Browser Wallet" and "injectedWallet.svg" -> need to detect automaticlly
injectedWallet({ chains }),
...activeWallets,
walletConnectWallet({
projectId,
chains,
options: {
metadata: {
name: "Scroll",
description: `Get started with our ${networkType} now.`,
url: "https://scroll.io/",
icons: ["https://scroll.io/logo_walletconnect.png"],
},
qrModalOptions: {
explorerRecommendedWalletIds: [
// metamask
"c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96",
// trust
"4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0",
// uniswap
"c03dfee351b6fcc421b4494ea33b9d4b92a984f87aa76d1663bb28705e95034a",
],
},
},
} as any),
]

export { Wallets, chains, publicClient }
export const config = getDefaultConfig({
wallets,
appName: "Scroll",
projectId,
chains: [mainnetChain, sepoliaChain as unknown as Chain, scroll, scrollSepolia],
})
38 changes: 14 additions & 24 deletions src/contexts/RainbowProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { RainbowKitProvider, connectorsForWallets, useConnectModal } from "@rainbow-me/rainbowkit"
import { RainbowKitProvider, useConnectModal } from "@rainbow-me/rainbowkit"
import "@rainbow-me/rainbowkit/styles.css"
import { type WalletClient } from "@wagmi/core"
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
import { BrowserProvider, ethers } from "ethers"
import { createContext, useCallback, useContext, useMemo } from "react"
import { WagmiConfig, createConfig, useAccount, useDisconnect, useNetwork, useWalletClient } from "wagmi"
import { WagmiProvider, useAccount, useDisconnect, useWalletClient } from "wagmi"

import { Wallets, chains, publicClient } from "./configs"
import { config } from "./configs"

type RainbowContextProps = {
provider: ethers.BrowserProvider | null
Expand All @@ -19,20 +19,9 @@ type RainbowContextProps = {

const RainbowContext = createContext<RainbowContextProps | undefined>(undefined)

const connectors = connectorsForWallets([
{
groupName: "Popular",
wallets: Wallets,
},
])
const queryClient = new QueryClient()

const wagmiConfig = createConfig({
autoConnect: true,
connectors,
publicClient,
})

function walletClientToSigner(walletClient: WalletClient) {
function walletClientToSigner(walletClient) {
const { chain, transport } = walletClient
const network = {
chainId: chain.id,
Expand All @@ -45,11 +34,13 @@ function walletClientToSigner(walletClient: WalletClient) {

const RainbowProvider = props => {
return (
<WagmiConfig config={wagmiConfig}>
<RainbowKitProvider modalSize="compact" chains={chains}>
<Web3ContextProvider>{props.children}</Web3ContextProvider>
</RainbowKitProvider>
</WagmiConfig>
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider locale="en" modalSize="compact">
<Web3ContextProvider>{props.children}</Web3ContextProvider>
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
)
}

Expand All @@ -59,8 +50,7 @@ const Web3ContextProvider = props => {
const { openConnectModal } = useConnectModal()
const { disconnect } = useDisconnect()

const { connector: activeConnector, address, isConnected } = useAccount()
const { chain } = useNetwork()
const { connector: activeConnector, address, isConnected, chain } = useAccount()

const provider = useMemo(() => {
if (walletClient && chain && chain.id === walletClient.chain.id) return walletClientToSigner(walletClient)
Expand Down
5 changes: 3 additions & 2 deletions src/hooks/useBlockNumbers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@ import useSWR from "swr"

import { CHAIN_ID } from "@/constants"
import { BLOCK_NUMBERS } from "@/constants/storageKey"
import { config } from "@/contexts/RainbowProvider/configs"

const useBlockNumbers = () => {
const [blockNumbers, setBlockNumbers] = useStorage(localStorage, BLOCK_NUMBERS, [-1, -1])
const [isL1Available, setIsL1Available] = useState(true)
const [isL2Available, setIsL2Available] = useState(true)

const fetchBlockNumber = async () => {
const fetchL1BlockNumber = getPublicClient({ chainId: CHAIN_ID.L1 }).getBlock({ blockTag: "finalized" })
const fetchL2BlockNumber = getPublicClient({ chainId: CHAIN_ID.L2 }).getBlock({ blockTag: "latest" })
const fetchL1BlockNumber = getPublicClient(config, { chainId: CHAIN_ID.L1 })!.getBlock({ blockTag: "finalized" })
const fetchL2BlockNumber = getPublicClient(config, { chainId: CHAIN_ID.L2 })!.getBlock({ blockTag: "latest" })
const blockNumbers = await Promise.allSettled([fetchL1BlockNumber, fetchL2BlockNumber])
return blockNumbers.map(item => (item.status === "fulfilled" ? Number(item.value.number) : item.reason))
}
Expand Down
1 change: 1 addition & 0 deletions src/hooks/useEstimateSendTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@ export function useEstimateSendTransaction(props) {

return {
estimateSend,
instance,
}
}
Loading

0 comments on commit da01927

Please sign in to comment.