1
0
mirror of https://github.com/oceanprotocol/commons.git synced 2023-03-15 18:03:00 +01:00
commons/client/src/context/UserProvider.tsx

235 lines
6.7 KiB
TypeScript

import React, { PureComponent } from 'react'
import Web3 from 'web3'
import { Ocean, Account } from '@oceanprotocol/squid'
import { User } from '.'
import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean'
import { nodeUri } from '../config'
import MarketProvider from './MarketProvider'
import { MetamaskProvider } from './MetamaskProvider'
import { BurnerWalletProvider } from './BurnerWalletProvider'
const POLL_ACCOUNTS = 1000 // every 1s
const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min
const DEFAULT_WEB3 = new Web3(new Web3.providers.HttpProvider(nodeUri)) // default web3
interface UserProviderState {
isLogged: boolean
isBurner: boolean
isWeb3Capable: boolean
isLoading: boolean
account: string
balance: {
eth: number
ocn: number
}
network: string
web3: Web3
ocean: Ocean
requestFromFaucet(account: string): Promise<FaucetResponse>
loginMetamask(): Promise<any>
loginBurnerWallet(): Promise<any>
logoutBurnerWallet(): Promise<any>
message: string
}
export default class UserProvider extends PureComponent<{}, UserProviderState> {
private loginMetamask = async () => {
const metamaskProvider = new MetamaskProvider()
await metamaskProvider.startLogin()
const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
isBurner: false,
web3
},
() => {
this.loadOcean()
}
)
}
private loginBurnerWallet = async () => {
const burnerwalletProvider = new BurnerWalletProvider()
await burnerwalletProvider.startLogin()
const web3 = burnerwalletProvider.getProvider()
this.setState(
{
isLogged: true,
isBurner: true,
web3
},
() => {
this.loadOcean()
}
)
}
private logoutBurnerWallet = async () => {
const burnerwalletProvider = new BurnerWalletProvider()
await burnerwalletProvider.logout()
}
public state = {
isLogged: false,
isBurner: false,
isWeb3Capable: Boolean(window.web3 || window.ethereum),
isLoading: true,
balance: {
eth: 0,
ocn: 0
},
network: '',
web3: DEFAULT_WEB3,
account: '',
ocean: {} as any,
requestFromFaucet: () => requestFromFaucet(''),
loginMetamask: () => this.loginMetamask(),
loginBurnerWallet: () => this.loginBurnerWallet(),
logoutBurnerWallet: () => this.logoutBurnerWallet(),
message: 'Connecting to Ocean...'
}
private accountsInterval: any = null
private networkInterval: any = null
public async componentDidMount() {
await this.bootstrap()
}
private initAccountsPoll() {
if (!this.accountsInterval) {
this.accountsInterval = setInterval(
this.fetchAccounts,
POLL_ACCOUNTS
)
}
}
private initNetworkPoll() {
if (!this.networkInterval) {
this.networkInterval = setInterval(this.fetchNetwork, POLL_NETWORK)
}
}
private loadDefaultWeb3 = async () => {
this.setState(
{
isLogged: false,
isBurner: false,
web3: DEFAULT_WEB3
},
() => {
this.loadOcean()
}
)
}
private loadOcean = async () => {
const { ocean } = await provideOcean(this.state.web3)
this.setState({ ocean, isLoading: false }, () => {
this.initNetworkPoll()
this.initAccountsPoll()
this.fetchNetwork()
this.fetchAccounts()
})
}
private bootstrap = async () => {
const logType = localStorage.getItem('logType')
const metamaskProvider = new MetamaskProvider()
switch (logType) {
case 'Metamask':
if (
(await metamaskProvider.isAvailable()) &&
(await metamaskProvider.isLogged())
) {
const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
web3
},
() => {
this.loadOcean()
}
)
} else {
this.loadDefaultWeb3()
}
break
case 'BurnerWallet':
this.loginBurnerWallet()
break
default:
this.loginBurnerWallet()
break
}
}
private fetchAccounts = async () => {
const { ocean, isLogged } = this.state
if (isLogged) {
let accounts
// Modern dapp browsers
if (window.ethereum && !isLogged) {
// simply set to empty, and have user click a button somewhere
// to initiate account unlocking
accounts = []
// alternatively, automatically prompt for account unlocking
// await this.unlockAccounts()
}
accounts = await ocean.accounts.list()
if (accounts.length > 0) {
const account = await accounts[0].getId()
if (account !== this.state.account) {
this.setState({
account,
isLogged: true,
requestFromFaucet: () => requestFromFaucet(account)
})
await this.fetchBalance(accounts[0])
}
} else {
!isLogged && this.setState({ isLogged: false, account: '' })
}
}
}
private fetchBalance = async (account: Account) => {
const balance = await account.getBalance()
const { eth, ocn } = balance
if (eth !== this.state.balance.eth || ocn !== this.state.balance.ocn) {
this.setState({ balance: { eth, ocn } })
}
}
private fetchNetwork = async () => {
const { ocean } = this.state
let network = 'Unknown'
if (ocean.keeper) {
network = await ocean.keeper.getNetworkName()
}
network !== this.state.network && this.setState({ network })
}
public render() {
return (
<User.Provider value={this.state}>
<MarketProvider ocean={this.state.ocean}>
{this.props.children}
</MarketProvider>
</User.Provider>
)
}
}