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

standalone modal version

This commit is contained in:
Matthias Kretschmann 2023-02-20 09:34:45 +00:00
parent f8726c633c
commit 3b3fc2092d
Signed by: m
GPG Key ID: 606EEEF3C479A91F
4 changed files with 107 additions and 90 deletions

14
package-lock.json generated
View File

@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"@coingecko/cryptoformat": "^0.5.4", "@coingecko/cryptoformat": "^0.5.4",
"@loadable/component": "^5.15.2", "@loadable/component": "^5.15.2",
"@metamask/detect-provider": "^2.0.0",
"@oceanprotocol/art": "^3.2.0", "@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^2.6.0", "@oceanprotocol/lib": "^2.6.0",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
@ -4267,6 +4268,14 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/@metamask/detect-provider": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@metamask/detect-provider/-/detect-provider-2.0.0.tgz",
"integrity": "sha512-sFpN+TX13E9fdBDh9lvQeZdJn4qYoRb/6QF2oZZK/Pn559IhCFacPMU1rMuqyXoFQF3JSJfii2l98B87QDPeCQ==",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@motionone/animation": { "node_modules/@motionone/animation": {
"version": "10.15.1", "version": "10.15.1",
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz",
@ -49988,6 +49997,11 @@
"integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==",
"dev": true "dev": true
}, },
"@metamask/detect-provider": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@metamask/detect-provider/-/detect-provider-2.0.0.tgz",
"integrity": "sha512-sFpN+TX13E9fdBDh9lvQeZdJn4qYoRb/6QF2oZZK/Pn559IhCFacPMU1rMuqyXoFQF3JSJfii2l98B87QDPeCQ=="
},
"@motionone/animation": { "@motionone/animation": {
"version": "10.15.1", "version": "10.15.1",
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz",

View File

@ -25,6 +25,7 @@
"dependencies": { "dependencies": {
"@coingecko/cryptoformat": "^0.5.4", "@coingecko/cryptoformat": "^0.5.4",
"@loadable/component": "^5.15.2", "@loadable/component": "^5.15.2",
"@metamask/detect-provider": "^2.0.0",
"@oceanprotocol/art": "^3.2.0", "@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^2.6.0", "@oceanprotocol/lib": "^2.6.0",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",

View File

@ -9,10 +9,9 @@ import React, {
} from 'react' } from 'react'
import Web3 from 'web3' import Web3 from 'web3'
import { Web3Modal } from '@web3modal/standalone' import { Web3Modal } from '@web3modal/standalone'
import { infuraProjectId as infuraId } from '../../app.config'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import { isBrowser } from '@utils/index'
import SignClient from '@walletconnect/sign-client' import SignClient from '@walletconnect/sign-client'
import detectEthereumProvider from '@metamask/detect-provider'
import { getEnsProfile } from '@utils/ens' import { getEnsProfile } from '@utils/ens'
import useNetworkMetadata, { import useNetworkMetadata, {
getNetworkDataById, getNetworkDataById,
@ -28,7 +27,6 @@ interface Web3ProviderValue {
web3: Web3 web3: Web3
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
web3Provider: any web3Provider: any
web3Modal: Web3Modal
// web3ProviderInfo: IProviderInfo // web3ProviderInfo: IProviderInfo
accountId: string accountId: string
accountEns: string accountEns: string
@ -43,18 +41,11 @@ interface Web3ProviderValue {
web3Loading: boolean web3Loading: boolean
isSupportedOceanNetwork: boolean isSupportedOceanNetwork: boolean
approvedBaseTokens: TokenInfo[] approvedBaseTokens: TokenInfo[]
connect: () => Promise<void> connectWeb3Modal: () => Promise<void>
connectMetaMask: () => Promise<void>
logout: () => Promise<void> logout: () => Promise<void>
} }
// const web3ModalTheme = {
// background: 'var(--background-body)',
// main: 'var(--font-color-heading)',
// secondary: 'var(--brand-grey-light)',
// border: 'var(--border-color)',
// hover: 'var(--background-highlight)'
// }
// const providerOptions = isBrowser // const providerOptions = isBrowser
// ? { // ? {
// walletconnect: { // walletconnect: {
@ -81,8 +72,6 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
const [web3, setWeb3] = useState<Web3>() const [web3, setWeb3] = useState<Web3>()
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const [web3Provider, setWeb3Provider] = useState<any>() const [web3Provider, setWeb3Provider] = useState<any>()
const [signClient, setSignClient] = useState<SignClient>()
const [web3Modal, setWeb3Modal] = useState<Web3Modal>()
// const [web3ProviderInfo, setWeb3ProviderInfo] = useState<IProviderInfo>() // const [web3ProviderInfo, setWeb3ProviderInfo] = useState<IProviderInfo>()
const [networkId, setNetworkId] = useState<number>() const [networkId, setNetworkId] = useState<number>()
@ -102,20 +91,42 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
const [approvedBaseTokens, setApprovedBaseTokens] = useState<TokenInfo[]>() const [approvedBaseTokens, setApprovedBaseTokens] = useState<TokenInfo[]>()
// ----------------------------------- // -----------------------------------
// Helper: connect to web3 // Helper: get web3 provider from MetaMask
// ----------------------------------- // -----------------------------------
const connect = useCallback(async () => { const connectMetaMask = useCallback(async () => {
if (!web3Modal || !signClient) {
setWeb3Loading(false)
return
}
try { try {
setWeb3Loading(true) setWeb3Loading(true)
LoggerInstance.log('[web3] Connecting Web3...') LoggerInstance.log('[web3] Connecting Web3...')
const provider = await detectEthereumProvider()
setWeb3Provider(provider)
} catch (error) {
LoggerInstance.error('[web3] Error: ', error.message)
} finally {
setWeb3Loading(false)
}
}, [])
// -----------------------------------
// Helper: get web3 provider from Web3Modal
// -----------------------------------
const connectWeb3Modal = useCallback(async () => {
try {
setWeb3Loading(true)
LoggerInstance.log('[web3] Connecting Web3...')
const web3Modal = new Web3Modal({
projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID,
standaloneChains: ['eip155:1'],
walletConnectVersion: 2
// theme: web3ModalTheme
})
const signClient = await SignClient.init({
projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID
})
if (signClient) { if (signClient) {
const namespaces = { const requiredNamespaces = {
eip155: { eip155: {
methods: ['eth_sign'], methods: ['eth_sign'],
chains: ['eip155:1'], chains: ['eip155:1'],
@ -123,42 +134,24 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
} }
} }
const { uri, approval } = await signClient.connect({ const { uri, approval } = await signClient.connect({
requiredNamespaces: namespaces requiredNamespaces
}) })
if (uri) { if (uri) {
const provider = await web3Modal.openModal({ const provider = await web3Modal.openModal({
uri, uri,
standaloneChains: namespaces.eip155.chains standaloneChains: requiredNamespaces.eip155.chains
}) })
await approval() await approval()
setWeb3Provider(provider) setWeb3Provider(provider)
web3Modal.closeModal() web3Modal.closeModal()
} }
} }
if (!web3Provider) return
const web3 = new Web3(web3Provider)
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) { } catch (error) {
LoggerInstance.error('[web3] Error: ', error.message) LoggerInstance.error('[web3] Error: ', error.message)
} finally { } finally {
setWeb3Loading(false) setWeb3Loading(false)
} }
}, [web3Modal, web3Provider, signClient]) }, [])
// ----------------------------------- // -----------------------------------
// Helper: Get approved base tokens list // Helper: Get approved base tokens list
@ -244,30 +237,34 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
}, [accountId]) }, [accountId])
// ----------------------------------- // -----------------------------------
// Create initial Web3Modal instance // Init Web3
// ----------------------------------- // -----------------------------------
useEffect(() => { useEffect(() => {
if (web3Modal) { if (!web3Provider) return
setWeb3Loading(false)
return
}
async function init() { async function initWeb3() {
const web3Modal = new Web3Modal({ try {
projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID, const web3 = new Web3(web3Provider)
standaloneChains: ['eip155:1'], setWeb3(web3)
walletConnectVersion: 2 LoggerInstance.log('[web3] Web3 created.', web3)
// theme: web3ModalTheme
}) const networkId = await web3.eth.net.getId()
const signClient = await SignClient.init({ setNetworkId(networkId)
projectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID LoggerInstance.log('[web3] network id ', networkId)
})
setWeb3Modal(web3Modal) const chainId = await web3.eth.getChainId()
setSignClient(signClient) setChainId(chainId)
LoggerInstance.log('[web3] Web3Modal instance created.', web3Modal) 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)
} }
init() }
}, [web3Modal]) initWeb3()
}, [web3Provider])
// ----------------------------------- // -----------------------------------
// Reconnect automatically for returning users // Reconnect automatically for returning users
@ -431,7 +428,6 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
value={{ value={{
web3, web3,
web3Provider, web3Provider,
web3Modal,
accountId, accountId,
accountEns, accountEns,
accountEnsAvatar, accountEnsAvatar,
@ -445,7 +441,8 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
web3Loading, web3Loading,
isSupportedOceanNetwork, isSupportedOceanNetwork,
approvedBaseTokens, approvedBaseTokens,
connect, connectWeb3Modal,
connectMetaMask,
logout logout
}} }}
> >

View File

@ -1,30 +1,25 @@
import React, { FormEvent } from 'react' import React, { useState } 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 styles from './Account.module.css' import styles from './Account.module.css'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import Avatar from '@shared/atoms/Avatar' import Avatar from '@shared/atoms/Avatar'
import Modal from '@components/@shared/atoms/Modal'
// 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 {
useWeb3() accountId,
accountEns,
accountEnsAvatar,
connectWeb3Modal,
connectMetaMask
} = useWeb3()
async function handleActivation(e: FormEvent<HTMLButtonElement>) { const [isModalOpen, setIsModalOpen] = useState(false)
// prevent accidentially submitting a form the button might be in
e.preventDefault()
await connect() return accountId ? (
}
return !accountId && web3Modal?.cachedProvider ? (
// Improve user experience for cached provider when connecting takes some time
<button className={styles.button} onClick={(e) => e.preventDefault()}>
<Loader />
</button>
) : accountId ? (
<button <button
className={styles.button} className={styles.button}
aria-label="Account" aria-label="Account"
@ -38,15 +33,25 @@ const Account = React.forwardRef((props, ref: any) => {
<Caret aria-hidden="true" className={styles.caret} /> <Caret aria-hidden="true" className={styles.caret} />
</button> </button>
) : ( ) : (
<>
<button <button
className={`${styles.button} ${styles.initial}`} className={`${styles.button} ${styles.initial}`}
onClick={(e) => handleActivation(e)} onClick={() => setIsModalOpen(true)}
// Need the `ref` here although we do not want // Need the `ref` here although we do not want
// the Tippy to show in this state. // the Tippy to show in this state.
ref={ref} ref={ref}
> >
Connect <span>Wallet</span> Connect <span>Wallet</span>
</button> </button>
<Modal
title={'Connect Wallet'}
isOpen={isModalOpen}
onToggleModal={() => setIsModalOpen(false)}
>
<button onClick={() => connectMetaMask()}>MetaMask</button>
<button onClick={() => connectWeb3Modal()}>WalletConnect</button>
</Modal>
</>
) )
}) })