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

initial prototype

This commit is contained in:
Max Berman 2020-01-02 15:13:06 +01:00
parent a2c94b879f
commit 11a7fdd7a6
7 changed files with 407 additions and 351 deletions

View File

@ -1,6 +1,5 @@
{ {
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"trailingComma": "none", "trailingComma": "none"
"tabWidth": 2
} }

View File

@ -46,7 +46,7 @@ const AssetTeaser = ({
/> />
)} )}
<h1>{main.name}</h1> <h1>{main.name}</h1>
<h2>test</h2>
{!minimal && ( {!minimal && (
<div className={styles.description}> <div className={styles.description}>
<Dotdotdot clamp={3}> <Dotdotdot clamp={3}>

View File

@ -1,15 +1,30 @@
import React, { useState } from 'react' import React, { useState, useContext } from 'react'
import { CONNECTIONS } from '../../config' import { CONNECTIONS } from '../../config'
import { User } from '../../context'
/* NETWORK SWITCHER */ /* NETWORK SWITCHER */
const urlParams = new URLSearchParams(window.location.search) const urlParams = new URLSearchParams(window.location.search)
const networkFromParam = urlParams.get('network') || 'pacific' const networkFromParam = urlParams.get('network') || 'pacific'
const idx = Object.keys(CONNECTIONS).indexOf(networkFromParam)
const commonsNetwork = Object.values(CONNECTIONS)[idx] // TypeScript won't let me access CONNECTIONS[networkFromParam] directly
console.log(commonsNetwork) // console.log(Object.keys(CONNECTIONS))
export function NetworkSwitcher() { export function NetworkSwitcher() {
return null const userContext = useContext(User)
const switchNetwork = (networkName: string): any => {
const idx = Object.keys(CONNECTIONS).indexOf(networkName)
userContext.switchNetwork(networkName, Object.values(CONNECTIONS)[idx]) // TypeScript won't let me access CONNECTIONS[networkName] directly
}
return (
<div>
<ul>
{Object.keys(CONNECTIONS).map((networkName, i) => (
<li key={i} onClick={() => switchNetwork(networkName)}>
{networkName}
</li>
))}
</ul>
<em>{userContext.network}</em>
</div>
)
} }

View File

@ -2,26 +2,7 @@
// commons-server connection // commons-server connection
// //
export const serviceUri = export const serviceUri =
process.env.REACT_APP_SERVICE_URI || 'http://localhost:4000' process.env.REACT_APP_SERVICE_URI || 'http://localhost:4000'
//
// OCEAN REMOTE CONNECTIONS
//
export const nodeUri =
process.env.REACT_APP_NODE_URI || 'https://pacific.oceanprotocol.com'
export const aquariusUri =
process.env.REACT_APP_AQUARIUS_URI ||
'https://aquarius.commons.oceanprotocol.com'
export const brizoUri =
process.env.REACT_APP_BRIZO_URI || 'https://brizo.commons.oceanprotocol.com'
export const brizoAddress =
process.env.REACT_APP_BRIZO_ADDRESS ||
'0x008c25ed3594e094db4592f4115d5fa74c4f41ea'
export const secretStoreUri =
process.env.REACT_APP_SECRET_STORE_URI ||
'https://secret-store.oceanprotocol.com'
export const faucetUri =
process.env.REACT_APP_FAUCET_URI || 'https://faucet.oceanprotocol.com'
// //
// APP CONFIG // APP CONFIG
@ -30,40 +11,62 @@ export const verbose = true
export const analyticsId = 'UA-60614729-11' export const analyticsId = 'UA-60614729-11'
export const showChannels = export const showChannels =
process.env.REACT_APP_SHOW_CHANNELS === 'true' || false process.env.REACT_APP_SHOW_CHANNELS === 'true' || false
export const allowPricing = export const allowPricing =
process.env.REACT_APP_ALLOW_PRICING === 'true' || false process.env.REACT_APP_ALLOW_PRICING === 'true' || false
export const showRequestTokens = export const showRequestTokens =
process.env.REACT_APP_SHOW_REQUEST_TOKENS_BUTTON === 'true' || false process.env.REACT_APP_SHOW_REQUEST_TOKENS_BUTTON === 'true' || false
// https://ipfs.github.io/public-gateway-checker/ // https://ipfs.github.io/public-gateway-checker/
export const ipfsGatewayUri = export const ipfsGatewayUri =
process.env.REACT_APP_IPFS_GATEWAY_URI || 'https://gateway.ipfs.io' process.env.REACT_APP_IPFS_GATEWAY_URI || 'https://gateway.ipfs.io'
export const ipfsNodeUri = export const ipfsNodeUri =
process.env.REACT_APP_IPFS_NODE_URI || 'https://ipfs.infura.io:5001' process.env.REACT_APP_IPFS_NODE_URI || 'https://ipfs.infura.io:5001'
//
// OCEAN REMOTE CONNECTIONS
//
export const nodeUri =
process.env.REACT_APP_NODE_URI || 'https://pacific.oceanprotocol.com'
export const aquariusUri =
process.env.REACT_APP_AQUARIUS_URI ||
'https://aquarius.commons.oceanprotocol.com'
export const brizoUri =
process.env.REACT_APP_BRIZO_URI || 'https://brizo.commons.oceanprotocol.com'
export const brizoAddress =
process.env.REACT_APP_BRIZO_ADDRESS ||
'0x008c25ed3594e094db4592f4115d5fa74c4f41ea'
export const secretStoreUri =
process.env.REACT_APP_SECRET_STORE_URI ||
'https://secret-store.oceanprotocol.com'
export const faucetUri =
process.env.REACT_APP_FAUCET_URI || 'https://faucet.oceanprotocol.com'
export const CONNECTIONS = { export const CONNECTIONS = {
pacific: { Pacific: {
nodeUri: 'https://pacific.oceanprotocol.com', nodeUri: 'https://pacific.oceanprotocol.com',
aquariusUri: 'https://aquarius.commons.oceanprotocol.com', aquariusUri: 'https://aquarius.commons.oceanprotocol.com',
brizoUri: 'https://brizo.commons.oceanprotocol.com', brizoUri: 'https://brizo.commons.oceanprotocol.com',
brizoAddress: '0x008c25ed3594e094db4592f4115d5fa74c4f41ea', brizoAddress: '0x008c25ed3594e094db4592f4115d5fa74c4f41ea',
secretStoreUri: 'https://secret-store.oceanprotocol.com', secretStoreUri: 'https://secret-store.oceanprotocol.com',
faucetUri: 'https://faucet.oceanprotocol.com' //faucetUri: 'https://faucet.oceanprotocol.com',
}, verbose: true
nile: { },
nodeUri: 'https://nile.dev-ocean.com', Nile: {
aquariusUri: 'https://aquarius.nile.dev-ocean.com', nodeUri: 'https://nile.dev-ocean.com',
brizoUri: 'https://brizo.nile.dev-ocean.com', aquariusUri: 'https://aquarius.nile.dev-ocean.com',
brizoAddress: '0x4aaab179035dc57b35e2ce066919048686f82972', brizoUri: 'https://brizo.nile.dev-ocean.com',
secretStoreUri: 'https://secret-store.nile.dev-ocean.com', brizoAddress: '0x4aaab179035dc57b35e2ce066919048686f82972',
faucetUri: 'https://faucet.nile.dev-ocean.com' secretStoreUri: 'https://secret-store.nile.dev-ocean.com',
}, //faucetUri: 'https://faucet.nile.dev-ocean.com',
duero: { verbose: true
nodeUri: 'https://duero.dev-ocean.com', },
aquariusUri: 'https://aquarius.duero.dev-ocean.com', Duero: {
brizoUri: 'https://brizo.duero.dev-ocean.com', nodeUri: 'https://duero.dev-ocean.com',
brizoAddress: '0x9d4ed58293f71122ad6a733c1603927a150735d0', aquariusUri: 'https://aquarius.duero.dev-ocean.com',
secretStoreUri: 'https://secret-store.duero.dev-ocean.com', brizoUri: 'https://brizo.duero.dev-ocean.com',
faucetUri: 'https://faucet.duero.dev-ocean.com' brizoAddress: '0x9d4ed58293f71122ad6a733c1603927a150735d0',
} secretStoreUri: 'https://secret-store.duero.dev-ocean.com',
//faucetUri: 'https://faucet.duero.dev-ocean.com',
verbose: true
}
} }

View File

@ -7,47 +7,47 @@ import { requestFromFaucet } from '../ocean'
const bip39 = require('bip39') const bip39 = require('bip39')
export class BurnerWalletProvider { export class BurnerWalletProvider {
private web3: Web3 private web3: Web3
public constructor() { public constructor() {
// Default // Default
this.web3 = null as any this.web3 = null as any
}
public async isLogged() {
if (localStorage.getItem('seedphrase') !== null) {
return true
}
return false
}
public async startLogin() {
let mnemonic
const isLogged = await this.isLogged()
if (isLogged) {
mnemonic = localStorage.getItem('seedphrase')
} else {
mnemonic = bip39.generateMnemonic()
localStorage.setItem('seedphrase', mnemonic)
} }
localStorage.setItem('logType', 'BurnerWallet') public async isLogged() {
const provider = new HDWalletProvider(mnemonic, nodeUri, 0, 1) if (localStorage.getItem('seedphrase') !== null) {
this.web3 = new Web3(provider as any) return true
const accounts = await this.web3.eth.getAccounts() }
const balance = await this.web3.eth.getBalance(accounts[0]) return false
}
// fill with Ether if account balance is empty public async startLogin() {
balance === '0' && (await requestFromFaucet(provider.getAddress(0))) let mnemonic
} const isLogged = await this.isLogged()
public async logout() { if (isLogged) {
// localStorage.removeItem('seedphrase') mnemonic = localStorage.getItem('seedphrase')
localStorage.removeItem('logType') } else {
} mnemonic = bip39.generateMnemonic()
localStorage.setItem('seedphrase', mnemonic)
}
public getProvider() { localStorage.setItem('logType', 'BurnerWallet')
return this.web3 const provider = new HDWalletProvider(mnemonic, nodeUri, 0, 1)
} this.web3 = new Web3(provider as any)
const accounts = await this.web3.eth.getAccounts()
const balance = await this.web3.eth.getBalance(accounts[0])
// fill with Ether if account balance is empty
balance === '0' && (await requestFromFaucet(provider.getAddress(0)))
}
public async logout() {
// localStorage.removeItem('seedphrase')
localStorage.removeItem('logType')
}
public getProvider() {
return this.web3
}
} }

View File

@ -6,263 +6,298 @@ import { provideOcean, requestFromFaucet, FaucetResponse } from '../ocean'
import MarketProvider from './MarketProvider' import MarketProvider from './MarketProvider'
import { MetamaskProvider } from './MetamaskProvider' import { MetamaskProvider } from './MetamaskProvider'
import { BurnerWalletProvider } from './BurnerWalletProvider' import { BurnerWalletProvider } from './BurnerWalletProvider'
import { NetworkSwitcher } from '../components/molecules/NetworkSwitcher' import { NetworkSwitcher } from '../components/molecules/NetworkSwitcher'
import { import {
aquariusUri, aquariusUri,
brizoUri, brizoUri,
brizoAddress, brizoAddress,
nodeUri, nodeUri,
secretStoreUri, secretStoreUri,
verbose verbose,
CONNECTIONS
} from '../config' } from '../config'
const oceanConfig = {
nodeUri,
aquariusUri,
brizoUri,
brizoAddress,
secretStoreUri,
verbose
}
const POLL_ACCOUNTS = 1000 // every 1s const POLL_ACCOUNTS = 1000 // every 1s
const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min const POLL_NETWORK = POLL_ACCOUNTS * 60 // every 1 min
const DEFAULT_WEB3 = new Web3(new Web3.providers.HttpProvider(nodeUri)) // default web3 const DEFAULT_WEB3 = new Web3(new Web3.providers.HttpProvider(nodeUri)) // default web3
interface UserProviderState { interface UserProviderState {
isLogged: boolean isLogged: boolean
isBurner: boolean isBurner: boolean
isWeb3Capable: boolean isWeb3Capable: boolean
isLoading: boolean isLoading: boolean
account: string account: string
balance: { balance: {
eth: number eth: number
ocn: number ocn: number
} }
network: string network: string
web3: Web3 web3: Web3
ocean: Ocean ocean: Ocean
requestFromFaucet(account: string): Promise<FaucetResponse> switchNetwork(network: string, config: Config): any
loginMetamask(): Promise<any> requestFromFaucet(account: string): Promise<FaucetResponse>
loginBurnerWallet(): Promise<any> loginMetamask(): Promise<any>
logoutBurnerWallet(): Promise<any> loginBurnerWallet(): Promise<any>
loadOcean: (config: Config) => Promise<Ocean | void> logoutBurnerWallet(): Promise<any>
message: string loadOcean: (config: Config) => Promise<Ocean | void>
} message: string
const oceanConfig = {
nodeUri,
aquariusUri,
brizoUri,
brizoAddress,
secretStoreUri,
verbose
} }
export default class UserProvider extends PureComponent<{}, UserProviderState> { export default class UserProvider extends PureComponent<{}, UserProviderState> {
private loginMetamask = async () => { public state = {
const metamaskProvider = new MetamaskProvider()
await metamaskProvider.startLogin()
const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
isBurner: false,
web3
},
() => {
this.loadOcean({
web3Provider: this.state.web3,
...oceanConfig
})
}
)
}
private loginBurnerWallet = async () => {
const burnerwalletProvider = new BurnerWalletProvider()
await burnerwalletProvider.startLogin()
const web3 = burnerwalletProvider.getProvider()
this.setState(
{
isLogged: true,
isBurner: true,
web3
},
() => {
this.loadOcean({
web3Provider: this.state.web3,
...oceanConfig
})
}
)
}
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(),
loadOcean: (config: Config) => this.loadOcean(config),
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, isLogged: false,
isBurner: false, isBurner: false,
web3: DEFAULT_WEB3 isWeb3Capable: Boolean(window.web3 || window.ethereum),
}, isLoading: true,
() => { balance: {
this.loadOcean({ eth: 0,
web3Provider: this.state.web3, ocn: 0
...oceanConfig },
}) network: '',
} web3: DEFAULT_WEB3,
) account: '',
} ocean: {} as any,
requestFromFaucet: () => requestFromFaucet(''),
loginMetamask: () => this.loginMetamask(),
switchNetwork: (network: string, config: Config) =>
this.switchNetwork(network, config),
loginBurnerWallet: () => this.loginBurnerWallet(),
logoutBurnerWallet: () => this.logoutBurnerWallet(),
loadOcean: (config: Config) => this.loadOcean(config),
message: 'Connecting to Ocean...'
}
private loadOcean = async (config: Config) => { private switchNetwork = (network: string, config: Config) => {
const { ocean } = await provideOcean({ console.log({ network, config, oceanConfig })
web3Provider: this.state.web3, const nodeUrl: any = config.nodeUri
...config this.setState(
})
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, network,
web3 web3: new Web3(new Web3.providers.HttpProvider(nodeUrl))
},
() =>
this.loadOcean({
web3Provider: this.state.web3,
...config
})
)
}
private loginMetamask = async () => {
console.log('loginMetamask')
const metamaskProvider = new MetamaskProvider()
await metamaskProvider.startLogin()
const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
isBurner: false,
web3
}, },
() => { () => {
this.loadOcean({ this.loadOcean({
web3Provider: this.state.web3, web3Provider: this.state.web3,
...oceanConfig ...oceanConfig
}) })
} }
) )
} else { }
this.loadDefaultWeb3()
private loginBurnerWallet = async () => {
console.log('loginMetamask')
const burnerwalletProvider = new BurnerWalletProvider()
await burnerwalletProvider.startLogin()
const web3 = burnerwalletProvider.getProvider()
this.setState(
{
isLogged: true,
isBurner: true,
web3
},
() => {
this.loadOcean({
web3Provider: this.state.web3,
...oceanConfig
})
}
)
}
private logoutBurnerWallet = async () => {
const burnerwalletProvider = new BurnerWalletProvider()
await burnerwalletProvider.logout()
}
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
)
} }
break
case 'BurnerWallet':
this.loginBurnerWallet()
break
default:
this.loginBurnerWallet()
break
} }
}
private fetchAccounts = async () => { private initNetworkPoll() {
const { ocean, isLogged } = this.state if (!this.networkInterval) {
this.networkInterval = setInterval(this.fetchNetwork, POLL_NETWORK)
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) => { private loadDefaultWeb3 = async () => {
const balance = await account.getBalance() console.log('loadDefaultWeb3')
const { eth, ocn } = balance this.setState(
if (eth !== this.state.balance.eth || ocn !== this.state.balance.ocn) { {
this.setState({ balance: { eth, ocn } }) isLogged: false,
isBurner: false,
web3: DEFAULT_WEB3
},
() => {
this.loadOcean({
web3Provider: this.state.web3,
...oceanConfig
})
}
)
} }
}
private fetchNetwork = async () => { private loadOcean = async (config: Config) => {
const { ocean } = this.state console.log('load ocean', config)
let network = 'Unknown' const { ocean } = await provideOcean({
if (ocean.keeper) { web3Provider: this.state.web3,
network = await ocean.keeper.getNetworkName() ...config
})
this.setState({ ocean, isLoading: false }, () => {
this.initNetworkPoll()
this.initAccountsPoll()
this.fetchNetwork()
this.fetchAccounts()
})
} }
network !== this.state.network && this.setState({ network })
}
public render() { private bootstrap = async () => {
return ( const logType = localStorage.getItem('logType')
<User.Provider value={this.state}> const metamaskProvider = new MetamaskProvider()
<MarketProvider ocean={this.state.ocean}>
<NetworkSwitcher /> console.log('BOOTSTRAP', { logType })
{this.props.children}
</MarketProvider> switch (logType) {
</User.Provider> case 'Metamask':
) if (
} (await metamaskProvider.isAvailable()) &&
(await metamaskProvider.isLogged())
) {
const web3 = metamaskProvider.getProvider()
this.setState(
{
isLogged: true,
web3
},
() => {
this.loadOcean({
web3Provider: this.state.web3,
...oceanConfig
})
}
)
} 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
console.log('1 this.state.network', this.state.network)
let network = 'Unknown'
if (ocean.keeper) {
network = await ocean.keeper.getNetworkName()
}
network !== this.state.network && this.setState({ network })
console.log('2 this.state.network', this.state.network)
}
public render() {
return (
<User.Provider value={this.state}>
<MarketProvider ocean={this.state.ocean}>
<NetworkSwitcher />
{this.props.children}
</MarketProvider>
</User.Provider>
)
}
} }

View File

@ -1,33 +1,37 @@
import React from 'react' import React from 'react'
import { Config } from '@oceanprotocol/squid'
export const User = React.createContext({ export const User = React.createContext({
isLogged: false, isLogged: false,
isBurner: false, isBurner: false,
isWeb3Capable: false, isWeb3Capable: false,
isLoading: false, isLoading: false,
account: '', account: '',
web3: {}, web3: {},
ocean: {}, ocean: {},
balance: { balance: {
eth: 0, eth: 0,
ocn: 0 ocn: 0
}, },
network: '', network: '',
requestFromFaucet: () => { switchNetwork: (network: string, config: Config) => {
/* empty */ /* empty */
}, },
loginMetamask: () => { requestFromFaucet: () => {
/* empty */ /* empty */
}, },
loginBurnerWallet: () => { loginMetamask: () => {
/* empty */ /* empty */
}, },
message: '' loginBurnerWallet: () => {
/* empty */
},
message: ''
}) })
export const Market = React.createContext({ export const Market = React.createContext({
totalAssets: 0, totalAssets: 0,
categories: [''], categories: [''],
network: '', network: '',
networkMatch: false networkMatch: false
}) })