react/src/providers/OceanProvider/OceanProvider.tsx

200 lines
5.2 KiB
TypeScript
Raw Normal View History

2020-07-18 02:44:41 +02:00
import React, {
useContext,
useState,
useEffect,
createContext,
ReactElement
} from 'react'
2020-04-27 16:29:34 +02:00
import Web3 from 'web3'
2020-07-09 14:33:22 +02:00
import ProviderStatus from './ProviderStatus'
import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib'
2020-07-14 13:20:17 +02:00
import Web3Modal, { ICoreOptions } from 'web3modal'
2020-07-16 11:25:01 +02:00
import { getDefaultProviders } from './getDefaultProviders'
2020-07-20 12:22:26 +02:00
2020-07-20 13:09:00 +02:00
interface Balance {
2020-07-20 13:24:42 +02:00
eth: string | undefined
ocean: string | undefined
2020-07-20 13:09:00 +02:00
}
2020-04-25 02:28:16 +02:00
interface OceanProviderValue {
2020-07-09 14:33:22 +02:00
web3: Web3 | undefined
web3Provider: any
web3Modal: Web3Modal
2020-04-25 02:28:16 +02:00
ocean: Ocean
2020-07-09 14:33:22 +02:00
config: Config
2020-04-27 10:34:22 +02:00
account: Account
accountId: string
2020-07-20 13:09:00 +02:00
balance: Balance
2020-07-09 14:33:22 +02:00
chainId: number | undefined
status: ProviderStatus
2020-07-20 13:58:45 +02:00
connect: (opts?: Partial<ICoreOptions>) => Promise<void>
logout: () => Promise<void>
2020-07-09 14:33:22 +02:00
}
2020-04-25 02:28:16 +02:00
const OceanContext = createContext(null)
function OceanProvider({
config,
children
}: {
2020-07-13 11:57:27 +02:00
config: Config
2020-05-07 13:42:29 +02:00
children: any
2020-07-18 02:44:41 +02:00
}): ReactElement {
2020-07-09 14:33:22 +02:00
const [web3, setWeb3] = useState<Web3 | undefined>()
const [web3Provider, setWeb3Provider] = useState<any | undefined>()
2020-04-25 02:28:16 +02:00
const [ocean, setOcean] = useState<Ocean | undefined>()
2020-07-09 14:33:22 +02:00
const [web3Modal, setWeb3Modal] = useState<Web3Modal>(null)
const [chainId, setChainId] = useState<number | undefined>()
2020-04-27 10:34:22 +02:00
const [account, setAccount] = useState<Account | undefined>()
const [accountId, setAccountId] = useState<string | undefined>()
2020-07-20 13:24:42 +02:00
const [balance, setBalance] = useState<Balance | undefined>({
eth: undefined,
ocean: undefined
})
2020-07-17 12:24:46 +02:00
const [status, setStatus] = useState<ProviderStatus>(
ProviderStatus.NOT_AVAILABLE
)
const [web3ModalOpts, setWeb3ModalOpts] = useState<Partial<ICoreOptions>>()
2020-07-09 14:33:22 +02:00
function init() {
2020-07-14 13:34:08 +02:00
Logger.log('Ocean Provider init')
2020-07-16 16:03:26 +02:00
window &&
window.ethereum &&
(window.ethereum.autoRefreshOnNetworkChange = false)
2020-07-09 14:33:22 +02:00
}
2020-07-14 13:34:08 +02:00
// On mount setup Web3Modal instance
2020-04-27 10:34:22 +02:00
useEffect(() => {
2020-07-09 14:33:22 +02:00
init()
2020-04-27 10:34:22 +02:00
}, [])
2020-07-13 11:57:27 +02:00
async function connect(opts?: Partial<ICoreOptions>) {
2020-07-14 13:34:08 +02:00
Logger.log('Connecting ....')
2020-07-20 13:37:34 +02:00
2020-07-16 11:25:01 +02:00
if (opts === undefined) {
2020-07-15 11:18:22 +02:00
opts = await getDefaultProviders()
}
2020-07-20 13:09:00 +02:00
const instance = web3Modal || new Web3Modal(opts)
2020-07-13 11:57:27 +02:00
setWeb3Modal(instance)
2020-07-20 13:09:00 +02:00
Logger.log('Web3Modal instance created.', instance)
const provider = web3Provider || (await instance.connect())
2020-07-09 14:33:22 +02:00
setWeb3Provider(provider)
const web3 = new Web3(provider)
setWeb3(web3)
2020-07-20 13:37:34 +02:00
Logger.log('Web3 created.', web3)
2020-07-09 14:33:22 +02:00
2020-07-20 13:33:42 +02:00
const chainId = web3 && (await web3.eth.getChainId())
setChainId(chainId)
Logger.log('chain id ', chainId)
2020-07-13 11:57:27 +02:00
config.web3Provider = web3
const ocean = await Ocean.getInstance(config)
setOcean(ocean)
2020-07-20 13:09:00 +02:00
Logger.log('Ocean instance created.', ocean)
2020-07-20 13:37:34 +02:00
2020-07-13 11:57:27 +02:00
setStatus(ProviderStatus.CONNECTED)
2020-07-20 13:09:00 +02:00
2020-07-13 11:57:27 +02:00
const account = (await ocean.accounts.list())[0]
setAccount(account)
Logger.log('Account ', account)
2020-07-20 13:09:00 +02:00
const accountId = await getAccountId(web3)
2020-07-13 11:57:27 +02:00
setAccountId(accountId)
Logger.log('account id', accountId)
2020-07-20 13:09:00 +02:00
2020-07-20 13:33:20 +02:00
const balance = await getBalance(account)
2020-07-13 11:57:27 +02:00
setBalance(balance)
2020-07-20 13:09:00 +02:00
Logger.log('balance', JSON.stringify(balance))
2020-07-09 14:33:22 +02:00
}
async function logout() {
// ToDo check how is the proper way to logout
web3Modal.clearCachedProvider()
}
2020-07-20 13:09:00 +02:00
async function getAccountId(web3: Web3) {
2020-07-09 14:33:22 +02:00
const accounts = await web3.eth.getAccounts()
return accounts[0]
}
2020-07-20 13:33:20 +02:00
async function getBalance(account: Account) {
const eth = await account.getEtherBalance()
const ocean = await account.getOceanBalance()
2020-07-20 13:09:00 +02:00
2020-07-20 13:33:20 +02:00
return { eth, ocean }
2020-07-09 14:33:22 +02:00
}
//
// Listen for provider, account & network changes
// and react to it
//
const handleConnect = async (provider: any) => {
Logger.debug("Handling 'connect' event with payload", provider)
}
const handleAccountsChanged = async (accounts: string[]) => {
console.debug("Handling 'accountsChanged' event with payload", accounts)
// if (status === ProviderStatus.CONNECTED) {
connect(web3ModalOpts)
2020-07-17 12:24:46 +02:00
// }
2020-07-09 14:33:22 +02:00
}
2020-07-15 11:18:22 +02:00
// ToDo need to handle this, it's not implemented, need to update chainId and reinitialize ocean lib
2020-07-09 14:33:22 +02:00
const handleNetworkChanged = async (networkId: string | number) => {
2020-07-17 12:24:46 +02:00
console.debug(
"Handling 'networkChanged' event with payload",
networkId,
status
)
// if (status === ProviderStatus.CONNECTED) {
connect(web3ModalOpts)
// }
2020-07-09 14:33:22 +02:00
}
2020-04-25 02:28:16 +02:00
useEffect(() => {
2020-07-09 14:33:22 +02:00
web3Modal && web3Modal.on('connect', handleConnect)
if (web3Provider !== undefined && web3Provider !== null) {
web3Provider.on('accountsChanged', handleAccountsChanged)
web3Provider.on('networkChanged', handleNetworkChanged)
return () => {
web3Provider.removeListener('accountsChanged', handleAccountsChanged)
web3Provider.removeListener('networkChanged', handleNetworkChanged)
}
2020-04-25 02:28:16 +02:00
}
2020-07-17 12:24:46 +02:00
}, [web3Modal, web3Provider])
2020-07-09 14:33:22 +02:00
2020-04-25 02:28:16 +02:00
return (
<OceanContext.Provider
2020-04-27 10:34:22 +02:00
value={
{
2020-07-09 14:33:22 +02:00
web3,
web3Provider,
web3Modal,
2020-04-27 10:34:22 +02:00
ocean,
account,
accountId,
balance,
2020-07-09 14:33:22 +02:00
chainId,
2020-04-27 14:37:26 +02:00
status,
2020-07-13 11:57:27 +02:00
config,
2020-07-09 14:33:22 +02:00
connect,
2020-07-14 13:34:08 +02:00
logout
2020-04-27 10:34:22 +02:00
} as OceanProviderValue
}
2020-04-25 02:28:16 +02:00
>
{children}
</OceanContext.Provider>
)
}
2020-04-27 14:58:37 +02:00
// Helper hook to access the provider values
const useOcean = (): OceanProviderValue => useContext(OceanContext)
2020-04-25 02:28:16 +02:00
2020-07-20 13:09:00 +02:00
export { OceanProvider, useOcean, OceanProviderValue, Balance }
2020-04-25 02:28:16 +02:00
export default OceanProvider