import React, { useContext, useState, createContext, ReactElement, useCallback, ReactNode, useEffect } from 'react' import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib' import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' import { useWeb3 } from './Web3' import { getDevelopmentConfig, getOceanConfig, getUserInfo } from '../utils/ocean' import { UserBalance } from '../@types/TokenBalance' const refreshInterval = 20000 // 20 sec. interface OceanProviderValue { ocean: Ocean config: ConfigHelperConfig account: Account balance: UserBalance connect: (config?: Config) => Promise refreshBalance: () => Promise } const OceanContext = createContext({} as OceanProviderValue) function OceanProvider({ initialConfig, children }: { initialConfig: Config | ConfigHelperConfig children: ReactNode }): ReactElement { const { web3, accountId, networkId } = useWeb3() const [ocean, setOcean] = useState() const [account, setAccount] = useState() const [balance, setBalance] = useState({ eth: undefined, ocean: undefined }) const [config, setConfig] = useState( initialConfig ) // ----------------------------------- // Create Ocean instance // ----------------------------------- const connect = useCallback( async (newConfig?: ConfigHelperConfig | Config) => { try { const usedConfig = newConfig || config Logger.log('[ocean] Connecting Ocean...', usedConfig) usedConfig.web3Provider = web3 || initialConfig.web3Provider if (newConfig) { setConfig(usedConfig) } if (usedConfig.web3Provider) { const newOcean = await Ocean.getInstance(usedConfig) setOcean(newOcean) Logger.log('[ocean] Ocean instance created.', newOcean) } } catch (error) { Logger.error('[ocean] Error: ', error.message) } }, [web3, config, initialConfig.web3Provider] ) async function refreshBalance() { if (!ocean || !account || !web3) return const { balance } = await getUserInfo(ocean) setBalance(balance) } // ----------------------------------- // Initial connection // ----------------------------------- useEffect(() => { async function init() { await connect() } init() // init periodic refresh of wallet balance const balanceInterval = setInterval(() => refreshBalance(), refreshInterval) return () => { clearInterval(balanceInterval) } }, []) // ----------------------------------- // Get user info, handle account change from web3 // ----------------------------------- useEffect(() => { if (!ocean || !accountId || !web3) return async function getInfo() { const { account, balance } = await getUserInfo(ocean) setAccount(account) setBalance(balance) } getInfo() }, [ocean, accountId, web3]) // ----------------------------------- // Handle network change from web3 // ----------------------------------- useEffect(() => { if (!networkId) return async function reconnect() { const newConfig = { ...getOceanConfig(networkId), // add local dev values ...(networkId === 8996 && { ...getDevelopmentConfig() }) } try { await connect(newConfig) } catch (error) { Logger.error('[ocean] Error: ', error.message) } } reconnect() }, [networkId]) return ( {children} ) } // Helper hook to access the provider values const useOcean = (): OceanProviderValue => useContext(OceanContext) export { OceanProvider, useOcean, OceanProviderValue, OceanContext } export default OceanProvider