mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
WIP
This commit is contained in:
parent
8023e30061
commit
125df58464
@ -5,12 +5,9 @@ import Footer from './components/organisms/Footer'
|
|||||||
import Spinner from './components/atoms/Spinner'
|
import Spinner from './components/atoms/Spinner'
|
||||||
import { User } from './context'
|
import { User } from './context'
|
||||||
import Routes from './Routes'
|
import Routes from './Routes'
|
||||||
import {commonsNetwork} from './components/molecules/NetworkSwitcher'
|
|
||||||
import './styles/global.scss'
|
import './styles/global.scss'
|
||||||
import styles from './App.module.scss'
|
import styles from './App.module.scss'
|
||||||
|
|
||||||
console.log(commonsNetwork)
|
|
||||||
|
|
||||||
export default class App extends Component {
|
export default class App extends Component {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
@ -36,5 +33,4 @@ export default class App extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
App.contextType = User
|
App.contextType = User
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
import { CONNECTIONS } from '../../config'
|
import { CONNECTIONS } from '../../config'
|
||||||
|
|
||||||
/* TEMP NETWORK SWITCHER */
|
/* NETWORK SWITCHER */
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search)
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
const network = urlParams.get('network') || 'pacific'
|
const networkFromParam = urlParams.get('network') || 'pacific'
|
||||||
const idx = Object.keys(CONNECTIONS).indexOf(network)
|
const idx = Object.keys(CONNECTIONS).indexOf(networkFromParam)
|
||||||
const commonsNetwork = Object.values(CONNECTIONS)[idx]
|
const commonsNetwork = Object.values(CONNECTIONS)[idx] // TypeScript won't let me access CONNECTIONS[networkFromParam] directly
|
||||||
|
|
||||||
|
console.log(commonsNetwork)
|
||||||
|
|
||||||
|
export function NetworkSwitcher() {
|
||||||
export { commonsNetwork }
|
return null
|
||||||
|
}
|
||||||
|
@ -8,34 +8,34 @@ import menu from '../../data/menu'
|
|||||||
import meta from '../../data/meta.json'
|
import meta from '../../data/meta.json'
|
||||||
|
|
||||||
const MenuItem = ({ item }: { item: any }) => (
|
const MenuItem = ({ item }: { item: any }) => (
|
||||||
<NavLink
|
<NavLink
|
||||||
to={item.link}
|
to={item.link}
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
activeClassName={styles.linkActive}
|
activeClassName={styles.linkActive}
|
||||||
exact
|
exact
|
||||||
>
|
>
|
||||||
{item.title}
|
{item.title}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default class Header extends PureComponent {
|
export default class Header extends PureComponent {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<div className={styles.headerContent}>
|
<div className={styles.headerContent}>
|
||||||
<NavLink to="/" className={styles.headerLogo}>
|
<NavLink to="/" className={styles.headerLogo}>
|
||||||
<Logo className={styles.headerLogoImage} />
|
<Logo className={styles.headerLogoImage} />
|
||||||
<h1 className={styles.headerTitle}>{meta.title}</h1>
|
<h1 className={styles.headerTitle}>{meta.title}</h1>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
<nav className={styles.headerMenu}>
|
<nav className={styles.headerMenu}>
|
||||||
{menu.map(item => (
|
{menu.map(item => (
|
||||||
<MenuItem key={item.title} item={item} />
|
<MenuItem key={item.title} item={item} />
|
||||||
))}
|
))}
|
||||||
<AccountStatus className={styles.accountStatus} />
|
<AccountStatus className={styles.accountStatus} />
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,153 +9,151 @@ import ReactGA from 'react-ga'
|
|||||||
import cleanupContentType from '../../../utils/cleanupContentType'
|
import cleanupContentType from '../../../utils/cleanupContentType'
|
||||||
|
|
||||||
export const messages: any = {
|
export const messages: any = {
|
||||||
99: 'Decrypting file URL...',
|
99: 'Decrypting file URL...',
|
||||||
0: '1/3<br />Asking for agreement signature...',
|
0: '1/3<br />Asking for agreement signature...',
|
||||||
1: '1/3<br />Agreement initialized.',
|
1: '1/3<br />Agreement initialized.',
|
||||||
2: '2/3<br />Asking for two payment confirmations...',
|
2: '2/3<br />Asking for two payment confirmations...',
|
||||||
3: '2/3<br />Payment confirmed. Requesting access...',
|
3: '2/3<br />Payment confirmed. Requesting access...',
|
||||||
4: '3/3<br /> Access granted. Consuming file...'
|
4: '3/3<br /> Access granted. Consuming file...'
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AssetFileProps {
|
interface AssetFileProps {
|
||||||
file: File
|
file: File
|
||||||
ddo: DDO
|
ddo: DDO
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AssetFileState {
|
interface AssetFileState {
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
error: string
|
error: string
|
||||||
step: number
|
step: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class AssetFile extends PureComponent<
|
export default class AssetFile extends PureComponent<
|
||||||
AssetFileProps,
|
AssetFileProps,
|
||||||
AssetFileState
|
AssetFileState
|
||||||
> {
|
> {
|
||||||
public static contextType = User
|
public static contextType = User
|
||||||
|
|
||||||
public state = {
|
public state = {
|
||||||
|
isLoading: false,
|
||||||
|
error: '',
|
||||||
|
step: 99
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetState = () =>
|
||||||
|
this.setState({
|
||||||
|
isLoading: true,
|
||||||
|
error: '',
|
||||||
|
step: 99
|
||||||
|
})
|
||||||
|
|
||||||
|
private purchaseAsset = async (ddo: DDO, index: number) => {
|
||||||
|
this.resetState()
|
||||||
|
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Purchase',
|
||||||
|
action: 'purchaseAsset-start ' + ddo.id
|
||||||
|
})
|
||||||
|
|
||||||
|
const { ocean } = this.context
|
||||||
|
|
||||||
|
try {
|
||||||
|
const accounts = await ocean.accounts.list()
|
||||||
|
const service = ddo.findServiceByType('access')
|
||||||
|
|
||||||
|
const agreements = await ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
|
||||||
|
accounts[0].id
|
||||||
|
)
|
||||||
|
const agreement = agreements.find((element: any) => {
|
||||||
|
return element.did === ddo.id
|
||||||
|
})
|
||||||
|
|
||||||
|
let agreementId
|
||||||
|
|
||||||
|
if (agreement) {
|
||||||
|
;({ agreementId } = agreement)
|
||||||
|
} else {
|
||||||
|
agreementId = await ocean.assets
|
||||||
|
.order(ddo.id, service.index, accounts[0])
|
||||||
|
.next((step: number) => this.setState({ step }))
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually add another step here for better UX
|
||||||
|
this.setState({ step: 4 })
|
||||||
|
|
||||||
|
const path = await ocean.assets.consume(
|
||||||
|
agreementId,
|
||||||
|
ddo.id,
|
||||||
|
service.index,
|
||||||
|
accounts[0],
|
||||||
|
'',
|
||||||
|
index
|
||||||
|
)
|
||||||
|
Logger.log('path', path)
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Purchase',
|
||||||
|
action: 'purchaseAsset-end ' + ddo.id
|
||||||
|
})
|
||||||
|
this.setState({ isLoading: false })
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('error', error.message)
|
||||||
|
this.setState({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: '',
|
error: `${error.message}. Sorry about that, can you try again?`
|
||||||
step: 99
|
})
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Purchase',
|
||||||
|
action: 'purchaseAsset-error ' + error.message
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private resetState = () =>
|
public render() {
|
||||||
this.setState({
|
const { ddo, file } = this.props
|
||||||
isLoading: true,
|
const { isLoading, error, step } = this.state
|
||||||
error: '',
|
const { isLogged } = this.context
|
||||||
step: 99
|
const { index, contentType, contentLength } = file
|
||||||
})
|
|
||||||
|
|
||||||
private purchaseAsset = async (ddo: DDO, index: number) => {
|
return (
|
||||||
this.resetState()
|
<div className={styles.fileWrap}>
|
||||||
|
<ul key={index} className={styles.file}>
|
||||||
|
{contentType || contentLength ? (
|
||||||
|
<>
|
||||||
|
<li>{cleanupContentType(contentType)}</li>
|
||||||
|
<li>
|
||||||
|
{contentLength && contentLength !== '0'
|
||||||
|
? filesize(contentLength)
|
||||||
|
: ''}
|
||||||
|
</li>
|
||||||
|
{/* <li>{encoding}</li> */}
|
||||||
|
{/* <li>{compression}</li> */}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<li className={styles.empty}>No file info available</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
|
||||||
ReactGA.event({
|
{isLoading ? (
|
||||||
category: 'Purchase',
|
<Spinner message={messages[step]} />
|
||||||
action: 'purchaseAsset-start ' + ddo.id
|
) : (
|
||||||
})
|
<Market.Consumer>
|
||||||
|
{market => (
|
||||||
|
<Button
|
||||||
|
primary
|
||||||
|
className={styles.buttonMain}
|
||||||
|
// weird 0 hack so TypeScript is happy
|
||||||
|
onClick={() => this.purchaseAsset(ddo, index || 0)}
|
||||||
|
disabled={!isLogged || !market.networkMatch}
|
||||||
|
name="Download"
|
||||||
|
>
|
||||||
|
Get file
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Market.Consumer>
|
||||||
|
)}
|
||||||
|
|
||||||
const { ocean } = this.context
|
{error !== '' && <div className={styles.error}>{error}</div>}
|
||||||
|
</div>
|
||||||
try {
|
)
|
||||||
const accounts = await ocean.accounts.list()
|
}
|
||||||
const service = ddo.findServiceByType('access')
|
|
||||||
|
|
||||||
const agreements = await ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
|
|
||||||
accounts[0].id
|
|
||||||
)
|
|
||||||
const agreement = agreements.find((element: any) => {
|
|
||||||
return element.did === ddo.id
|
|
||||||
})
|
|
||||||
|
|
||||||
let agreementId
|
|
||||||
|
|
||||||
if (agreement) {
|
|
||||||
;({ agreementId } = agreement)
|
|
||||||
} else {
|
|
||||||
agreementId = await ocean.assets
|
|
||||||
.order(ddo.id, service.index, accounts[0])
|
|
||||||
.next((step: number) => this.setState({ step }))
|
|
||||||
}
|
|
||||||
|
|
||||||
// manually add another step here for better UX
|
|
||||||
this.setState({ step: 4 })
|
|
||||||
|
|
||||||
const path = await ocean.assets.consume(
|
|
||||||
agreementId,
|
|
||||||
ddo.id,
|
|
||||||
service.index,
|
|
||||||
accounts[0],
|
|
||||||
'',
|
|
||||||
index
|
|
||||||
)
|
|
||||||
Logger.log('path', path)
|
|
||||||
ReactGA.event({
|
|
||||||
category: 'Purchase',
|
|
||||||
action: 'purchaseAsset-end ' + ddo.id
|
|
||||||
})
|
|
||||||
this.setState({ isLoading: false })
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error('error', error.message)
|
|
||||||
this.setState({
|
|
||||||
isLoading: false,
|
|
||||||
error: `${error.message}. Sorry about that, can you try again?`
|
|
||||||
})
|
|
||||||
ReactGA.event({
|
|
||||||
category: 'Purchase',
|
|
||||||
action: 'purchaseAsset-error ' + error.message
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const { ddo, file } = this.props
|
|
||||||
const { isLoading, error, step } = this.state
|
|
||||||
const { isLogged } = this.context
|
|
||||||
const { index, contentType, contentLength } = file
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={styles.fileWrap}>
|
|
||||||
<ul key={index} className={styles.file}>
|
|
||||||
{contentType || contentLength ? (
|
|
||||||
<>
|
|
||||||
<li>{cleanupContentType(contentType)}</li>
|
|
||||||
<li>
|
|
||||||
{contentLength && contentLength !== '0'
|
|
||||||
? filesize(contentLength)
|
|
||||||
: ''}
|
|
||||||
</li>
|
|
||||||
{/* <li>{encoding}</li> */}
|
|
||||||
{/* <li>{compression}</li> */}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<li className={styles.empty}>No file info available</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{isLoading ? (
|
|
||||||
<Spinner message={messages[step]} />
|
|
||||||
) : (
|
|
||||||
<Market.Consumer>
|
|
||||||
{market => (
|
|
||||||
<Button
|
|
||||||
primary
|
|
||||||
className={styles.buttonMain}
|
|
||||||
// weird 0 hack so TypeScript is happy
|
|
||||||
onClick={() =>
|
|
||||||
this.purchaseAsset(ddo, index || 0)
|
|
||||||
}
|
|
||||||
disabled={!isLogged || !market.networkMatch}
|
|
||||||
name="Download"
|
|
||||||
>
|
|
||||||
Get file
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Market.Consumer>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{error !== '' && <div className={styles.error}>{error}</div>}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async isLogged() {
|
localStorage.setItem('logType', 'BurnerWallet')
|
||||||
if (localStorage.getItem('seedphrase') !== null) {
|
const provider = new HDWalletProvider(mnemonic, nodeUri, 0, 1)
|
||||||
return true
|
this.web3 = new Web3(provider as any)
|
||||||
}
|
const accounts = await this.web3.eth.getAccounts()
|
||||||
return false
|
const balance = await this.web3.eth.getBalance(accounts[0])
|
||||||
}
|
|
||||||
|
|
||||||
public async startLogin() {
|
// fill with Ether if account balance is empty
|
||||||
let mnemonic
|
balance === '0' && (await requestFromFaucet(provider.getAddress(0)))
|
||||||
const isLogged = await this.isLogged()
|
}
|
||||||
|
|
||||||
if (isLogged) {
|
public async logout() {
|
||||||
mnemonic = localStorage.getItem('seedphrase')
|
// localStorage.removeItem('seedphrase')
|
||||||
} else {
|
localStorage.removeItem('logType')
|
||||||
mnemonic = bip39.generateMnemonic()
|
}
|
||||||
localStorage.setItem('seedphrase', mnemonic)
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem('logType', 'BurnerWallet')
|
public getProvider() {
|
||||||
const provider = new HDWalletProvider(mnemonic, nodeUri, 0, 1)
|
return this.web3
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,94 +4,94 @@ import { Market, User } from '.'
|
|||||||
import formPublish from '../data/form-publish.json'
|
import formPublish from '../data/form-publish.json'
|
||||||
|
|
||||||
const categories =
|
const categories =
|
||||||
(formPublish.steps[1].fields &&
|
(formPublish.steps[1].fields &&
|
||||||
formPublish.steps[1].fields.categories &&
|
formPublish.steps[1].fields.categories &&
|
||||||
formPublish.steps[1].fields.categories.options) ||
|
formPublish.steps[1].fields.categories.options) ||
|
||||||
[]
|
[]
|
||||||
|
|
||||||
interface MarketProviderProps {
|
interface MarketProviderProps {
|
||||||
ocean: Ocean
|
ocean: Ocean
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MarketProviderState {
|
interface MarketProviderState {
|
||||||
totalAssets: number
|
totalAssets: number
|
||||||
categories: string[]
|
categories: string[]
|
||||||
network: string
|
network: string
|
||||||
networkMatch: boolean
|
networkMatch: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class MarketProvider extends PureComponent<
|
export default class MarketProvider extends PureComponent<
|
||||||
MarketProviderProps,
|
MarketProviderProps,
|
||||||
MarketProviderState
|
MarketProviderState
|
||||||
> {
|
> {
|
||||||
public static contextType = User
|
public static contextType = User
|
||||||
|
|
||||||
public state = {
|
public state = {
|
||||||
totalAssets: 0,
|
totalAssets: 0,
|
||||||
categories,
|
categories,
|
||||||
network: 'Pacific',
|
network: 'Pacific',
|
||||||
networkMatch: false
|
networkMatch: false
|
||||||
|
}
|
||||||
|
|
||||||
|
public async componentDidMount() {
|
||||||
|
await this.checkCorrectUserNetwork()
|
||||||
|
}
|
||||||
|
|
||||||
|
public async componentDidUpdate(prevProps: any) {
|
||||||
|
// Using ocean prop instead of getting it from context to be able to compare.
|
||||||
|
// Cause there is no `prevContext`.
|
||||||
|
if (prevProps.ocean !== this.props.ocean) {
|
||||||
|
await this.getTotalAssets()
|
||||||
|
await this.getMarketNetwork()
|
||||||
|
await this.checkCorrectUserNetwork()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getTotalAssets = async () => {
|
||||||
|
const searchQuery = {
|
||||||
|
offset: 1,
|
||||||
|
page: 1,
|
||||||
|
query: {},
|
||||||
|
sort: {
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async componentDidMount() {
|
try {
|
||||||
await this.checkCorrectUserNetwork()
|
const { ocean } = this.props
|
||||||
|
const search = await ocean.assets.query(searchQuery)
|
||||||
|
this.setState({ totalAssets: search.totalResults })
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('Error', error.message)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async componentDidUpdate(prevProps: any) {
|
private getMarketNetwork = async () => {
|
||||||
// Using ocean prop instead of getting it from context to be able to compare.
|
try {
|
||||||
// Cause there is no `prevContext`.
|
const { ocean } = this.props
|
||||||
if (prevProps.ocean !== this.props.ocean) {
|
// Set desired network to whatever Brizo is running in
|
||||||
await this.getTotalAssets()
|
const brizo = await ocean.brizo.getVersionInfo()
|
||||||
await this.getMarketNetwork()
|
const network =
|
||||||
await this.checkCorrectUserNetwork()
|
brizo.network.charAt(0).toUpperCase() + brizo.network.slice(1)
|
||||||
}
|
this.setState({ network })
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('Error', error.message)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getTotalAssets = async () => {
|
private async checkCorrectUserNetwork() {
|
||||||
const searchQuery = {
|
if (this.context.network === this.state.network) {
|
||||||
offset: 1,
|
this.setState({ networkMatch: true })
|
||||||
page: 1,
|
} else {
|
||||||
query: {},
|
this.setState({ networkMatch: false })
|
||||||
sort: {
|
|
||||||
value: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { ocean } = this.props
|
|
||||||
const search = await ocean.assets.query(searchQuery)
|
|
||||||
this.setState({ totalAssets: search.totalResults })
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error('Error', error.message)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getMarketNetwork = async () => {
|
public render() {
|
||||||
try {
|
return (
|
||||||
const { ocean } = this.props
|
<Market.Provider value={this.state}>
|
||||||
// Set desired network to whatever Brizo is running in
|
{this.props.children}
|
||||||
const brizo = await ocean.brizo.getVersionInfo()
|
</Market.Provider>
|
||||||
const network =
|
)
|
||||||
brizo.network.charAt(0).toUpperCase() + brizo.network.slice(1)
|
}
|
||||||
this.setState({ network })
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error('Error', error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async checkCorrectUserNetwork() {
|
|
||||||
if (this.context.network === this.state.network) {
|
|
||||||
this.setState({ networkMatch: true })
|
|
||||||
} else {
|
|
||||||
this.setState({ networkMatch: false })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
return (
|
|
||||||
<Market.Provider value={this.state}>
|
|
||||||
{this.props.children}
|
|
||||||
</Market.Provider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,48 @@
|
|||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
|
|
||||||
export class MetamaskProvider {
|
export class MetamaskProvider {
|
||||||
private web3: Web3
|
private web3: Web3
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
// Default
|
// Default
|
||||||
this.web3 = null as any
|
this.web3 = null as any
|
||||||
// Modern dapp browsers
|
// Modern dapp browsers
|
||||||
if (window.ethereum) {
|
if (window.ethereum) {
|
||||||
this.web3 = new Web3(window.ethereum)
|
this.web3 = new Web3(window.ethereum)
|
||||||
}
|
|
||||||
// Legacy dapp browsers
|
|
||||||
else if (window.web3) {
|
|
||||||
this.web3 = new Web3(window.web3.currentProvider)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// Legacy dapp browsers
|
||||||
|
else if (window.web3) {
|
||||||
|
this.web3 = new Web3(window.web3.currentProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async isAvailable() {
|
public async isAvailable() {
|
||||||
return this.web3 !== null
|
return this.web3 !== null
|
||||||
}
|
}
|
||||||
|
|
||||||
public async isLogged() {
|
public async isLogged() {
|
||||||
if (this.web3 === null) return false
|
if (this.web3 === null) return false
|
||||||
if ((await this.web3.eth.getAccounts()).length > 0) {
|
if ((await this.web3.eth.getAccounts()).length > 0) {
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
public async startLogin() {
|
public async startLogin() {
|
||||||
try {
|
try {
|
||||||
await window.ethereum.enable()
|
await window.ethereum.enable()
|
||||||
localStorage.setItem('logType', 'Metamask')
|
localStorage.setItem('logType', 'Metamask')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async logout() {
|
public async logout() {
|
||||||
localStorage.removeItem('logType')
|
localStorage.removeItem('logType')
|
||||||
// reload page?
|
// reload page?
|
||||||
}
|
}
|
||||||
|
|
||||||
public getProvider() {
|
public getProvider() {
|
||||||
return this.web3
|
return this.web3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,227 +8,227 @@ 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'
|
||||||
|
|
||||||
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>
|
requestFromFaucet(account: string): Promise<FaucetResponse>
|
||||||
loginMetamask(): Promise<any>
|
loginMetamask(): Promise<any>
|
||||||
loginBurnerWallet(): Promise<any>
|
loginBurnerWallet(): Promise<any>
|
||||||
logoutBurnerWallet(): Promise<any>
|
logoutBurnerWallet(): Promise<any>
|
||||||
message: string
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class UserProvider extends PureComponent<{}, UserProviderState> {
|
export default class UserProvider extends PureComponent<{}, UserProviderState> {
|
||||||
private loginMetamask = async () => {
|
private loginMetamask = async () => {
|
||||||
const metamaskProvider = new MetamaskProvider()
|
const metamaskProvider = new MetamaskProvider()
|
||||||
await metamaskProvider.startLogin()
|
await metamaskProvider.startLogin()
|
||||||
const web3 = metamaskProvider.getProvider()
|
const web3 = metamaskProvider.getProvider()
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
isLogged: true,
|
isLogged: true,
|
||||||
isBurner: false,
|
isBurner: false,
|
||||||
web3
|
web3
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.loadOcean()
|
this.loadOcean()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private loginBurnerWallet = async () => {
|
private loginBurnerWallet = async () => {
|
||||||
const burnerwalletProvider = new BurnerWalletProvider()
|
const burnerwalletProvider = new BurnerWalletProvider()
|
||||||
await burnerwalletProvider.startLogin()
|
await burnerwalletProvider.startLogin()
|
||||||
const web3 = burnerwalletProvider.getProvider()
|
const web3 = burnerwalletProvider.getProvider()
|
||||||
this.setState(
|
this.setState(
|
||||||
{
|
{
|
||||||
isLogged: true,
|
isLogged: true,
|
||||||
isBurner: true,
|
isBurner: true,
|
||||||
web3
|
web3
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.loadOcean()
|
this.loadOcean()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private logoutBurnerWallet = async () => {
|
private logoutBurnerWallet = async () => {
|
||||||
const burnerwalletProvider = new BurnerWalletProvider()
|
const burnerwalletProvider = new BurnerWalletProvider()
|
||||||
await burnerwalletProvider.logout()
|
await burnerwalletProvider.logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
public state = {
|
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,
|
isLogged: false,
|
||||||
isBurner: false,
|
isBurner: false,
|
||||||
isWeb3Capable: Boolean(window.web3 || window.ethereum),
|
web3: DEFAULT_WEB3
|
||||||
isLoading: true,
|
},
|
||||||
balance: {
|
() => {
|
||||||
eth: 0,
|
this.loadOcean()
|
||||||
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 loadOcean = async () => {
|
||||||
|
const { ocean } = await provideOcean(this.state.web3)
|
||||||
|
this.setState({ ocean, isLoading: false }, () => {
|
||||||
|
this.initNetworkPoll()
|
||||||
|
this.initAccountsPoll()
|
||||||
|
this.fetchNetwork()
|
||||||
|
this.fetchAccounts()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private networkInterval: any = null
|
private bootstrap = async () => {
|
||||||
|
const logType = localStorage.getItem('logType')
|
||||||
|
const metamaskProvider = new MetamaskProvider()
|
||||||
|
|
||||||
public async componentDidMount() {
|
switch (logType) {
|
||||||
await this.bootstrap()
|
case 'Metamask':
|
||||||
}
|
if (
|
||||||
|
(await metamaskProvider.isAvailable()) &&
|
||||||
private initAccountsPoll() {
|
(await metamaskProvider.isLogged())
|
||||||
if (!this.accountsInterval) {
|
) {
|
||||||
this.accountsInterval = setInterval(
|
const web3 = metamaskProvider.getProvider()
|
||||||
this.fetchAccounts,
|
this.setState(
|
||||||
POLL_ACCOUNTS
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private initNetworkPoll() {
|
|
||||||
if (!this.networkInterval) {
|
|
||||||
this.networkInterval = setInterval(this.fetchNetwork, POLL_NETWORK)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadDefaultWeb3 = async () => {
|
|
||||||
this.setState(
|
|
||||||
{
|
{
|
||||||
isLogged: false,
|
isLogged: true,
|
||||||
isBurner: false,
|
web3
|
||||||
web3: DEFAULT_WEB3
|
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
this.loadOcean()
|
this.loadOcean()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
} else {
|
||||||
|
this.loadDefaultWeb3()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
|
case 'BurnerWallet':
|
||||||
|
this.loginBurnerWallet()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
this.loginBurnerWallet()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fetchAccounts = async () => {
|
private fetchAccounts = async () => {
|
||||||
const { ocean, isLogged } = this.state
|
const { ocean, isLogged } = this.state
|
||||||
|
|
||||||
if (isLogged) {
|
if (isLogged) {
|
||||||
let accounts
|
let accounts
|
||||||
|
|
||||||
// Modern dapp browsers
|
// Modern dapp browsers
|
||||||
if (window.ethereum && !isLogged) {
|
if (window.ethereum && !isLogged) {
|
||||||
// simply set to empty, and have user click a button somewhere
|
// simply set to empty, and have user click a button somewhere
|
||||||
// to initiate account unlocking
|
// to initiate account unlocking
|
||||||
accounts = []
|
accounts = []
|
||||||
|
|
||||||
// alternatively, automatically prompt for account unlocking
|
// alternatively, automatically prompt for account unlocking
|
||||||
// await this.unlockAccounts()
|
// await this.unlockAccounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
accounts = await ocean.accounts.list()
|
accounts = await ocean.accounts.list()
|
||||||
|
|
||||||
if (accounts.length > 0) {
|
if (accounts.length > 0) {
|
||||||
const account = await accounts[0].getId()
|
const account = await accounts[0].getId()
|
||||||
|
|
||||||
if (account !== this.state.account) {
|
if (account !== this.state.account) {
|
||||||
this.setState({
|
this.setState({
|
||||||
account,
|
account,
|
||||||
isLogged: true,
|
isLogged: true,
|
||||||
requestFromFaucet: () => requestFromFaucet(account)
|
requestFromFaucet: () => requestFromFaucet(account)
|
||||||
})
|
})
|
||||||
|
|
||||||
await this.fetchBalance(accounts[0])
|
await this.fetchBalance(accounts[0])
|
||||||
}
|
|
||||||
} else {
|
|
||||||
!isLogged && this.setState({ isLogged: false, account: '' })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
!isLogged && this.setState({ isLogged: false, account: '' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fetchBalance = async (account: Account) => {
|
private fetchBalance = async (account: Account) => {
|
||||||
const balance = await account.getBalance()
|
const balance = await account.getBalance()
|
||||||
const { eth, ocn } = balance
|
const { eth, ocn } = balance
|
||||||
if (eth !== this.state.balance.eth || ocn !== this.state.balance.ocn) {
|
if (eth !== this.state.balance.eth || ocn !== this.state.balance.ocn) {
|
||||||
this.setState({ balance: { eth, ocn } })
|
this.setState({ balance: { eth, ocn } })
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fetchNetwork = async () => {
|
private fetchNetwork = async () => {
|
||||||
const { ocean } = this.state
|
const { ocean } = this.state
|
||||||
let network = 'Unknown'
|
let network = 'Unknown'
|
||||||
if (ocean.keeper) {
|
if (ocean.keeper) {
|
||||||
network = await ocean.keeper.getNetworkName()
|
network = await ocean.keeper.getNetworkName()
|
||||||
}
|
|
||||||
network !== this.state.network && this.setState({ network })
|
|
||||||
}
|
}
|
||||||
|
network !== this.state.network && this.setState({ network })
|
||||||
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<User.Provider value={this.state}>
|
<User.Provider value={this.state}>
|
||||||
<MarketProvider ocean={this.state.ocean}>
|
<MarketProvider ocean={this.state.ocean}>
|
||||||
{this.props.children}
|
<NetworkSwitcher />
|
||||||
</MarketProvider>
|
{this.props.children}
|
||||||
</User.Provider>
|
</MarketProvider>
|
||||||
)
|
</User.Provider>
|
||||||
}
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,33 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
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: () => {
|
requestFromFaucet: () => {
|
||||||
/* empty */
|
/* empty */
|
||||||
},
|
},
|
||||||
loginMetamask: () => {
|
loginMetamask: () => {
|
||||||
/* empty */
|
/* empty */
|
||||||
},
|
},
|
||||||
loginBurnerWallet: () => {
|
loginBurnerWallet: () => {
|
||||||
/* empty */
|
/* empty */
|
||||||
},
|
},
|
||||||
message: ''
|
message: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
export const Market = React.createContext({
|
export const Market = React.createContext({
|
||||||
totalAssets: 0,
|
totalAssets: 0,
|
||||||
categories: [''],
|
categories: [''],
|
||||||
network: '',
|
network: '',
|
||||||
networkMatch: false
|
networkMatch: false
|
||||||
})
|
})
|
||||||
|
@ -5,23 +5,22 @@ import App from './App'
|
|||||||
import * as serviceWorker from './serviceWorker'
|
import * as serviceWorker from './serviceWorker'
|
||||||
|
|
||||||
function renderToDOM() {
|
function renderToDOM() {
|
||||||
const root = document.getElementById('root')
|
const root = document.getElementById('root')
|
||||||
|
|
||||||
if (root !== null) {
|
if (root !== null) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
<App />
|
<App />
|
||||||
</UserProvider>,
|
</UserProvider>,
|
||||||
root
|
root
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { renderToDOM }
|
export { renderToDOM }
|
||||||
|
|
||||||
renderToDOM()
|
renderToDOM()
|
||||||
|
|
||||||
|
|
||||||
// If you want your app to work offline and load faster, you can change
|
// If you want your app to work offline and load faster, you can change
|
||||||
// unregister() to register() below. Note this comes with some pitfalls.
|
// unregister() to register() below. Note this comes with some pitfalls.
|
||||||
// Learn more about service workers: http://bit.ly/CRA-PWA
|
// Learn more about service workers: http://bit.ly/CRA-PWA
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import { MetaData } from '@oceanprotocol/squid'
|
import { MetaData } from '@oceanprotocol/squid'
|
||||||
|
|
||||||
const AssetModel: MetaData = {
|
const AssetModel: MetaData = {
|
||||||
// OEP-08 Attributes
|
// OEP-08 Attributes
|
||||||
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||||
main: {
|
main: {
|
||||||
type: 'dataset',
|
type: 'dataset',
|
||||||
name: '',
|
name: '',
|
||||||
dateCreated: '',
|
dateCreated: '',
|
||||||
author: '',
|
author: '',
|
||||||
license: '',
|
license: '',
|
||||||
price: '',
|
price: '',
|
||||||
files: []
|
files: []
|
||||||
},
|
},
|
||||||
additionalInformation: {
|
additionalInformation: {
|
||||||
description: '',
|
description: '',
|
||||||
copyrightHolder: '',
|
copyrightHolder: '',
|
||||||
categories: []
|
categories: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AssetModel
|
export default AssetModel
|
||||||
|
@ -10,48 +10,48 @@ const history = createMemoryHistory()
|
|||||||
const location = createLocation('/faucet')
|
const location = createLocation('/faucet')
|
||||||
|
|
||||||
const setup = () => {
|
const setup = () => {
|
||||||
const utils = render(
|
const utils = render(
|
||||||
<User.Provider value={userMockConnected}>
|
<User.Provider value={userMockConnected}>
|
||||||
<Market.Provider
|
<Market.Provider
|
||||||
value={{
|
value={{
|
||||||
network: 'pacific',
|
network: 'pacific',
|
||||||
totalAssets: 100,
|
totalAssets: 100,
|
||||||
categories: [''],
|
categories: [''],
|
||||||
networkMatch: true
|
networkMatch: true
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<Faucet
|
<Faucet
|
||||||
history={history}
|
history={history}
|
||||||
location={location}
|
location={location}
|
||||||
match={{ params: '', path: '', url: '', isExact: true }}
|
match={{ params: '', path: '', url: '', isExact: true }}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</Market.Provider>
|
</Market.Provider>
|
||||||
</User.Provider>
|
</User.Provider>
|
||||||
)
|
)
|
||||||
const button = utils.getByText('Request ETH')
|
const button = utils.getByText('Request ETH')
|
||||||
const { container } = utils
|
const { container } = utils
|
||||||
return { button, container, ...utils }
|
return { button, container, ...utils }
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Faucet', () => {
|
describe('Faucet', () => {
|
||||||
it('renders without crashing', () => {
|
it('renders without crashing', () => {
|
||||||
const { container } = setup()
|
const { container } = setup()
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows actions when connected', () => {
|
it('shows actions when connected', () => {
|
||||||
const { button } = setup()
|
const { button } = setup()
|
||||||
expect(button).toBeInTheDocument()
|
expect(button).toBeInTheDocument()
|
||||||
expect(button).not.toHaveAttribute('disabled')
|
expect(button).not.toHaveAttribute('disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('fires requestFromFaucet', async () => {
|
it('fires requestFromFaucet', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
const { button } = setup()
|
const { button } = setup()
|
||||||
fireEvent.click(button)
|
fireEvent.click(button)
|
||||||
})
|
|
||||||
expect(userMockConnected.requestFromFaucet).toHaveBeenCalledTimes(1)
|
|
||||||
})
|
})
|
||||||
|
expect(userMockConnected.requestFromFaucet).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -13,153 +13,152 @@ import Content from '../components/atoms/Content'
|
|||||||
import withTracker from '../hoc/withTracker'
|
import withTracker from '../hoc/withTracker'
|
||||||
|
|
||||||
interface SearchProps {
|
interface SearchProps {
|
||||||
location: Location
|
location: Location
|
||||||
history: History
|
history: History
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SearchState {
|
interface SearchState {
|
||||||
results: any[]
|
results: any[]
|
||||||
totalResults: number
|
totalResults: number
|
||||||
offset: number
|
offset: number
|
||||||
totalPages: number
|
totalPages: number
|
||||||
currentPage: number
|
currentPage: number
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
searchTerm: string
|
searchTerm: string
|
||||||
searchCategories: string
|
searchCategories: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class Search extends PureComponent<SearchProps, SearchState> {
|
class Search extends PureComponent<SearchProps, SearchState> {
|
||||||
public static contextType = User
|
public static contextType = User
|
||||||
|
|
||||||
public state = {
|
public state = {
|
||||||
results: [],
|
results: [],
|
||||||
totalResults: 0,
|
totalResults: 0,
|
||||||
offset: 25,
|
offset: 25,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
searchCategories: ''
|
searchCategories: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
public async componentDidMount() {
|
||||||
|
const { search } = this.props.location
|
||||||
|
const { text, page, categories } = queryString.parse(search)
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
await this.setState({
|
||||||
|
searchTerm: decodeURIComponent(`${text}`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public async componentDidMount() {
|
if (categories) {
|
||||||
const { search } = this.props.location
|
await this.setState({
|
||||||
const { text, page, categories } = queryString.parse(search)
|
searchCategories: decodeURIComponent(`${categories}`)
|
||||||
|
})
|
||||||
if (text) {
|
|
||||||
await this.setState({
|
|
||||||
searchTerm: decodeURIComponent(`${text}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (categories) {
|
|
||||||
await this.setState({
|
|
||||||
searchCategories: decodeURIComponent(`${categories}`)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// switch to respective page if query string is present
|
|
||||||
if (page) {
|
|
||||||
const currentPage = Number(page)
|
|
||||||
await this.setState({ currentPage })
|
|
||||||
}
|
|
||||||
|
|
||||||
this.searchAssets()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private searchAssets = async () => {
|
// switch to respective page if query string is present
|
||||||
const { ocean } = this.context
|
if (page) {
|
||||||
const { offset, currentPage, searchTerm, searchCategories } = this.state
|
const currentPage = Number(page)
|
||||||
|
await this.setState({ currentPage })
|
||||||
const queryValues =
|
|
||||||
searchCategories !== '' && searchTerm !== ''
|
|
||||||
? { text: [searchTerm], categories: [searchCategories] }
|
|
||||||
: searchCategories !== '' && searchTerm === ''
|
|
||||||
? { categories: [searchCategories] }
|
|
||||||
: { text: [searchTerm] }
|
|
||||||
|
|
||||||
const searchQuery = {
|
|
||||||
offset,
|
|
||||||
page: currentPage,
|
|
||||||
query: {
|
|
||||||
...queryValues
|
|
||||||
},
|
|
||||||
sort: {
|
|
||||||
created: -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const search = await ocean.assets.query(searchQuery)
|
|
||||||
this.setState({
|
|
||||||
results: search.results,
|
|
||||||
totalResults: search.totalResults,
|
|
||||||
totalPages: search.totalPages,
|
|
||||||
isLoading: false
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error(error.message)
|
|
||||||
this.setState({ isLoading: false })
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private handlePageClick = async (data: { selected: number }) => {
|
this.searchAssets()
|
||||||
// react-pagination starts counting at 0, we start at 1
|
}
|
||||||
const toPage = data.selected + 1
|
|
||||||
|
|
||||||
this.props.history.push({
|
private searchAssets = async () => {
|
||||||
pathname: this.props.location.pathname,
|
const { ocean } = this.context
|
||||||
search: `?text=${this.state.searchTerm}&page=${toPage}`
|
const { offset, currentPage, searchTerm, searchCategories } = this.state
|
||||||
})
|
|
||||||
|
|
||||||
await this.setState({ currentPage: toPage, isLoading: true })
|
const queryValues =
|
||||||
await this.searchAssets()
|
searchCategories !== '' && searchTerm !== ''
|
||||||
|
? { text: [searchTerm], categories: [searchCategories] }
|
||||||
|
: searchCategories !== '' && searchTerm === ''
|
||||||
|
? { categories: [searchCategories] }
|
||||||
|
: { text: [searchTerm] }
|
||||||
|
|
||||||
|
const searchQuery = {
|
||||||
|
offset,
|
||||||
|
page: currentPage,
|
||||||
|
query: {
|
||||||
|
...queryValues
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
created: -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public renderResults = () =>
|
try {
|
||||||
this.state.isLoading ? (
|
const search = await ocean.assets.query(searchQuery)
|
||||||
<Spinner message="Searching..." />
|
this.setState({
|
||||||
) : this.state.results && this.state.results.length ? (
|
results: search.results,
|
||||||
<div className={styles.results}>
|
totalResults: search.totalResults,
|
||||||
{this.state.results.map((asset: any) => (
|
totalPages: search.totalPages,
|
||||||
<AssetTeaser key={asset.id} asset={asset} />
|
isLoading: false
|
||||||
))}
|
})
|
||||||
</div>
|
} catch (error) {
|
||||||
) : (
|
Logger.error(error.message)
|
||||||
<div className={styles.empty}>
|
this.setState({ isLoading: false })
|
||||||
<p>No Data Sets Found.</p>
|
|
||||||
<Link to="/publish">+ Publish A Data Set</Link>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
public render() {
|
|
||||||
const { totalResults, totalPages, currentPage } = this.state
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Route title="Search" wide>
|
|
||||||
<Content wide>
|
|
||||||
{!this.state.isLoading && (
|
|
||||||
<h2 className={styles.resultsTitle}>
|
|
||||||
{totalResults} results for{' '}
|
|
||||||
<span>
|
|
||||||
{decodeURIComponent(
|
|
||||||
this.state.searchTerm ||
|
|
||||||
this.state.searchCategories
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</h2>
|
|
||||||
)}
|
|
||||||
{this.renderResults()}
|
|
||||||
|
|
||||||
<Pagination
|
|
||||||
totalPages={totalPages}
|
|
||||||
currentPage={currentPage}
|
|
||||||
handlePageClick={this.handlePageClick}
|
|
||||||
/>
|
|
||||||
</Content>
|
|
||||||
</Route>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private handlePageClick = async (data: { selected: number }) => {
|
||||||
|
// react-pagination starts counting at 0, we start at 1
|
||||||
|
const toPage = data.selected + 1
|
||||||
|
|
||||||
|
this.props.history.push({
|
||||||
|
pathname: this.props.location.pathname,
|
||||||
|
search: `?text=${this.state.searchTerm}&page=${toPage}`
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.setState({ currentPage: toPage, isLoading: true })
|
||||||
|
await this.searchAssets()
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderResults = () =>
|
||||||
|
this.state.isLoading ? (
|
||||||
|
<Spinner message="Searching..." />
|
||||||
|
) : this.state.results && this.state.results.length ? (
|
||||||
|
<div className={styles.results}>
|
||||||
|
{this.state.results.map((asset: any) => (
|
||||||
|
<AssetTeaser key={asset.id} asset={asset} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className={styles.empty}>
|
||||||
|
<p>No Data Sets Found.</p>
|
||||||
|
<Link to="/publish">+ Publish A Data Set</Link>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { totalResults, totalPages, currentPage } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Route title="Search" wide>
|
||||||
|
<Content wide>
|
||||||
|
{!this.state.isLoading && (
|
||||||
|
<h2 className={styles.resultsTitle}>
|
||||||
|
{totalResults} results for{' '}
|
||||||
|
<span>
|
||||||
|
{decodeURIComponent(
|
||||||
|
this.state.searchTerm || this.state.searchCategories
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
)}
|
||||||
|
{this.renderResults()}
|
||||||
|
|
||||||
|
<Pagination
|
||||||
|
totalPages={totalPages}
|
||||||
|
currentPage={currentPage}
|
||||||
|
handlePageClick={this.handlePageClick}
|
||||||
|
/>
|
||||||
|
</Content>
|
||||||
|
</Route>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withTracker(Search)
|
export default withTracker(Search)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user