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

cleanup and more fine-grained bootstrap process

* new detection flow, one after the other: web3 -> network -> ocean -> accounts
* make account enabling part of bootstrap
* kick out dedicated startLogin action
* plan for modern, legacy, and non-dapp browsers
* consolidate fetchNetwork & fetchAccounts
This commit is contained in:
Matthias Kretschmann 2019-04-13 13:43:04 +02:00
parent fe695009ff
commit 3a8d6ea284
Signed by: m
GPG Key ID: 606EEEF3C479A91F
9 changed files with 159 additions and 206 deletions

View File

@ -43,45 +43,31 @@ interface AppState {
network: string
web3: Web3
ocean: any
startLogin: () => void
requestFromFaucet(): void
message: string
}
class App extends Component<{}, AppState> {
private accountsInterval: any
private networkInterval: any
public startLogin = (event?: any) => {
if (event) {
event.preventDefault()
}
this.startLoginProcess()
}
private accountsInterval: any = null
private networkInterval: any = null
private requestFromFaucet = async () => {
if (this.state.account !== '') {
try {
const response = await fetch(
`${faucetScheme}://${faucetHost}:${faucetPort}/faucet`,
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: this.state.account,
agent: 'commons'
})
}
)
return response.json()
} catch (error) {
Logger.log('requestFromFaucet', error)
}
} else {
// no account found
try {
const url = `${faucetScheme}://${faucetHost}:${faucetPort}/faucet`
const response = await fetch(url, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
address: this.state.account,
agent: 'commons'
})
})
return response.json()
} catch (error) {
Logger.log('requestFromFaucet', error)
}
}
@ -102,7 +88,6 @@ class App extends Component<{}, AppState> {
),
account: '',
ocean: {} as any,
startLogin: this.startLogin,
requestFromFaucet: this.requestFromFaucet,
message: 'Connecting to Ocean...'
}
@ -116,68 +101,72 @@ class App extends Component<{}, AppState> {
private bootstrap = async () => {
try {
if (window.web3) {
let web3provider = new Web3(window.web3.currentProvider)
this.setState({
isWeb3: true,
message: 'Setting up Web3...'
})
//
// Start with Web3 detection
//
this.setState({ message: 'Setting up Web3...' })
// Modern dapp browsers
if (window.ethereum) {
window.web3 = new Web3(window.ethereum)
this.setState({ isWeb3: true })
}
// Legacy dapp browsers
else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider)
this.setState({ isWeb3: true })
}
// Non-dapp browsers
else {
this.setState({ isWeb3: false })
}
// Modern & legacy dapp browsers
if (this.state.isWeb3) {
//
// Detecting network with window.web3
//
let isNile
await web3provider.eth.net.getId((err, netId) => {
await window.web3.eth.net.getId((err, netId) => {
if (err) return
isNile = netId === 8995
const network = isNile ? 'Nile' : netId.toString()
this.setState({ isNile, network })
if (
isNile !== this.state.isNile ||
network !== this.state.network
) {
this.setState({ isNile, network })
}
})
if (!isNile) {
web3provider = this.state.web3
window.web3 = this.state.web3
}
//
// Provide the Ocean
//
this.setState({ message: 'Connecting to Ocean...' })
const { ocean } = await provideOcean(web3provider)
const { ocean } = await provideOcean(window.web3)
this.setState({ ocean, isLoading: false })
// Set proper network names now that we have Ocean
const network = await ocean.keeper.getNetworkName()
isNile = network === 'Nile'
this.setState({ isNile, network })
this.fetchNetwork()
// Get accounts with Ocean
const accounts = await ocean.accounts.list()
if (accounts.length > 0) {
this.setState({
isLogged: true,
account: accounts[0].getId()
})
const balance = await accounts[0].getBalance()
this.setState({ balance })
}
} else {
//
// No Web3 browser
//
// Get accounts
this.fetchAccounts()
}
// Non-dapp browsers
else {
this.setState({ message: 'Connecting to Ocean...' })
const { ocean } = await provideOcean(this.state.web3)
this.setState({ isLoading: false })
this.setState({ ocean, isLoading: false })
const network = await ocean.keeper.getNetworkName()
const isNile = network === 'Nile'
this.setState({
isNile,
ocean,
network
})
this.fetchNetwork()
}
} catch (e) {
// error in bootstrap process
@ -188,7 +177,7 @@ class App extends Component<{}, AppState> {
}
private initAccountsPoll() {
if (!this.accountsInterval && this.state.ocean.length) {
if (!this.accountsInterval) {
this.accountsInterval = setInterval(
this.fetchAccounts,
POLL_ACCOUNTS
@ -197,16 +186,28 @@ class App extends Component<{}, AppState> {
}
private initNetworkPoll() {
if (!this.networkInterval && this.state.ocean.length) {
if (!this.networkInterval) {
this.networkInterval = setInterval(this.fetchNetwork, POLL_NETWORK)
}
}
private fetchAccounts = async () => {
const { web3 } = window
const { ocean } = this.state
const { ocean, isWeb3, isLogged, isNile } = this.state
if (isWeb3) {
// Modern dapp browsers
if (window.ethereum) {
if (!isLogged && isNile) {
try {
await window.ethereum.enable()
} catch (error) {
// User denied account access...
this.accountsInterval = null
return
}
}
}
if (web3) {
const accounts = await ocean.accounts.list()
if (accounts.length > 0) {
@ -225,23 +226,16 @@ class App extends Component<{}, AppState> {
this.setState({ balance })
}
} else {
this.state.isLogged !== false &&
isLogged !== false &&
this.setState({ isLogged: false, account: '' })
}
} else {
this.state.isWeb3 !== false &&
this.setState({
isWeb3: false,
isLogged: false
})
}
}
private fetchNetwork = async () => {
const { web3 } = window
const { ocean } = this.state
const { ocean, isWeb3 } = this.state
if (web3) {
if (isWeb3) {
const network = await ocean.keeper.getNetworkName()
const isNile = network === 'Nile'
@ -249,32 +243,6 @@ class App extends Component<{}, AppState> {
}
}
private startLoginProcess = async () => {
try {
if (this.state.isWeb3 && window.ethereum) {
await window.ethereum.enable()
const accounts = await this.state.ocean.accounts.list()
if (accounts.length > 0) {
const balance = await accounts[0].getBalance()
this.setState({
isLogged: true,
balance,
account: accounts[0].getId()
})
} else {
// not unlocked
}
} else {
// no metamask/mist, show installation guide!
}
} catch (e) {
Logger.log('error logging', e)
// error in logging process
// show error
// rerun bootstrap process?
}
}
public render() {
return (
<div className={styles.app}>

View File

@ -4,7 +4,6 @@ import { Logger } from '@oceanprotocol/squid'
import { User } from '../../context/User'
import Spinner from '../atoms/Spinner'
import Asset from '../molecules/Asset'
import Web3message from './Web3message'
import styles from './AssetsUser.module.scss'
export default class AssetsUser extends PureComponent<
@ -60,48 +59,49 @@ export default class AssetsUser extends PureComponent<
public render() {
const { account, isNile } = this.context
return isNile && account ? (
<div className={styles.assetsUser}>
{this.props.recent && (
<h2 className={styles.subTitle}>
Your Latest Published Data Sets
</h2>
)}
return (
isNile &&
account && (
<div className={styles.assetsUser}>
{this.props.recent && (
<h2 className={styles.subTitle}>
Your Latest Published Data Sets
</h2>
)}
{this.state.isLoading ? (
<Spinner />
) : this.state.results.length ? (
<>
{this.state.results
.slice(
0,
this.props.recent
? this.props.recent
: undefined
)
.filter(asset => !!asset)
.map((asset: any) => (
<Asset
list={this.props.list}
key={asset.id}
asset={asset}
/>
))}
{this.props.recent && (
<Link className={styles.link} to={'/history'}>
All Data Sets
</Link>
)}
</>
) : (
<div className={styles.empty}>
<p>No Data Sets Yet.</p>
<Link to="/publish">+ Publish A Data Set</Link>
</div>
)}
</div>
) : (
<Web3message />
{this.state.isLoading ? (
<Spinner />
) : this.state.results.length ? (
<>
{this.state.results
.slice(
0,
this.props.recent
? this.props.recent
: undefined
)
.filter(asset => !!asset)
.map((asset: any) => (
<Asset
list={this.props.list}
key={asset.id}
asset={asset}
/>
))}
{this.props.recent && (
<Link className={styles.link} to={'/history'}>
All Data Sets
</Link>
)}
</>
) : (
<div className={styles.empty}>
<p>No Data Sets Yet.</p>
<Link to="/publish">+ Publish A Data Set</Link>
</div>
)}
</div>
)
)
}
}

View File

@ -9,7 +9,7 @@ export default class Web3message extends PureComponent {
private noWeb3 = () => (
<div className={styles.message}>
<AccountStatus className={styles.status} /> Not a Web3 Browser. For
publishing or downloading an asset you need to{' '}
publishing and downloading an asset you need to{' '}
<a
href="https://docs.oceanprotocol.com/tutorials/metamask-setup/"
target="_blank"
@ -21,14 +21,11 @@ export default class Web3message extends PureComponent {
</div>
)
private unlockAccount = (states: any) => (
private unlockAccount = () => (
<div className={styles.message}>
<AccountStatus className={styles.status} /> Account locked. For
publishing and downloading an asset you need to unlock your Web3
account.{' '}
<Button link onClick={states.startLogin}>
Unlock account
</Button>
<AccountStatus className={styles.status} /> No accounts detected.
For publishing and downloading an asset you need to unlock your Web3
account.
</div>
)
@ -52,20 +49,18 @@ export default class Web3message extends PureComponent {
)
public render() {
return (
<User.Consumer>
{states =>
!states.isWeb3
? this.noWeb3()
: !states.isNile
? this.wrongNetwork(states.network)
: !states.isLogged
? this.unlockAccount(states)
: states.isLogged
? this.haveAccount(states.account)
: null
}
</User.Consumer>
)
const { isWeb3, isNile, isLogged, network, account } = this.context
return !isWeb3
? this.noWeb3()
: !isNile
? this.wrongNetwork(network)
: !isLogged
? this.unlockAccount()
: isLogged
? this.haveAccount(account)
: null
}
}
Web3message.contextType = User

View File

@ -13,9 +13,6 @@ export const User = React.createContext({
ocn: 0
},
network: '',
startLogin: () => {
/* empty */
},
requestFromFaucet: () => {
/* empty */
}

View File

@ -76,7 +76,7 @@ export default class AssetFile extends PureComponent<
public render() {
const { ddo, file } = this.props
const { isLoading, message, error } = this.state
const { isLogged } = this.context
const { isLogged, isNile } = this.context
return (
<div className={styles.fileWrap}>
@ -98,7 +98,7 @@ export default class AssetFile extends PureComponent<
primary
className={styles.buttonMain}
onClick={() => this.purchaseAsset(ddo, file.index)}
disabled={!isLogged}
disabled={!isLogged || !isNile}
>
Get file
</Button>

View File

@ -77,7 +77,7 @@ export default class Faucet extends PureComponent<{}, FaucetState> {
<Button
primary
onClick={() => this.getTokens(this.context.requestFromFaucet)}
disabled={!this.context.isLogged}
disabled={!this.context.isLogged || !this.context.isNile}
>
Request Ether
</Button>

View File

@ -1,13 +1,21 @@
import React, { Component } from 'react'
import Route from '../components/templates/Route'
import AssetsUser from '../components/organisms/AssetsUser'
import Web3message from '../components/organisms/Web3message'
import { User } from '../context/User'
export default class History extends Component {
public render() {
return (
<Route title="History">
{(!this.context.isLogged || !this.context.isNile) && (
<Web3message />
)}
<AssetsUser list />
</Route>
)
}
}
History.contextType = User

View File

@ -154,29 +154,9 @@ export default class Step extends PureComponent<StepProps, {}> {
{this.nextButton()}
{lastStep && (
<User.Consumer>
{states =>
states.isLogged ? (
<Button primary>Register asset</Button>
) : states.isWeb3 ? (
<Button onClick={states.startLogin}>
Register asset (unlock Metamask)
</Button>
) : (
<Button
onClick={(e: Event) => {
e.preventDefault()
window.open(
'https://docs.oceanprotocol.com/tutorials/metamask-setup/',
'_blank'
)
}}
>
Register asset (install Metamask)
</Button>
)
}
</User.Consumer>
<Button disabled={!this.context.isLogged} primary>
Register asset
</Button>
)}
</div>
</>

View File

@ -4,6 +4,7 @@ import Route from '../../components/templates/Route'
import Form from '../../components/atoms/Form/Form'
import AssetModel from '../../models/AssetModel'
import { User } from '../../context/User'
import Web3message from '../../components/organisms/Web3message'
import Step from './Step'
import Progress from './Progress'
import ReactGA from 'react-ga'
@ -318,6 +319,10 @@ class Publish extends Component<{}, PublishState> {
title="Publish"
description="Publish a new data set into the Ocean Protocol Network."
>
{(!this.context.isLogged || !this.context.isNile) && (
<Web3message />
)}
<Progress steps={steps} currentStep={this.state.currentStep} />
<Form onSubmit={this.registerAsset}>