1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

refactor wallet components

This commit is contained in:
Matthias Kretschmann 2023-01-18 17:50:56 +00:00
parent 9a4de0cab9
commit 759d38ca21
Signed by: m
GPG Key ID: 606EEEF3C479A91F
11 changed files with 160 additions and 447 deletions

View File

@ -49,4 +49,5 @@ export interface MarketMetadataProviderValue {
siteContent: SiteContent siteContent: SiteContent
appConfig: AppConfig appConfig: AppConfig
getOpcFeeForToken: (tokenAddress: string, chainId: number) => string getOpcFeeForToken: (tokenAddress: string, chainId: number) => string
approvedBaseTokens: TokenInfo[]
} }

View File

@ -13,8 +13,13 @@ import { opcQuery } from './_queries'
import { MarketMetadataProviderValue, OpcFee } from './_types' import { MarketMetadataProviderValue, OpcFee } from './_types'
import siteContent from '../../../content/site.json' import siteContent from '../../../content/site.json'
import appConfig from '../../../app.config' import appConfig from '../../../app.config'
import { fetchData, getQueryContext } from '@utils/subgraph' import {
fetchData,
getQueryContext,
getOpcsApprovedTokens
} from '@utils/subgraph'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import { useNetwork, useConnect } from 'wagmi'
const MarketMetadataContext = createContext({} as MarketMetadataProviderValue) const MarketMetadataContext = createContext({} as MarketMetadataProviderValue)
@ -23,7 +28,11 @@ function MarketMetadataProvider({
}: { }: {
children: ReactNode children: ReactNode
}): ReactElement { }): ReactElement {
const { isLoading } = useConnect()
const { chain } = useNetwork()
const [opcFees, setOpcFees] = useState<OpcFee[]>() const [opcFees, setOpcFees] = useState<OpcFee[]>()
const [approvedBaseTokens, setApprovedBaseTokens] = useState<TokenInfo[]>()
useEffect(() => { useEffect(() => {
async function getOpcData() { async function getOpcData() {
@ -64,6 +73,25 @@ function MarketMetadataProvider({
}, },
[opcFees] [opcFees]
) )
// -----------------------------------
// Get and set approved base tokens list
// -----------------------------------
const getApprovedBaseTokens = useCallback(async (chainId: number) => {
try {
const approvedTokensList = await getOpcsApprovedTokens(chainId)
setApprovedBaseTokens(approvedTokensList)
LoggerInstance.log('[web3] Approved baseTokens', approvedTokensList)
} catch (error) {
LoggerInstance.error('[web3] Error: ', error.message)
}
}, [])
useEffect(() => {
if (isLoading) return
getApprovedBaseTokens(chain?.id || 1)
}, [chain?.id, getApprovedBaseTokens, isLoading])
return ( return (
<MarketMetadataContext.Provider <MarketMetadataContext.Provider
value={ value={

View File

@ -7,44 +7,15 @@ import React, {
ReactNode, ReactNode,
useCallback useCallback
} from 'react' } from 'react'
import Web3 from 'web3'
// import Web3Modal, { getProviderInfo, IProviderInfo } from 'web3modal'
// import { infuraProjectId as infuraId } from '../../app.config'
// import WalletConnectProvider from '@walletconnect/web3-provider'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
// import { isBrowser } from '@utils/index'
import { getEnsProfile } from '@utils/ens'
import useNetworkMetadata, {
getNetworkDataById,
getNetworkDisplayName,
getNetworkType,
NetworkType
} from '../@hooks/useNetworkMetadata'
import { useMarketMetadata } from './MarketMetadata' import { useMarketMetadata } from './MarketMetadata'
import { useNetwork, useAccount, useProvider } from 'wagmi'
import { utils } from 'ethers'
import { getTokenBalance } from '@utils/web3' import { getTokenBalance } from '@utils/web3'
import { getOpcsApprovedTokens } from '@utils/subgraph' import useNetworkMetadata from '@hooks/useNetworkMetadata'
interface Web3ProviderValue { interface Web3ProviderValue {
web3: Web3
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// web3Provider: any
// web3Modal: Web3Modal
// web3ProviderInfo: IProviderInfo
accountId: string
accountEns: string
accountEnsAvatar: string
balance: UserBalance balance: UserBalance
networkId: number
chainId: number
networkDisplayName: string
networkData: EthereumListsChain
block: number
isTestnet: boolean
web3Loading: boolean
isSupportedOceanNetwork: boolean
approvedBaseTokens: TokenInfo[]
// connect: () => Promise<void>
// logout: () => Promise<void>
} }
// const web3ModalTheme = { // const web3ModalTheme = {
@ -55,117 +26,29 @@ interface Web3ProviderValue {
// hover: 'var(--background-highlight)' // hover: 'var(--background-highlight)'
// } // }
// const providerOptions = isBrowser
// ? {
// walletconnect: {
// package: WalletConnectProvider,
// options: {
// infuraId,
// rpc: {
// 137: 'https://polygon-rpc.com',
// 80001: 'https://rpc-mumbai.matic.today'
// }
// }
// }
// }
// : {}
// export const web3ModalOpts = {
// cacheProvider: true,
// providerOptions,
// theme: web3ModalTheme
// }
const refreshInterval = 20000 // 20 sec. const refreshInterval = 20000 // 20 sec.
const Web3Context = createContext({} as Web3ProviderValue) const Web3Context = createContext({} as Web3ProviderValue)
function Web3Provider({ children }: { children: ReactNode }): ReactElement { function Web3Provider({ children }: { children: ReactNode }): ReactElement {
const { networksList } = useNetworkMetadata() const { approvedBaseTokens } = useMarketMetadata()
const { appConfig } = useMarketMetadata() const { networkData } = useNetworkMetadata()
const { chain } = useNetwork()
const { address } = useAccount()
const provider = useProvider()
const [web3, setWeb3] = useState<Web3>()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const [web3Provider, setWeb3Provider] = useState<any>()
// const [web3Modal, setWeb3Modal] = useState<Web3Modal>()
// const [web3ProviderInfo, setWeb3ProviderInfo] = useState<IProviderInfo>()
const [networkId, setNetworkId] = useState<number>()
const [chainId, setChainId] = useState<number>()
const [networkDisplayName, setNetworkDisplayName] = useState<string>()
const [networkData, setNetworkData] = useState<EthereumListsChain>()
const [block, setBlock] = useState<number>()
const [isTestnet, setIsTestnet] = useState<boolean>()
const [accountId, setAccountId] = useState<string>()
const [accountEns, setAccountEns] = useState<string>()
const [accountEnsAvatar, setAccountEnsAvatar] = useState<string>()
const [web3Loading, setWeb3Loading] = useState<boolean>(true)
const [balance, setBalance] = useState<UserBalance>({ const [balance, setBalance] = useState<UserBalance>({
eth: '0' eth: '0'
}) })
const [isSupportedOceanNetwork, setIsSupportedOceanNetwork] = useState(true)
const [approvedBaseTokens, setApprovedBaseTokens] = useState<TokenInfo[]>()
// -----------------------------------
// Helper: connect to web3
// -----------------------------------
// const connect = useCallback(async () => {
// if (!web3Modal) {
// setWeb3Loading(false)
// return
// }
// try {
// setWeb3Loading(true)
// LoggerInstance.log('[web3] Connecting Web3...')
// const provider = await web3Modal?.connect()
// setWeb3Provider(provider)
// const web3 = new Web3(provider)
// setWeb3(web3)
// LoggerInstance.log('[web3] Web3 created.', web3)
// const networkId = await web3.eth.net.getId()
// setNetworkId(networkId)
// LoggerInstance.log('[web3] network id ', networkId)
// const chainId = await web3.eth.getChainId()
// setChainId(chainId)
// LoggerInstance.log('[web3] chain id ', chainId)
// const accountId = (await web3.eth.getAccounts())[0]
// setAccountId(accountId)
// LoggerInstance.log('[web3] account id', accountId)
// } catch (error) {
// LoggerInstance.error('[web3] Error: ', error.message)
// } finally {
// setWeb3Loading(false)
// }
// }, [web3Modal])
// -----------------------------------
// Helper: Get approved base tokens list
// -----------------------------------
const getApprovedBaseTokens = useCallback(async (chainId: number) => {
try {
const approvedTokensList = await getOpcsApprovedTokens(chainId)
setApprovedBaseTokens(approvedTokensList)
LoggerInstance.log('[web3] Approved baseTokens', approvedTokensList)
} catch (error) {
LoggerInstance.error('[web3] Error: ', error.message)
}
}, [])
// ----------------------------------- // -----------------------------------
// Helper: Get user balance // Helper: Get user balance
// ----------------------------------- // -----------------------------------
const getUserBalance = useCallback(async () => { const getUserBalance = useCallback(async () => {
if (!accountId || !networkId || !web3 || !networkData) return if (!address || !chain?.id || !provider) return
try { try {
const userBalance = web3.utils.fromWei( const userBalance = utils.formatEther(await provider.getBalance('latest'))
await web3.eth.getBalance(accountId, 'latest')
)
const key = networkData.nativeCurrency.symbol.toLowerCase() const key = networkData.nativeCurrency.symbol.toLowerCase()
const balance: UserBalance = { [key]: userBalance } const balance: UserBalance = { [key]: userBalance }
@ -174,10 +57,10 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
approvedBaseTokens.map(async (token) => { approvedBaseTokens.map(async (token) => {
const { address, decimals, symbol } = token const { address, decimals, symbol } = token
const tokenBalance = await getTokenBalance( const tokenBalance = await getTokenBalance(
accountId, address,
decimals, decimals,
address, address,
web3 provider
) )
balance[symbol.toLocaleLowerCase()] = tokenBalance balance[symbol.toLocaleLowerCase()] = tokenBalance
}) })
@ -189,87 +72,7 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
} catch (error) { } catch (error) {
LoggerInstance.error('[web3] Error: ', error.message) LoggerInstance.error('[web3] Error: ', error.message)
} }
}, [accountId, approvedBaseTokens, networkId, web3, networkData]) }, [address, approvedBaseTokens, chain?.id, provider])
// -----------------------------------
// Helper: Get user ENS info
// -----------------------------------
const getUserEns = useCallback(async () => {
if (!accountId) return
try {
const profile = await getEnsProfile(accountId)
if (!profile) {
setAccountEns(null)
setAccountEnsAvatar(null)
return
}
setAccountEns(profile.name)
LoggerInstance.log(
`[web3] ENS name found for ${accountId}:`,
profile.name
)
if (profile.avatar) {
setAccountEnsAvatar(profile.avatar)
LoggerInstance.log(
`[web3] ENS avatar found for ${accountId}:`,
profile.avatar
)
} else {
setAccountEnsAvatar(null)
}
} catch (error) {
LoggerInstance.error('[web3] Error: ', error.message)
}
}, [accountId])
// -----------------------------------
// Create initial Web3Modal instance
// -----------------------------------
// useEffect(() => {
// if (web3Modal) {
// setWeb3Loading(false)
// return
// }
// async function init() {
// // note: needs artificial await here so the log message is reached and output
// const web3ModalInstance = await new Web3Modal(web3ModalOpts)
// setWeb3Modal(web3ModalInstance)
// LoggerInstance.log(
// '[web3] Web3Modal instance created.',
// web3ModalInstance
// )
// }
// init()
// }, [connect, web3Modal])
// -----------------------------------
// Reconnect automatically for returning users
// -----------------------------------
// useEffect(() => {
// if (!web3Modal?.cachedProvider) return
// async function connectCached() {
// LoggerInstance.log(
// '[web3] Connecting to cached provider: ',
// web3Modal.cachedProvider
// )
// await connect()
// }
// connectCached()
// }, [connect, web3Modal])
// -----------------------------------
// Get and set approved base tokens list
// -----------------------------------
useEffect(() => {
if (web3Loading) return
getApprovedBaseTokens(chainId || 1)
}, [chainId, getApprovedBaseTokens, web3Loading])
// ----------------------------------- // -----------------------------------
// Get and set user balance // Get and set user balance
@ -285,151 +88,8 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
} }
}, [getUserBalance]) }, [getUserBalance])
// -----------------------------------
// Get and set user ENS info
// -----------------------------------
useEffect(() => {
getUserEns()
}, [getUserEns])
// -----------------------------------
// Get and set network metadata
// -----------------------------------
useEffect(() => {
if (!networkId) return
const networkData = getNetworkDataById(networksList, networkId)
setNetworkData(networkData)
LoggerInstance.log(
networkData
? `[web3] Network metadata found.`
: `[web3] No network metadata found.`,
networkData
)
// Construct network display name
const networkDisplayName = getNetworkDisplayName(networkData)
setNetworkDisplayName(networkDisplayName)
setIsTestnet(getNetworkType(networkData) !== NetworkType.Mainnet)
LoggerInstance.log(
`[web3] Network display name set to: ${networkDisplayName}`
)
}, [networkId, networksList])
// -----------------------------------
// Get and set latest head block
// -----------------------------------
useEffect(() => {
if (!web3) return
async function getBlock() {
const block = await web3.eth.getBlockNumber()
setBlock(block)
LoggerInstance.log('[web3] Head block: ', block)
}
getBlock()
}, [web3, networkId])
// -----------------------------------
// Get and set web3 provider info
// -----------------------------------
// Workaround cause getInjectedProviderName() always returns `MetaMask`
// https://github.com/oceanprotocol/market/issues/332
// useEffect(() => {
// if (!web3Provider) return
// const providerInfo = getProviderInfo(web3Provider)
// setWeb3ProviderInfo(providerInfo)
// }, [web3Provider])
// -----------------------------------
// Logout helper
// -----------------------------------
// async function logout() {
// /* eslint-disable @typescript-eslint/no-explicit-any */
// if ((web3?.currentProvider as any)?.close) {
// await (web3.currentProvider as any).close()
// }
// /* eslint-enable @typescript-eslint/no-explicit-any */
// await web3Modal.clearCachedProvider()
// }
// -----------------------------------
// Get valid Networks and set isSupportedOceanNetwork
// -----------------------------------
useEffect(() => {
if (appConfig.chainIdsSupported.includes(networkId)) {
setIsSupportedOceanNetwork(true)
} else {
setIsSupportedOceanNetwork(false)
}
}, [networkId, appConfig.chainIdsSupported])
// -----------------------------------
// Handle change events
// -----------------------------------
async function handleChainChanged(chainId: string) {
LoggerInstance.log('[web3] Chain changed', chainId)
const networkId = await web3.eth.net.getId()
setChainId(Number(chainId))
setNetworkId(Number(networkId))
}
async function handleNetworkChanged(networkId: string) {
LoggerInstance.log('[web3] Network changed', networkId)
const chainId = await web3.eth.getChainId()
setNetworkId(Number(networkId))
setChainId(Number(chainId))
}
async function handleAccountsChanged(accounts: string[]) {
LoggerInstance.log('[web3] Account changed', accounts[0])
setAccountId(accounts[0])
}
useEffect(() => {
if (!web3Provider || !web3) return
web3Provider.on('chainChanged', handleChainChanged)
web3Provider.on('networkChanged', handleNetworkChanged)
web3Provider.on('accountsChanged', handleAccountsChanged)
return () => {
web3Provider.removeListener('chainChanged', handleChainChanged)
web3Provider.removeListener('networkChanged', handleNetworkChanged)
web3Provider.removeListener('accountsChanged', handleAccountsChanged)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [web3Provider, web3])
return ( return (
<Web3Context.Provider <Web3Context.Provider value={{ balance }}>{children}</Web3Context.Provider>
value={{
web3,
// web3Provider,
// web3Modal,
// web3ProviderInfo,
accountId,
accountEns,
accountEnsAvatar,
balance,
networkId,
chainId,
networkDisplayName,
networkData,
block,
isTestnet,
web3Loading,
isSupportedOceanNetwork,
approvedBaseTokens
// connect,
// logout
}}
>
{children}
</Web3Context.Provider>
) )
} }

View File

@ -1,9 +1,57 @@
import { UseNetworkMetadata } from './types' import { UseNetworkMetadata } from './types'
import networkdata from '../../../content/networks-metadata.json' import networkdata from '../../../content/networks-metadata.json'
import { useEffect, useState } from 'react'
import {
getNetworkDataById,
getNetworkDisplayName,
getNetworkType,
NetworkType
} from './utils'
import { useMarketMetadata } from '@context/MarketMetadata'
import { useNetwork } from 'wagmi'
export default function useNetworkMetadata(): UseNetworkMetadata { export default function useNetworkMetadata(): UseNetworkMetadata {
const { appConfig } = useMarketMetadata()
const { chain } = useNetwork()
const [networkDisplayName, setNetworkDisplayName] = useState<string>()
const [networkData, setNetworkData] = useState<EthereumListsChain>()
const [isTestnet, setIsTestnet] = useState<boolean>()
const [isSupportedOceanNetwork, setIsSupportedOceanNetwork] = useState(true)
const networksList: EthereumListsChain[] = networkdata const networksList: EthereumListsChain[] = networkdata
return { networksList }
// -----------------------------------
// Get and set network metadata
// -----------------------------------
useEffect(() => {
if (!chain?.id) return
const networkData = getNetworkDataById(networksList, chain.id)
setNetworkData(networkData)
// Construct network display name
const networkDisplayName = getNetworkDisplayName(networkData)
setNetworkDisplayName(networkDisplayName)
// Check if network is supported by Ocean Protocol
if (appConfig.chainIdsSupported.includes(chain.id)) {
setIsSupportedOceanNetwork(true)
} else {
setIsSupportedOceanNetwork(false)
}
// Check if network is testnet
setIsTestnet(getNetworkType(networkData) !== NetworkType.Mainnet)
}, [chain?.id, networksList, appConfig.chainIdsSupported])
return {
networksList,
networkDisplayName,
networkData,
isTestnet,
isSupportedOceanNetwork
}
} }
export * from './utils' export * from './utils'

View File

@ -1,3 +1,7 @@
export interface UseNetworkMetadata { export interface UseNetworkMetadata {
networkDisplayName: string
networkData: EthereumListsChain
isTestnet: boolean
isSupportedOceanNetwork: boolean
networksList: EthereumListsChain[] networksList: EthereumListsChain[]
} }

View File

@ -1,17 +1,15 @@
import { getNetworkDisplayName } from '@hooks/useNetworkMetadata' import { getNetworkDisplayName } from '@hooks/useNetworkMetadata'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import Web3 from 'web3'
import { getOceanConfig } from './ocean' import { getOceanConfig } from './ocean'
import { AbiItem } from 'web3-utils/types'
import { import {
EthereumClient, EthereumClient,
modalConnectors, modalConnectors,
walletConnectProvider walletConnectProvider
} from '@web3modal/ethereum' } from '@web3modal/ethereum'
import { configureChains, createClient } from 'wagmi' import { configureChains, createClient, erc20ABI } from 'wagmi'
import { mainnet, polygon, bsc, goerli, polygonMumbai } from 'wagmi/chains' import { mainnet, polygon, bsc, goerli, polygonMumbai } from 'wagmi/chains'
import { ethers, utils } from 'ethers'
export const chains = [mainnet, polygon, bsc, goerli, polygonMumbai] export const chains = [mainnet, polygon, bsc, goerli, polygonMumbai]
@ -42,10 +40,10 @@ export function accountTruncate(account: string): string {
* @param chainId * @param chainId
* @returns Web3 instance * @returns Web3 instance
*/ */
export async function getDummyWeb3(chainId: number): Promise<Web3> { // export async function getDummyWeb3(chainId: number): Promise<Web3> {
const config = getOceanConfig(chainId) // const config = getOceanConfig(chainId)
return new Web3(config.nodeUri) // return new Web3(config.nodeUri)
} // }
export async function addCustomNetwork( export async function addCustomNetwork(
web3Provider: any, web3Provider: any,
@ -143,37 +141,13 @@ export async function getTokenBalance(
accountId: string, accountId: string,
decimals: number, decimals: number,
tokenAddress: string, tokenAddress: string,
web3: Web3 provider: any
): Promise<string> { ): Promise<string> {
const minABI = [
{
constant: true,
inputs: [
{
name: '_owner',
type: 'address'
}
],
name: 'balanceOf',
outputs: [
{
name: 'balance',
type: 'uint256'
}
],
payable: false,
stateMutability: 'view',
type: 'function'
}
] as AbiItem[]
try { try {
const token = new web3.eth.Contract(minABI, tokenAddress, { const token = new ethers.Contract(tokenAddress, erc20ABI, provider)
from: accountId
})
const balance = await token.methods.balanceOf(accountId).call() const balance = await token.methods.balanceOf(accountId).call()
const adjustedDecimalsBalance = `${balance}${'0'.repeat(18 - decimals)}` const adjustedDecimalsBalance = `${balance}${'0'.repeat(18 - decimals)}`
return web3.utils.fromWei(adjustedDecimalsBalance) return utils.formatEther(adjustedDecimalsBalance)
} catch (e) { } catch (e) {
LoggerInstance.error(`ERROR: Failed to get the balance: ${e.message}`) LoggerInstance.error(`ERROR: Failed to get the balance: ${e.message}`)
} }

View File

@ -1,39 +1,45 @@
import React, { FormEvent } from 'react' import React, { FormEvent } from 'react'
import Caret from '@images/caret.svg' import Caret from '@images/caret.svg'
import { accountTruncate } from '@utils/web3' import { accountTruncate } from '@utils/web3'
import Loader from '@shared/atoms/Loader' // import Loader from '@shared/atoms/Loader'
import styles from './Account.module.css' import styles from './Account.module.css'
import { useWeb3 } from '@context/Web3'
import Avatar from '@shared/atoms/Avatar' import Avatar from '@shared/atoms/Avatar'
import { useAccount, useProvider, useEnsName, useEnsAvatar } from 'wagmi'
import { useWeb3Modal } from '@web3modal/react'
// Forward ref for Tippy.js // Forward ref for Tippy.js
// eslint-disable-next-line // eslint-disable-next-line
const Account = React.forwardRef((props, ref: any) => { const Account = React.forwardRef((props, ref: any) => {
const { accountId, accountEns, accountEnsAvatar, web3Modal, connect } = // const provider = useProvider()
useWeb3() const { address } = useAccount()
const { data: accountEns } = useEnsName({ address, chainId: 1 })
const { data: accountEnsAvatar } = useEnsAvatar({ address, chainId: 1 })
const { open } = useWeb3Modal()
async function handleActivation(e: FormEvent<HTMLButtonElement>) { async function handleActivation(e: FormEvent<HTMLButtonElement>) {
// prevent accidentially submitting a form the button might be in // prevent accidentially submitting a form the button might be in
e.preventDefault() e.preventDefault()
await connect() await open()
} }
return !accountId && web3Modal?.cachedProvider ? ( // return
// Improve user experience for cached provider when connecting takes some time // !address && provider ? (
<button className={styles.button} onClick={(e) => e.preventDefault()}> // // Improve user experience for cached provider when connecting takes some time
<Loader /> // <button className={styles.button} onClick={(e) => e.preventDefault()}>
</button> // <Loader />
) : accountId ? ( // </button>
// ) :
return address ? (
<button <button
className={styles.button} className={styles.button}
aria-label="Account" aria-label="Account"
ref={ref} ref={ref}
onClick={(e) => e.preventDefault()} onClick={(e) => e.preventDefault()}
> >
<Avatar accountId={accountId} src={accountEnsAvatar} /> <Avatar accountId={address} src={accountEnsAvatar} />
<span className={styles.address} title={accountId}> <span className={styles.address} title={address}>
{accountTruncate(accountEns || accountId)} {accountTruncate(accountEns || address)}
</span> </span>
<Caret aria-hidden="true" className={styles.caret} /> <Caret aria-hidden="true" className={styles.caret} />
</button> </button>

View File

@ -4,20 +4,21 @@ import { useUserPreferences } from '@context/UserPreferences'
import Button from '@shared/atoms/Button' import Button from '@shared/atoms/Button'
import AddToken from '@shared/AddToken' import AddToken from '@shared/AddToken'
import Conversion from '@shared/Price/Conversion' import Conversion from '@shared/Price/Conversion'
import { useWeb3 } from '@context/Web3'
import { getOceanConfig } from '@utils/ocean' import { getOceanConfig } from '@utils/ocean'
import { useNetwork, useProvider, useDisconnect, useAccount } from 'wagmi'
import styles from './Details.module.css' import styles from './Details.module.css'
import { useWeb3 } from '@context/Web3'
import { useWeb3Modal } from '@web3modal/react'
import useNetworkMetadata from '@hooks/useNetworkMetadata'
export default function Details(): ReactElement { export default function Details(): ReactElement {
const { const { chain } = useNetwork()
web3ProviderInfo, const { connector: activeConnector, isConnected } = useAccount()
web3Modal, const { open: openWeb3Modal } = useWeb3Modal()
connect, const { disconnect } = useDisconnect()
logout, const provider = useProvider()
networkData, const { balance } = useWeb3()
networkId, const { networkData } = useNetworkMetadata()
balance
} = useWeb3()
const { locale } = useUserPreferences() const { locale } = useUserPreferences()
const [mainCurrency, setMainCurrency] = useState<string>() const [mainCurrency, setMainCurrency] = useState<string>()
@ -27,19 +28,19 @@ export default function Details(): ReactElement {
}>() }>()
useEffect(() => { useEffect(() => {
if (!networkId) return if (!chain?.id) return
const symbol = networkData?.nativeCurrency.symbol const symbol = networkData?.nativeCurrency.symbol
setMainCurrency(symbol) setMainCurrency(symbol)
const oceanConfig = getOceanConfig(networkId) const oceanConfig = getOceanConfig(chain.id)
oceanConfig && oceanConfig &&
setOceanTokenMetadata({ setOceanTokenMetadata({
address: oceanConfig.oceanTokenAddress, address: oceanConfig.oceanTokenAddress,
symbol: oceanConfig.oceanTokenSymbol symbol: oceanConfig.oceanTokenSymbol
}) })
}, [networkData, networkId]) }, [networkData, chain?.id])
return ( return (
<div className={styles.details}> <div className={styles.details}>
@ -65,10 +66,10 @@ export default function Details(): ReactElement {
<li className={styles.actions}> <li className={styles.actions}>
<div title="Connected provider" className={styles.walletInfo}> <div title="Connected provider" className={styles.walletInfo}>
<span className={styles.walletLogoWrap}> <span className={styles.walletLogoWrap}>
<img className={styles.walletLogo} src={web3ProviderInfo?.logo} /> {/* <img className={styles.walletLogo} src={activeConnector?.logo} /> */}
{web3ProviderInfo?.name} {activeConnector?.name}
</span> </span>
{web3ProviderInfo?.name === 'MetaMask' && ( {activeConnector?.name === 'MetaMask' && (
<AddToken <AddToken
address={oceanTokenMetadata?.address} address={oceanTokenMetadata?.address}
symbol={oceanTokenMetadata?.symbol} symbol={oceanTokenMetadata?.symbol}
@ -77,21 +78,14 @@ export default function Details(): ReactElement {
)} )}
</div> </div>
<p> <p>
<Button <Button style="text" size="small" onClick={() => openWeb3Modal()}>
style="text"
size="small"
onClick={async () => {
await web3Modal?.clearCachedProvider()
connect()
}}
>
Switch Wallet Switch Wallet
</Button> </Button>
<Button <Button
style="text" style="text"
size="small" size="small"
onClick={() => { onClick={() => {
logout() disconnect()
location.reload() location.reload()
}} }}
> >

View File

@ -2,21 +2,23 @@ import React, { ReactElement } from 'react'
import Status from '@shared/atoms/Status' import Status from '@shared/atoms/Status'
import Badge from '@shared/atoms/Badge' import Badge from '@shared/atoms/Badge'
import Tooltip from '@shared/atoms/Tooltip' import Tooltip from '@shared/atoms/Tooltip'
import { useWeb3 } from '@context/Web3'
import NetworkName from '@shared/NetworkName' import NetworkName from '@shared/NetworkName'
import styles from './Network.module.css' import styles from './Network.module.css'
import { useNetwork } from 'wagmi'
import useNetworkMetadata from '@hooks/useNetworkMetadata'
export default function Network(): ReactElement { export default function Network(): ReactElement {
const { networkId, isTestnet, isSupportedOceanNetwork } = useWeb3() const { chain } = useNetwork()
const { isTestnet, isSupportedOceanNetwork } = useNetworkMetadata()
return networkId ? ( return chain?.id ? (
<div className={styles.network}> <div className={styles.network}>
{!isSupportedOceanNetwork && ( {!isSupportedOceanNetwork && (
<Tooltip content="No Ocean Protocol contracts are deployed to this network."> <Tooltip content="No Ocean Protocol contracts are deployed to this network.">
<Status state="error" className={styles.warning} /> <Status state="error" className={styles.warning} />
</Tooltip> </Tooltip>
)} )}
<NetworkName className={styles.name} networkId={networkId} minimal /> <NetworkName className={styles.name} networkId={chain.id} minimal />
{isTestnet && <Badge label="Test" className={styles.badge} />} {isTestnet && <Badge label="Test" className={styles.badge} />}
</div> </div>
) : null ) : null

View File

@ -4,19 +4,15 @@ import Details from './Details'
import Tooltip from '@shared/atoms/Tooltip' import Tooltip from '@shared/atoms/Tooltip'
import Network from './Network' import Network from './Network'
import styles from './index.module.css' import styles from './index.module.css'
import { useWeb3 } from '@context/Web3' import { useAccount } from 'wagmi'
export default function Wallet(): ReactElement { export default function Wallet(): ReactElement {
const { accountId } = useWeb3() const { address } = useAccount()
return ( return (
<div className={styles.wallet}> <div className={styles.wallet}>
<Network /> <Network />
<Tooltip <Tooltip content={<Details />} trigger="click focus" disabled={!address}>
content={<Details />}
trigger="click focus"
disabled={!accountId}
>
<Account /> <Account />
</Tooltip> </Tooltip>
</div> </div>

View File

@ -19,9 +19,9 @@ function MyApp({ Component, pageProps }: AppProps): ReactElement {
Decimal.set({ rounding: 1 }) Decimal.set({ rounding: 1 })
return ( return (
<> <>
<MarketMetadataProvider> <WagmiConfig client={wagmiClient}>
<Web3Provider> <MarketMetadataProvider>
<WagmiConfig client={wagmiClient}> <Web3Provider>
<UrqlProvider> <UrqlProvider>
<UserPreferencesProvider> <UserPreferencesProvider>
<PricesProvider> <PricesProvider>
@ -33,9 +33,9 @@ function MyApp({ Component, pageProps }: AppProps): ReactElement {
</PricesProvider> </PricesProvider>
</UserPreferencesProvider> </UserPreferencesProvider>
</UrqlProvider> </UrqlProvider>
</WagmiConfig> </Web3Provider>
</Web3Provider> </MarketMetadataProvider>
</MarketMetadataProvider> </WagmiConfig>
<Web3Modal <Web3Modal
projectId={process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID} projectId={process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID}