1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Merge branch 'main' into feature/compute

This commit is contained in:
Matthias Kretschmann 2021-04-13 15:14:59 +02:00
commit faa6a8329a
Signed by: m
GPG Key ID: 606EEEF3C479A91F
27 changed files with 602 additions and 66 deletions

View File

@ -1,4 +1,5 @@
# Network, possible values: development, pacific, rinkeby, mainnet
# Default network, possible values:
# "development", "ropsten", "rinkeby", "mainnet", "polygon"
GATSBY_NETWORK="rinkeby"
#GATSBY_INFURA_PROJECT_ID="xxx"

317
package-lock.json generated
View File

@ -3620,27 +3620,321 @@
"integrity": "sha512-j4PEZSVtKSqxDYMVh/hd5vk088Bg6a6QkrUMTXN9Q6OIFAMfHM235f1AxaakNrEyK0FKMD908KuJEdfFLRn9Hw=="
},
"@oceanprotocol/contracts": {
"version": "0.5.10",
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.10.tgz",
"integrity": "sha512-6GrBk1jy+zxjDjh2SPra06etrqdp8CB6RaZaTq2OQpK8dA2Dq91hqCbj+6eb21MlU8bDY3/atnxax9rgPgsxkA=="
"version": "0.5.13",
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.13.tgz",
"integrity": "sha512-0dasqU7PL8xZOxvn6ID2IJ6TgQZbkcwtZqiMiYvtsv9+fQr/n13qXYXwkmNEjQb3YL4IeSVUnHehk5KpGRPFWA=="
},
"@oceanprotocol/lib": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.12.1.tgz",
"integrity": "sha512-Cw4d4Di6GnL1gfZcYqemnKh1Agpc66AemIJANfbJpO08KkgiLEZhhMYsYQZzha+zQD9Jr4ZuzE/ZlYDr6S0o6w==",
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.13.0.tgz",
"integrity": "sha512-+LoN16bo1hcqfxsxLV22ZEbObdif0RJXg5GlndlF/VQGNVrSm+XYxUp+si5HCWa8sBeYH/hOSQRnrD8YXnyWrw==",
"requires": {
"@ethereum-navigator/navigator": "^0.5.2",
"@oceanprotocol/contracts": "^0.5.10",
"@types/crypto-js": "^4.0.1",
"cross-fetch": "^3.1.2",
"crypto-js": "^4.0.0",
"decimal.js": "^10.2.1",
"fs": "0.0.1-security",
"lzma": "^2.3.2",
"node-fetch": "^2.6.1",
"node-abort-controller": "^1.2.0",
"save-file": "^2.3.1",
"uuid": "^8.3.2",
"web3": "^1.3.4",
"web3-eth-contract": "^1.3.4"
"web3": "^1.3.5",
"web3-eth-contract": "^1.3.5"
},
"dependencies": {
"@types/node": {
"version": "12.20.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.7.tgz",
"integrity": "sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA=="
},
"cross-fetch": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz",
"integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==",
"requires": {
"node-fetch": "2.6.1"
}
},
"eth-lib": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz",
"integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==",
"requires": {
"bn.js": "^4.11.6",
"elliptic": "^6.4.0",
"xhr-request-promise": "^0.1.2"
}
},
"web3": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3/-/web3-1.3.5.tgz",
"integrity": "sha512-UyQW/MT5EIGBrXPCh/FDIaD7RtJTn5/rJUNw2FOglp0qoXnCQHNKvntiR1ylztk05fYxIF6UgsC76IrazlKJjw==",
"requires": {
"web3-bzz": "1.3.5",
"web3-core": "1.3.5",
"web3-eth": "1.3.5",
"web3-eth-personal": "1.3.5",
"web3-net": "1.3.5",
"web3-shh": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-bzz": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.3.5.tgz",
"integrity": "sha512-XiEUAbB1uKm/agqfwBsCW8fbw+sma85TfwuDpdcy591vinVk0S9TfWgLxro6v1KJ6nSELySIbKGbAJbh2GSyxw==",
"requires": {
"@types/node": "^12.12.6",
"got": "9.6.0",
"swarm-js": "^0.1.40",
"underscore": "1.9.1"
}
},
"web3-core": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.3.5.tgz",
"integrity": "sha512-VQjTvnGTqJwDwjKEHSApea3RmgtFGLDSJ6bqrOyHROYNyTyKYjFQ/drG9zs3rjDkND9mgh8foI1ty37Qua3QCQ==",
"requires": {
"@types/bn.js": "^4.11.5",
"@types/node": "^12.12.6",
"bignumber.js": "^9.0.0",
"web3-core-helpers": "1.3.5",
"web3-core-method": "1.3.5",
"web3-core-requestmanager": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-core-helpers": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.3.5.tgz",
"integrity": "sha512-HYh3ix5FjysgT0jyzD8s/X5ym0b4BGU7I2QtuBiydMnE0mQEWy7GcT9XKpTySA8FTOHHIAQYvQS07DN/ky3UzA==",
"requires": {
"underscore": "1.9.1",
"web3-eth-iban": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-core-method": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.3.5.tgz",
"integrity": "sha512-hCbmgQ+At6OTuaNGAdjXMsCr4eUCmp9yGKSuaB5HdkNVDpqFso4HHjVxcjNrTyJp3OZnyjKBzQzK1ZWLpLl84Q==",
"requires": {
"@ethersproject/transactions": "^5.0.0-beta.135",
"underscore": "1.9.1",
"web3-core-helpers": "1.3.5",
"web3-core-promievent": "1.3.5",
"web3-core-subscriptions": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-core-promievent": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.3.5.tgz",
"integrity": "sha512-K0j8x3ZJr0eAyNvyUCxOUsSTd4hco0/9nxxlyOuijcsa6YV8l9NL6eqhniWbSyxCJT8ka5Mb7yAiUZe69EDLBQ==",
"requires": {
"eventemitter3": "4.0.4"
}
},
"web3-core-requestmanager": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.3.5.tgz",
"integrity": "sha512-9l294U3Ga8qmvv8E37BqjQREfMs+kFnkU3PY28g9DZGYzKvl3V1dgDYqxyrOBdCFhc7rNSpHdgC4PrVHjouspg==",
"requires": {
"underscore": "1.9.1",
"util": "^0.12.0",
"web3-core-helpers": "1.3.5",
"web3-providers-http": "1.3.5",
"web3-providers-ipc": "1.3.5",
"web3-providers-ws": "1.3.5"
}
},
"web3-core-subscriptions": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.3.5.tgz",
"integrity": "sha512-6mtXdaEB1V1zKLqYBq7RF2W75AK5ZJNGpW6QYC7Zvbku7zq1ZlgaUkJo88JKMWJ7etfaHaYqQ/7VveHk5sQynA==",
"requires": {
"eventemitter3": "4.0.4",
"underscore": "1.9.1",
"web3-core-helpers": "1.3.5"
}
},
"web3-eth": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.3.5.tgz",
"integrity": "sha512-5qqDPMMD+D0xRqOV2ePU2G7/uQmhn0FgCEhFzKDMHrssDQJyQLW/VgfA0NLn64lWnuUrGnQStGvNxrWf7MgsfA==",
"requires": {
"underscore": "1.9.1",
"web3-core": "1.3.5",
"web3-core-helpers": "1.3.5",
"web3-core-method": "1.3.5",
"web3-core-subscriptions": "1.3.5",
"web3-eth-abi": "1.3.5",
"web3-eth-accounts": "1.3.5",
"web3-eth-contract": "1.3.5",
"web3-eth-ens": "1.3.5",
"web3-eth-iban": "1.3.5",
"web3-eth-personal": "1.3.5",
"web3-net": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-eth-abi": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.3.5.tgz",
"integrity": "sha512-bkbG2v/mOW5DH6rF/SEgqunusjYoEi2IBw+fkmD3rzWDaEY7+/i1xY94AeO257d06QMgld75GtV/N+aEs7A6vQ==",
"requires": {
"@ethersproject/abi": "5.0.7",
"underscore": "1.9.1",
"web3-utils": "1.3.5"
}
},
"web3-eth-accounts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.3.5.tgz",
"integrity": "sha512-r3WOR21rgm6Cd6OFnifr3Tizdm5K+g2TsSOPySwX4FrgLrYDL6ck4zr5VXUPz+llpSExb/JztpE8pqEHr3U2NA==",
"requires": {
"crypto-browserify": "3.12.0",
"eth-lib": "0.2.8",
"ethereumjs-common": "^1.3.2",
"ethereumjs-tx": "^2.1.1",
"scrypt-js": "^3.0.1",
"underscore": "1.9.1",
"uuid": "3.3.2",
"web3-core": "1.3.5",
"web3-core-helpers": "1.3.5",
"web3-core-method": "1.3.5",
"web3-utils": "1.3.5"
},
"dependencies": {
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
}
}
},
"web3-eth-contract": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.3.5.tgz",
"integrity": "sha512-WfGVeQquN3D7Qm+KEIN9EI7yrm/fL2V9Y4+YhDWiKA/ns1pX1LYcEWojTOnBXCnPF3tcvoKKL+KBxXg1iKm38A==",
"requires": {
"@types/bn.js": "^4.11.5",
"underscore": "1.9.1",
"web3-core": "1.3.5",
"web3-core-helpers": "1.3.5",
"web3-core-method": "1.3.5",
"web3-core-promievent": "1.3.5",
"web3-core-subscriptions": "1.3.5",
"web3-eth-abi": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-eth-ens": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.3.5.tgz",
"integrity": "sha512-5bkpFTXV18CvaVP8kCbLZZm2r1TWUv9AsXH+80yz8bTZulUGvXsBMRfK6e5nfEr2Yv59xlIXCFoalmmySI9EJw==",
"requires": {
"content-hash": "^2.5.2",
"eth-ens-namehash": "2.0.8",
"underscore": "1.9.1",
"web3-core": "1.3.5",
"web3-core-helpers": "1.3.5",
"web3-core-promievent": "1.3.5",
"web3-eth-abi": "1.3.5",
"web3-eth-contract": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-eth-iban": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.3.5.tgz",
"integrity": "sha512-x+BI/d2Vt0J1cKK8eFd4W0f1TDjgEOYCwiViTb28lLE+tqrgyPqWDA+l6UlKYLF/yMFX3Dym4ofcCOtgcn4q4g==",
"requires": {
"bn.js": "^4.11.9",
"web3-utils": "1.3.5"
}
},
"web3-eth-personal": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.3.5.tgz",
"integrity": "sha512-xELQHNZ8p3VoO1582ghCaq+Bx7pSkOOalc6/ACOCGtHDMelqgVejrmSIZGScYl+k0HzngmQAzURZWQocaoGM1g==",
"requires": {
"@types/node": "^12.12.6",
"web3-core": "1.3.5",
"web3-core-helpers": "1.3.5",
"web3-core-method": "1.3.5",
"web3-net": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-net": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.3.5.tgz",
"integrity": "sha512-usbFbuUpKK8s7jPLGoUzi/WpNnefGFPTj948aJv8BZ04UQA4L/XS5NNkkhk358zNMmhGfEFW8wrWy+0Oy0njtA==",
"requires": {
"web3-core": "1.3.5",
"web3-core-method": "1.3.5",
"web3-utils": "1.3.5"
}
},
"web3-providers-http": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.3.5.tgz",
"integrity": "sha512-ZQOmceFjcajEZdiuqciXjijwIYWNmEJ1oxMtbrwB2eGxHRCMXEH2xGRUZuhOFNF88yQC/VXVi14yvYg5ZlFJlA==",
"requires": {
"web3-core-helpers": "1.3.5",
"xhr2-cookies": "1.1.0"
}
},
"web3-providers-ipc": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.3.5.tgz",
"integrity": "sha512-cbZOeb/sALiHjzMolJjIyHla/J5wdL2JKUtRO66Nh/uLALBCpU8JUgzNvpAdJ1ae3+A33+EdFStdzuDYHKtQew==",
"requires": {
"oboe": "2.1.5",
"underscore": "1.9.1",
"web3-core-helpers": "1.3.5"
}
},
"web3-providers-ws": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.3.5.tgz",
"integrity": "sha512-zeZ4LMvKhYaJBDCqA//Bzgp4r/T0tNq5U/xvN0axA4YflzF7yqlsbzGwCkcZYDbrUaK3Ltl2uOmvwjbWALOZ1A==",
"requires": {
"eventemitter3": "4.0.4",
"underscore": "1.9.1",
"web3-core-helpers": "1.3.5",
"websocket": "^1.0.32"
}
},
"web3-shh": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.3.5.tgz",
"integrity": "sha512-aRwzCduXvuGVslLL/Y15VcOHa70Qr2kxZI7UwOzQVhaaOdxuRRvo3AK/cmyln1Tsd54/n93Yk8I3qg5I2+6alw==",
"requires": {
"web3-core": "1.3.5",
"web3-core-method": "1.3.5",
"web3-core-subscriptions": "1.3.5",
"web3-net": "1.3.5"
}
},
"web3-utils": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz",
"integrity": "sha512-5apMRm8ElYjI/92GHqijmaLC+s+d5lgjpjHft+rJSs/dsnX8I8tQreqev0dmU+wzU+2EEe4Sx9a/OwGWHhQv3A==",
"requires": {
"bn.js": "^4.11.9",
"eth-lib": "0.2.8",
"ethereum-bloom-filters": "^1.0.6",
"ethjs-unit": "0.1.6",
"number-to-bn": "1.7.0",
"randombytes": "^2.1.0",
"underscore": "1.9.1",
"utf8": "3.0.0"
}
}
}
},
"@oceanprotocol/typographies": {
@ -27202,6 +27496,11 @@
}
}
},
"node-abort-controller": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-1.2.1.tgz",
"integrity": "sha512-79PYeJuj6S9+yOHirR0JBLFOgjB6sQCir10uN6xRx25iD+ZD4ULqgRn3MwWBRaQGB0vEgReJzWwJo42T1R6YbQ=="
},
"node-addon-api": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz",

View File

@ -27,7 +27,7 @@
"@coingecko/cryptoformat": "^0.4.2",
"@loadable/component": "^5.14.1",
"@oceanprotocol/art": "^3.0.0",
"@oceanprotocol/lib": "^0.12.1",
"@oceanprotocol/lib": "^0.13.0",
"@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^3.0.3",
"@sindresorhus/slugify": "^1.0.0",

View File

@ -1,14 +1,16 @@
import React, { ReactElement } from 'react'
import { graphql, PageProps, useStaticQuery } from 'gatsby'
import Alert from './atoms/Alert'
import Footer from './organisms/Footer'
import Header from './organisms/Header'
import Styles from '../global/Styles'
import styles from './App.module.css'
import { useSiteMetadata } from '../hooks/useSiteMetadata'
import Alert from './atoms/Alert'
import { graphql, PageProps, useStaticQuery } from 'gatsby'
import { useAccountPurgatory } from '../hooks/useAccountPurgatory'
import AnnouncementBanner from './molecules/AnnouncementBanner'
import { useWeb3 } from '../providers/Web3'
import { useSiteMetadata } from '../hooks/useSiteMetadata'
import { useAccountPurgatory } from '../hooks/useAccountPurgatory'
import NetworkBanner from './molecules/NetworkBanner'
import styles from './App.module.css'
import AnnouncementBanner from './atoms/AnnouncementBanner'
import { useGraphSyncStatus } from '../hooks/useGraphSyncStatus'
const contentQuery = graphql`
query AppQuery {
@ -39,15 +41,25 @@ export default function App({
const { warning } = useSiteMetadata()
const { accountId } = useWeb3()
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
const { isGraphSynced, blockHead, blockGraph } = useGraphSyncStatus()
return (
<Styles>
<div className={styles.app}>
{!location.pathname.includes('/asset/did') && <AnnouncementBanner />}
{!isGraphSynced && (
<AnnouncementBanner
text={`The data for this network has only synced to Ethereum block ${blockGraph} (out of ${blockHead}). Please check back soon.`}
state="error"
/>
)}
{!location.pathname.includes('/asset/did') && <NetworkBanner />}
<Header />
{(props as PageProps).uri === '/' && (
<Alert text={warning.main} state="info" />
)}
{isInPurgatory && (
<Alert
title={purgatory.title}

View File

@ -5,6 +5,21 @@
background-color: var(--background-content);
}
.banner.error {
background-color: var(--brand-alert-red);
color: var(--brand-white);
}
.banner.warning {
background-color: var(--brand-alert-yellow);
color: var(--brand-white);
}
.banner.success {
background-color: var(--brand-alert-green);
color: var(--brand-white);
}
.banner > div {
display: inline-block;
}

View File

@ -0,0 +1,44 @@
import React, { ReactElement } from 'react'
import classNames from 'classnames/bind'
import Markdown from '../atoms/Markdown'
import Button from '../atoms/Button'
import styles from './AnnouncementBanner.module.css'
const cx = classNames.bind(styles)
export interface AnnouncementAction {
name: string
style?: string
handleAction: () => void
}
export default function AnnouncementBanner({
text,
action,
state,
className
}: {
text: string
action?: AnnouncementAction
state?: 'success' | 'warning' | 'error'
className?: string
}): ReactElement {
const styleClasses = cx({
banner: true,
error: state === 'error',
warning: state === 'warning',
success: state === 'success',
[className]: className
})
return (
<div className={styleClasses}>
{text && <Markdown className={styles.text} text={text} />}
{action && (
<Button style="text" size="small" onClick={action.handleAction}>
{action.name}
</Button>
)}
</div>
)
}

View File

@ -1,7 +1,7 @@
import React, { ReactElement, ReactNode, useEffect, useState } from 'react'
import { ReactComponent as External } from '../../images/external.svg'
import styles from './ExplorerLink.module.css'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { ConfigHelperConfig } from '@oceanprotocol/lib'
import { useOcean } from '../../providers/Ocean'
export default function ExplorerLink({

View File

@ -1,11 +1,10 @@
import { useUserPreferences } from '../../providers/UserPreferences'
import React, { ReactElement, useEffect, useState } from 'react'
import Table from '../atoms/Table'
import { DDO, Logger } from '@oceanprotocol/lib'
import { DDO, Logger, ConfigHelperConfig } from '@oceanprotocol/lib'
import { useOcean } from '../../providers/Ocean'
import Price from '../atoms/Price'
import Tooltip from '../atoms/Tooltip'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import AssetTitle from './AssetListTitle'
import { queryMetadata } from '../../utils/aquarius'
import axios, { CancelToken } from 'axios'

View File

@ -19,7 +19,7 @@ export default function MarketStats(): ReactElement {
const [totalValueLocked, setTotalValueLocked] = useState<string>()
const [totalOceanLiquidity, setTotalOceanLiquidity] = useState<string>()
const [poolCount, setPoolCount] = useState<number>()
const { data } = useQuery(getTotalPoolsValues)
const { data } = useQuery(getTotalPoolsValues, { pollInterval: 20000 })
useEffect(() => {
if (!data || !data.poolFactories || data.poolFactories.length === 0) return

View File

@ -1,21 +1,15 @@
import React, { ReactElement, useEffect, useState } from 'react'
import styles from './AnnouncementBanner.module.css'
import Markdown from '../atoms/Markdown'
import { useWeb3 } from '../../providers/Web3'
import { addCustomNetwork, NetworkObject } from '../../utils/web3'
import { getOceanConfig } from '../../utils/ocean'
import { getProviderInfo } from 'web3modal'
import { useOcean } from '../../providers/Ocean'
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
import Button from '../atoms/Button'
import AnnouncementBanner, {
AnnouncementAction
} from '../atoms/AnnouncementBanner'
export interface AnnouncementAction {
name: string
style?: string
handleAction: () => void
}
const network: NetworkObject = {
const networkMatic: NetworkObject = {
chainId: 137,
name: 'Matic Network',
urlList: [
@ -24,7 +18,7 @@ const network: NetworkObject = {
]
}
export default function AnnouncementBanner(): ReactElement {
export default function NetworkBanner(): ReactElement {
const { web3Provider } = useWeb3()
const { config, connect } = useOcean()
const { announcement } = useSiteMetadata()
@ -34,7 +28,7 @@ export default function AnnouncementBanner(): ReactElement {
const addCustomNetworkAction = {
name: 'Add custom network',
handleAction: () => addCustomNetwork(web3Provider, network)
handleAction: () => addCustomNetwork(web3Provider, networkMatic)
}
const switchToPolygonAction = {
name: 'Switch to Polygon',
@ -88,16 +82,5 @@ export default function AnnouncementBanner(): ReactElement {
}
}, [web3Provider, config, announcement])
return (
<div className={styles.container}>
<div className={styles.banner}>
{text && <Markdown className={styles.text} text={text} />}
{action && (
<Button style="text" size="small" onClick={action.handleAction}>
{action.name}
</Button>
)}
</div>
</div>
)
return <AnnouncementBanner text={text} action={action} />
}

View File

@ -0,0 +1,14 @@
.sync {
display: inline-block;
font-size: var(--font-size-mini);
cursor: help;
}
.text {
margin-left: calc(var(--spacer) / 12);
}
.status {
transform: scale(0.7);
transform-origin: bottom;
}

View File

@ -0,0 +1,23 @@
import React, { ReactElement } from 'react'
import Tooltip from '../atoms/Tooltip'
import Status from '../atoms/Status'
import { useGraphSyncStatus } from '../../hooks/useGraphSyncStatus'
import styles from './SyncStatus.module.css'
export default function SyncStatus(): ReactElement {
const { isGraphSynced, blockGraph, blockHead } = useGraphSyncStatus()
return (
<div className={styles.sync}>
<Tooltip
content={`Synced to Ethereum block ${blockGraph} (out of ${blockHead})`}
>
<Status
className={styles.status}
state={isGraphSynced ? 'success' : 'error'}
/>
<span className={styles.text}>{blockGraph}</span>
</Tooltip>
</div>
)
}

View File

@ -1,4 +1,4 @@
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { ConfigHelperConfig } from '@oceanprotocol/lib'
import React, { ReactElement } from 'react'
import { useOcean } from '../../../providers/Ocean'
import { useWeb3 } from '../../../providers/Web3'

View File

@ -1,8 +1,7 @@
import React, { useState, useEffect, ReactElement } from 'react'
import { useOcean } from '../../../providers/Ocean'
import Status from '../../atoms/Status'
import { ConfigHelper } from '@oceanprotocol/lib'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { ConfigHelper, ConfigHelperConfig } from '@oceanprotocol/lib'
import styles from './Network.module.css'
import Badge from '../../atoms/Badge'
import Tooltip from '../../atoms/Tooltip'

View File

@ -77,6 +77,10 @@ function getOptions(locale: string, isDarkMode: boolean): ChartOptions {
legend: {
display: false
},
hover: {
intersect: false,
animationDuration: 0
},
scales: {
yAxes: [
{

View File

@ -2,7 +2,7 @@ import { useUserPreferences } from '../../../providers/UserPreferences'
import React, { ReactElement } from 'react'
import styles from './Bookmark.module.css'
import { ReactComponent as BookmarkIcon } from '../../../images/bookmark.svg'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { ConfigHelperConfig } from '@oceanprotocol/lib'
import { useOcean } from '../../../providers/Ocean'
export default function Bookmark({ did }: { did: string }): ReactElement {

View File

@ -5,6 +5,7 @@ import { useSiteMetadata } from '../../hooks/useSiteMetadata'
import { Link } from 'gatsby'
import MarketStats from '../molecules/MarketStats'
import BuildId from '../atoms/BuildId'
import SyncStatus from '../molecules/SyncStatus'
export default function Footer(): ReactElement {
const { copyright } = useSiteMetadata()
@ -13,9 +14,8 @@ export default function Footer(): ReactElement {
return (
<footer className={styles.footer}>
<div className={styles.content}>
<BuildId />
<SyncStatus /> | <BuildId />
<MarketStats />
<div className={styles.copyright}>
© {year} <Markdown text={copyright} /> {' '}
<Link to="/terms">Terms</Link>

View File

@ -33,6 +33,8 @@ export default function ComputeDetailsModal({
const job = await ocean.compute.status(
account,
computeJob.did,
undefined,
undefined,
computeJob.jobId
)
if (job?.length > 0) {

View File

@ -97,7 +97,9 @@ export default function ComputeJobs(): ReactElement {
account,
orderHistory[i].did,
undefined,
undefined,
orderHistory[i].transactionHash,
undefined,
false
)
computeJob.forEach((item) => {

View File

@ -0,0 +1,104 @@
import { useState, useEffect } from 'react'
import fetch from 'cross-fetch'
import { useOcean } from '../providers/Ocean'
import { useWeb3 } from '../providers/Web3'
import { Logger } from '@oceanprotocol/lib'
import Web3 from 'web3'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
const blockDifferenceThreshold = 30
const ethGraphUrl = `https://api.thegraph.com/subgraphs/name/blocklytics/ethereum-blocks`
const ethGraphQuery =
'{"query":" query Blocks{ blocks(first: 1, skip: 0, orderBy: number, orderDirection: desc, where: {number_gt: 9300000}) { id number timestamp author difficulty gasUsed gasLimit } }","variables":{},"operationName":"Blocks"}'
const graphQuery =
'{"query":" query Meta { _meta { block { hash number } deployment hasIndexingErrors } }","variables":{},"operationName":"Meta"}'
export interface UseGraphSyncStatus {
isGraphSynced: boolean
blockHead: number
blockGraph: number
}
async function fetchGraph(url: string, queryBody: string): Promise<Response> {
try {
const response = await fetch(url, {
method: 'POST',
body: queryBody
})
return await response.json()
} catch (error) {
console.error('Error parsing json: ' + error.message)
}
}
async function getBlockHead(config: ConfigHelperConfig) {
// for ETH main, get block from graph fetch
if (config.network === 'mainnet') {
const response: any = await fetchGraph(ethGraphUrl, ethGraphQuery)
return Number(response.data.blocks[0].number)
}
// for everything else, create new web3 instance with infura
const web3Instance = new Web3(config.nodeUri)
const blockHead = await web3Instance.eth.getBlockNumber()
return blockHead
}
async function getBlockSubgraph(subgraphUri: string) {
const response: any = await fetchGraph(
`${subgraphUri}/subgraphs/name/oceanprotocol/ocean-subgraph`,
graphQuery
)
const blockNumberGraph = Number(response.data._meta.block.number)
return blockNumberGraph
}
export function useGraphSyncStatus(): UseGraphSyncStatus {
const { config } = useOcean()
const { block, web3Loading } = useWeb3()
const [blockGraph, setBlockGraph] = useState<number>()
const [blockHead, setBlockHead] = useState<number>()
const [isGraphSynced, setIsGraphSynced] = useState(true)
const [subgraphLoading, setSubgraphLoading] = useState(false)
// Get and set head block
useEffect(() => {
if (!config || !config.nodeUri || web3Loading) return
async function initBlockHead() {
const blockHead = block || (await getBlockHead(config))
setBlockHead(blockHead)
Logger.log('[GraphStatus] Head block: ', blockHead)
}
initBlockHead()
}, [web3Loading, block, config.nodeUri])
// Get and set subgraph block
useEffect(() => {
if (!config || !config.subgraphUri) return
async function initBlockSubgraph() {
setSubgraphLoading(true)
const blockGraph = await getBlockSubgraph(config.subgraphUri)
setBlockGraph(blockGraph)
setSubgraphLoading(false)
Logger.log('[GraphStatus] Latest block from subgraph: ', blockGraph)
}
initBlockSubgraph()
}, [config.subgraphUri])
// Set sync status
useEffect(() => {
if ((!blockGraph && !blockHead) || web3Loading || subgraphLoading) return
const difference = blockHead - blockGraph
if (difference > blockDifferenceThreshold) {
setIsGraphSynced(false)
return
}
setIsGraphSynced(true)
}, [blockGraph, blockHead])
return { blockHead, blockGraph, isGraphSynced }
}

View File

@ -5,8 +5,7 @@ import {
InMemoryCache,
NormalizedCacheObject
} from '@apollo/client'
import { Logger } from '@oceanprotocol/lib'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { Logger, ConfigHelperConfig } from '@oceanprotocol/lib'
import { useOcean } from './Ocean'
import fetch from 'cross-fetch'
import React, { useState, useEffect, ReactNode, ReactElement } from 'react'

View File

@ -37,6 +37,8 @@ const poolQuery = gql`
query PoolPrice($datatoken: String) {
pools(where: { datatokenAddress: $datatoken }) {
spotPrice
datatokenReserve
oceanReserve
}
}
`
@ -125,7 +127,9 @@ function AssetProvider({
return
setPrice((prevState) => ({
...prevState,
value: poolPrice.pools[0].spotPrice
value: poolPrice.pools[0].spotPrice,
ocean: poolPrice.pools[0].oceanReserve,
datatoken: poolPrice.pools[0].datatokenReserve
}))
}, [poolPrice])

View File

@ -7,8 +7,14 @@ import React, {
ReactNode,
useEffect
} from 'react'
import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import {
Ocean,
Logger,
Account,
Config,
ConfigHelperConfig
} from '@oceanprotocol/lib'
import { useWeb3 } from './Web3'
import {
getDevelopmentConfig,

View File

@ -6,10 +6,8 @@ import React, {
useState,
useEffect
} from 'react'
import { Logger } from '@oceanprotocol/lib'
import { LogLevel } from '@oceanprotocol/lib/dist/node/utils/Logger'
import { Logger, LogLevel, ConfigHelperConfig } from '@oceanprotocol/lib'
import { useOcean } from './Ocean'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { isBrowser } from '../utils'
interface UserPreferencesValue {

View File

@ -28,7 +28,9 @@ interface Web3ProviderValue {
networkId: number
networkDisplayName: string
networkData: EthereumListsChain
block: number
isTestnet: boolean
web3Loading: boolean
connect: () => Promise<void>
logout: () => Promise<void>
}
@ -107,13 +109,16 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
const [networkId, setNetworkId] = useState<number>()
const [networkDisplayName, setNetworkDisplayName] = useState<string>()
const [networkData, setNetworkData] = useState<EthereumListsChain>()
const [block, setBlock] = useState<number>()
const [isTestnet, setIsTestnet] = useState<boolean>()
const [accountId, setAccountId] = useState<string>()
const [web3Loading, setWeb3Loading] = useState<boolean>()
const connect = useCallback(async () => {
if (!web3Modal) return
try {
setWeb3Loading(true)
Logger.log('[web3] Connecting Web3...')
const provider = await web3Modal?.connect()
@ -132,6 +137,8 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
Logger.log('[web3] account id', accountId)
} catch (error) {
Logger.error('[web3] Error: ', error.message)
} finally {
setWeb3Loading(false)
}
}, [web3Modal])
@ -186,6 +193,20 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
Logger.log(`[web3] Network display name set to: ${networkDisplayName}`)
}, [networkId, networksList])
// -----------------------------------
// Get and set latest head block
// -----------------------------------
useEffect(() => {
if (!web3) return
async function getBlock() {
const block = await web3.eth.getBlockNumber()
setBlock(block)
Logger.log('[web3] Head block: ', block)
}
getBlock()
}, [web3, networkId])
// -----------------------------------
// Logout helper
// -----------------------------------
@ -236,7 +257,9 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
networkId,
networkDisplayName,
networkData,
block,
isTestnet,
web3Loading,
connect,
logout
}}

View File

@ -1,11 +1,14 @@
import { Account, Logger, Ocean } from '@oceanprotocol/lib'
import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
import {
Account,
Logger,
Ocean,
ConfigHelper,
ConfigHelperConfig,
ConfigHelperNetworkId,
ConfigHelperNetworkName
} from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
} from '@oceanprotocol/lib'
import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
import { UserBalance } from '../@types/TokenBalance'
export function getOceanConfig(
@ -13,7 +16,9 @@ export function getOceanConfig(
): ConfigHelperConfig {
return new ConfigHelper().getConfig(
network,
process.env.GATSBY_INFURA_PROJECT_ID
network === 'polygon' || network === 137
? undefined
: process.env.GATSBY_INFURA_PROJECT_ID
) as ConfigHelperConfig
}

View File

@ -1,5 +1,4 @@
import { Logger } from '@oceanprotocol/lib'
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
import { Logger, ConfigHelperConfig } from '@oceanprotocol/lib'
export interface EthereumListsChain {
name: string
@ -56,6 +55,7 @@ export function addCustomNetwork(
): void {
const newNewtworkData = {
chainId: `0x${network.chainId.toString(16)}`,
chainName: network.name,
rpcUrls: network.urlList
}
web3Provider.request(