diff --git a/src/@types/globals.d.ts b/src/@types/globals.d.ts new file mode 100644 index 0000000..004173e --- /dev/null +++ b/src/@types/globals.d.ts @@ -0,0 +1,13 @@ +import Web3 from 'web3' +import { HttpProvider } from 'web3-core' + +interface EthereumProvider extends HttpProvider { + enable: () => Promise +} + +declare global { + interface Window { + web3: Web3 + ethereum: EthereumProvider + } +} diff --git a/src/index.ts b/src/index.ts index 6550c7e..932def5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,5 @@ +import './@types/globals' + export * from './providers' export * from './hooks' export * from './components' diff --git a/src/providers/OceanProvider/OceanProvider.tsx b/src/providers/OceanProvider/OceanProvider.tsx index d17d30e..e0ecc82 100644 --- a/src/providers/OceanProvider/OceanProvider.tsx +++ b/src/providers/OceanProvider/OceanProvider.tsx @@ -34,7 +34,7 @@ function OceanProvider({ children }: { config: Config - web3: Web3 + web3: Web3 | undefined children: ReactNode }): ReactNode { const [ocean, setOcean] = useState() @@ -58,6 +58,8 @@ function OceanProvider({ // 2. Once `web3` becomes available, connect to the whole network // ------------------------------------------------------------- useEffect(() => { + if (!web3) return + async function init(): Promise { const { ocean, account, accountId, balance } = await connectOcean( web3, diff --git a/src/providers/Web3Provider/Web3Provider.tsx b/src/providers/Web3Provider/Web3Provider.tsx index b86a42b..add7e59 100644 --- a/src/providers/Web3Provider/Web3Provider.tsx +++ b/src/providers/Web3Provider/Web3Provider.tsx @@ -1,17 +1,69 @@ -import React, { ReactNode, useContext, useState, createContext } from 'react' +import React, { + ReactNode, + useContext, + useState, + createContext, + useEffect +} from 'react' import Web3 from 'web3' +import { getWeb3 } from './utils' interface Web3ProviderValue { - web3: Web3 + web3: Web3 | undefined + account: string | undefined + balance: string | undefined + chainId: number | undefined + enable: () => void } const Web3Context = createContext(null) function Web3Provider({ children }: { children: ReactNode }): ReactNode { const [web3, setWeb3] = useState() + const [chainId, setChainId] = useState() + const [account, setAccount] = useState() + const [balance, setBalance] = useState() + + useEffect(() => { + async function initWeb3(): Promise { + const web3 = await getWeb3() + setWeb3(web3) + + const chainId = web3 && (await web3.eth.getChainId()) + setChainId(chainId) + } + initWeb3() + }, []) + + useEffect(() => { + if (!web3) return + + async function initUser(): Promise { + const account = await web3.eth.getAccounts()[0] + setAccount(account) + + const balance = await web3.eth.getBalance(account) + setBalance(balance) + } + initUser() + }, [web3]) + + async function enable(): Promise { + try { + // Request account access + await window.ethereum.enable() + return true + } catch (error) { + // User denied account access + console.error('User denied account access to wallet.') + return false + } + } return ( - + {children} ) diff --git a/src/providers/Web3Provider/utils.ts b/src/providers/Web3Provider/utils.ts new file mode 100644 index 0000000..0c573e7 --- /dev/null +++ b/src/providers/Web3Provider/utils.ts @@ -0,0 +1,22 @@ +import Web3 from 'web3' + +async function getWeb3(): Promise { + let web3: Web3 + + // modern dapp browsers + if (window.ethereum) { + web3 = new Web3(window.ethereum as any) + } + // legacy dapp browsers + else if (window.web3) { + web3 = new Web3(window.web3.currentProvider) + } + // no dapp browser + else { + console.debug('Non-Ethereum browser detected.') + } + + return web3 +} + +export { getWeb3 }