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:
parent
9a4de0cab9
commit
759d38ca21
@ -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[]
|
||||||
}
|
}
|
||||||
|
@ -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={
|
||||||
|
@ -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>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
export interface UseNetworkMetadata {
|
export interface UseNetworkMetadata {
|
||||||
|
networkDisplayName: string
|
||||||
|
networkData: EthereumListsChain
|
||||||
|
isTestnet: boolean
|
||||||
|
isSupportedOceanNetwork: boolean
|
||||||
networksList: EthereumListsChain[]
|
networksList: EthereumListsChain[]
|
||||||
}
|
}
|
||||||
|
@ -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}`)
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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}
|
||||||
|
Loading…
Reference in New Issue
Block a user