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:
commit
df587bb5b5
2
.husky/.gitignore
vendored
2
.husky/.gitignore
vendored
@ -1 +1 @@
|
|||||||
_
|
_
|
||||||
|
33
README.md
33
README.md
@ -18,6 +18,7 @@
|
|||||||
- [Ocean Protocol Subgraph](#ocean-protocol-subgraph)
|
- [Ocean Protocol Subgraph](#ocean-protocol-subgraph)
|
||||||
- [3Box](#3box)
|
- [3Box](#3box)
|
||||||
- [Purgatory](#purgatory)
|
- [Purgatory](#purgatory)
|
||||||
|
- [Network Metadata](#network-metadata)
|
||||||
- [🎨 Storybook](#-storybook)
|
- [🎨 Storybook](#-storybook)
|
||||||
- [✨ Code Style](#-code-style)
|
- [✨ Code Style](#-code-style)
|
||||||
- [👩🔬 Testing](#-testing)
|
- [👩🔬 Testing](#-testing)
|
||||||
@ -229,6 +230,8 @@ function Component() {
|
|||||||
|
|
||||||
Based on [list-purgatory](https://github.com/oceanprotocol/list-purgatory) some data sets get additional data. Within most components this can be done with the internal `useAsset()` hook which fetches data from the [market-purgatory](https://github.com/oceanprotocol/market-purgatory) endpoint in the background.
|
Based on [list-purgatory](https://github.com/oceanprotocol/list-purgatory) some data sets get additional data. Within most components this can be done with the internal `useAsset()` hook which fetches data from the [market-purgatory](https://github.com/oceanprotocol/market-purgatory) endpoint in the background.
|
||||||
|
|
||||||
|
For asset purgatory:
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
|
|
||||||
@ -238,6 +241,36 @@ function Component() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For account purgatory:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import { useAccountPurgatory } from '../../../hooks/useAccountPurgatory'
|
||||||
|
|
||||||
|
function Component() {
|
||||||
|
const { accountId } = useWeb3()
|
||||||
|
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||||
|
return isInPurgatory ? <div>{purgatoryData.reason}</div> : null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Network Metadata
|
||||||
|
|
||||||
|
All displayed chain & network metadata is retrieved from `https://chainid.network` on build time and integrated into Gatsby's GraphQL layer. This data source is a community-maintained GitHub repository under [ethereum-lists/chains](https://github.com/ethereum-lists/chains).
|
||||||
|
|
||||||
|
Within components this metadata can be queried for under `allNetworksMetadataJson`. The `useWeb3()` hook does this in the background to expose the final `networkDisplayName` for use in components:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
export default function NetworkName(): ReactElement {
|
||||||
|
const { networkDisplayName, isTestnet } = useWeb3()
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{networkDisplayName} {isTestnet && `(Test)`}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 🎨 Storybook
|
## 🎨 Storybook
|
||||||
|
|
||||||
> TODO: this is broken for most components. See https://github.com/oceanprotocol/market/issues/128
|
> TODO: this is broken for most components. See https://github.com/oceanprotocol/market/issues/128
|
||||||
|
@ -3,7 +3,7 @@ module.exports = {
|
|||||||
service: {
|
service: {
|
||||||
name: 'ocean',
|
name: 'ocean',
|
||||||
url:
|
url:
|
||||||
'https://subgraph.mainnet.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph',
|
'https://subgraph.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph',
|
||||||
// optional disable SSL validation check
|
// optional disable SSL validation check
|
||||||
skipSSLValidation: true
|
skipSSLValidation: true
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
"link": "/history"
|
"link": "/history"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"warning": "We are in beta. Please familiarize yourself with [the market](https://oceanprotocol.com/technology/marketplaces), [the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13), and the [Terms of Use](/terms)."
|
"warning": "We are in beta. Please familiarize yourself with [the market](https://oceanprotocol.com/technology/marketplaces), [the risks](https://blog.oceanprotocol.com/on-staking-on-data-in-ocean-market-3d8e09eb0a13), and the [Terms of Use](/terms).",
|
||||||
|
"warningPolygon": "Polygon/Matic EVM support is in early stages. Use the Matic bridge to [get mOCEAN](https://docs.oceanprotocol.com/tutorials/polygon-bridge/).",
|
||||||
|
"warningPolygonPublish": "Only republish data sets with a pool from ETH Mainnet into Polygon/Matic if the liquidity is **less than or equal to 1000 OCEAN in the original pool**. Doing otherwise will lead to [purgatory](https://github.com/oceanprotocol/list-purgatory) for the data set in Polygon/Matic."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
const path = require('path')
|
|
||||||
const createFields = require('./gatsby/createFields')
|
const createFields = require('./gatsby/createFields')
|
||||||
const createMarkdownPages = require('./gatsby/createMarkdownPages')
|
const createMarkdownPages = require('./gatsby/createMarkdownPages')
|
||||||
const execSync = require('child_process').execSync
|
const execSync = require('child_process').execSync
|
||||||
@ -48,14 +47,6 @@ exports.onCreateWebpackConfig = ({ actions }) => {
|
|||||||
fs: 'empty'
|
fs: 'empty'
|
||||||
},
|
},
|
||||||
// fix for 'got'/'swarm-js' dependency
|
// fix for 'got'/'swarm-js' dependency
|
||||||
externals: ['got'],
|
externals: ['got']
|
||||||
|
|
||||||
// fix for being able to use `npm link` with @oceanprotocol/react
|
|
||||||
// see https://github.com/facebook/react/issues/13991
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
react: path.resolve('./node_modules/react')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
12
package-lock.json
generated
12
package-lock.json
generated
@ -3643,18 +3643,6 @@
|
|||||||
"web3-eth-contract": "^1.3.4"
|
"web3-eth-contract": "^1.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@oceanprotocol/react": {
|
|
||||||
"version": "0.5.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/react/-/react-0.5.5.tgz",
|
|
||||||
"integrity": "sha512-2xkdiU7vsV+MbS4FD3xrUIud6oZ6ognuLg8zesV8yGND4WlyNR95g2bp3L93H0asg65VdYh5ZSyNzxPHKjzqhg==",
|
|
||||||
"requires": {
|
|
||||||
"@oceanprotocol/lib": "^0.11.4",
|
|
||||||
"axios": "^0.21.1",
|
|
||||||
"decimal.js": "^10.2.1",
|
|
||||||
"web3": "1.3.4",
|
|
||||||
"web3modal": "^1.9.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@oceanprotocol/typographies": {
|
"@oceanprotocol/typographies": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/typographies/-/typographies-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/typographies/-/typographies-0.1.0.tgz",
|
||||||
|
@ -23,12 +23,11 @@
|
|||||||
"postinstall": "husky install"
|
"postinstall": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.3.6",
|
"@apollo/client": "^3.3.11",
|
||||||
"@coingecko/cryptoformat": "^0.4.2",
|
"@coingecko/cryptoformat": "^0.4.2",
|
||||||
"@loadable/component": "^5.14.1",
|
"@loadable/component": "^5.14.1",
|
||||||
"@oceanprotocol/art": "^3.0.0",
|
"@oceanprotocol/art": "^3.0.0",
|
||||||
"@oceanprotocol/lib": "^0.11.4",
|
"@oceanprotocol/lib": "^0.11.4",
|
||||||
"@oceanprotocol/react": "^0.5.5",
|
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
"@portis/web3": "^3.0.3",
|
"@portis/web3": "^3.0.3",
|
||||||
"@sindresorhus/slugify": "^1.0.0",
|
"@sindresorhus/slugify": "^1.0.0",
|
||||||
@ -87,7 +86,8 @@
|
|||||||
"slugify": "^1.4.6",
|
"slugify": "^1.4.6",
|
||||||
"swr": "^0.3.11",
|
"swr": "^0.3.11",
|
||||||
"use-dark-mode": "^2.3.1",
|
"use-dark-mode": "^2.3.1",
|
||||||
"web3": "^1.3.1",
|
"web3": "^1.3.4",
|
||||||
|
"web3modal": "^1.9.3",
|
||||||
"yup": "^0.32.6"
|
"yup": "^0.32.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
3
src/@types/MetaData.d.ts
vendored
3
src/@types/MetaData.d.ts
vendored
@ -4,7 +4,8 @@ import {
|
|||||||
AdditionalInformation,
|
AdditionalInformation,
|
||||||
ServiceMetadata
|
ServiceMetadata
|
||||||
} from '@oceanprotocol/lib'
|
} from '@oceanprotocol/lib'
|
||||||
import { DataTokenOptions, PriceOptions } from '@oceanprotocol/react'
|
import { DataTokenOptions } from '../hooks/usePublish'
|
||||||
|
import { PriceOptions } from '../hooks/usePricing'
|
||||||
|
|
||||||
export interface AdditionalInformationMarket extends AdditionalInformation {
|
export interface AdditionalInformationMarket extends AdditionalInformation {
|
||||||
links?: File[]
|
links?: File[]
|
||||||
|
7
src/@types/TokenBalance.d.ts
vendored
7
src/@types/TokenBalance.d.ts
vendored
@ -1,4 +1,9 @@
|
|||||||
export default interface TokenBalance {
|
export interface PoolBalance {
|
||||||
ocean: number
|
ocean: number
|
||||||
datatoken: number
|
datatoken: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UserBalance {
|
||||||
|
eth: string
|
||||||
|
ocean: string
|
||||||
|
}
|
||||||
|
@ -4,9 +4,10 @@ import Header from './organisms/Header'
|
|||||||
import Styles from '../global/Styles'
|
import Styles from '../global/Styles'
|
||||||
import styles from './App.module.css'
|
import styles from './App.module.css'
|
||||||
import { useSiteMetadata } from '../hooks/useSiteMetadata'
|
import { useSiteMetadata } from '../hooks/useSiteMetadata'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import Alert from './atoms/Alert'
|
import Alert from './atoms/Alert'
|
||||||
import { graphql, PageProps, useStaticQuery } from 'gatsby'
|
import { graphql, PageProps, useStaticQuery } from 'gatsby'
|
||||||
|
import { useAccountPurgatory } from '../hooks/useAccountPurgatory'
|
||||||
|
import { useWeb3 } from '../providers/Web3'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query AppQuery {
|
query AppQuery {
|
||||||
@ -34,23 +35,25 @@ export default function App({
|
|||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const purgatory = data.purgatory.edges[0].node.childContentJson.account
|
const purgatory = data.purgatory.edges[0].node.childContentJson.account
|
||||||
|
|
||||||
const { warning } = useSiteMetadata()
|
const { warning, warningPolygon } = useSiteMetadata()
|
||||||
const {
|
const { accountId } = useWeb3()
|
||||||
isInPurgatory: isAccountInPurgatory,
|
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||||
purgatoryData: accountPurgatory
|
const { networkId } = useWeb3()
|
||||||
} = useOcean()
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Styles>
|
<Styles>
|
||||||
<div className={styles.app}>
|
<div className={styles.app}>
|
||||||
<Header />
|
<Header />
|
||||||
{(props as PageProps).uri === '/' && (
|
{(props as PageProps).uri === '/' && (
|
||||||
<Alert text={warning} state="info" />
|
<Alert
|
||||||
|
text={(networkId === 137 ? `${warningPolygon}\n\n` : '') + warning}
|
||||||
|
state="info"
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{isAccountInPurgatory && (
|
{isInPurgatory && (
|
||||||
<Alert
|
<Alert
|
||||||
title={purgatory.title}
|
title={purgatory.title}
|
||||||
badge={`Reason: ${accountPurgatory?.reason}`}
|
badge={`Reason: ${purgatoryData?.reason}`}
|
||||||
text={purgatory.description}
|
text={purgatory.description}
|
||||||
state="error"
|
state="error"
|
||||||
/>
|
/>
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
.dropzone {
|
|
||||||
padding: var(--spacer);
|
|
||||||
text-align: center;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
border: 0.1rem dashed var(--color-secondary);
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dragover {
|
|
||||||
border-color: var(--color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.disabled {
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import Dropzone from './Dropzone'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: 'Atoms/Dropzone'
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Default = () => <Dropzone handleOnDrop={() => null} />
|
|
@ -1,68 +0,0 @@
|
|||||||
import React, { ReactElement, useCallback } from 'react'
|
|
||||||
import { useDropzone } from 'react-dropzone'
|
|
||||||
import styles from './Dropzone.module.css'
|
|
||||||
import { formatBytes } from '../../utils'
|
|
||||||
|
|
||||||
export default function Dropzone({
|
|
||||||
handleOnDrop,
|
|
||||||
disabled,
|
|
||||||
multiple,
|
|
||||||
error
|
|
||||||
}: {
|
|
||||||
handleOnDrop(files: File[]): void
|
|
||||||
disabled?: boolean
|
|
||||||
multiple?: boolean
|
|
||||||
error?: string
|
|
||||||
}): ReactElement {
|
|
||||||
const onDrop = useCallback((acceptedFiles) => handleOnDrop(acceptedFiles), [
|
|
||||||
handleOnDrop
|
|
||||||
])
|
|
||||||
|
|
||||||
const {
|
|
||||||
getRootProps,
|
|
||||||
getInputProps,
|
|
||||||
isDragActive,
|
|
||||||
isDragReject,
|
|
||||||
acceptedFiles
|
|
||||||
} = useDropzone({ onDrop })
|
|
||||||
|
|
||||||
const files = acceptedFiles.map((file: any) => (
|
|
||||||
<li key={file.path}>
|
|
||||||
{file.path} - {formatBytes(file.size, 0)}
|
|
||||||
</li>
|
|
||||||
))
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
{...getRootProps({
|
|
||||||
className: isDragActive
|
|
||||||
? `${styles.dropzone} ${styles.dragover}`
|
|
||||||
: disabled
|
|
||||||
? `${styles.dropzone} ${styles.disabled}`
|
|
||||||
: styles.dropzone
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{acceptedFiles.length > 0 ? (
|
|
||||||
<aside>
|
|
||||||
<ul>{files}</ul>
|
|
||||||
</aside>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<input {...getInputProps({ multiple })} />
|
|
||||||
|
|
||||||
{isDragActive && !isDragReject ? (
|
|
||||||
`Drop it like it's hot!`
|
|
||||||
) : multiple ? (
|
|
||||||
`Drag 'n' drop some files here, or click to select files`
|
|
||||||
) : error ? (
|
|
||||||
<div className={styles.error}>{error}</div>
|
|
||||||
) : (
|
|
||||||
`Drag 'n' drop a file here, or click to select a file`
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
import React, { ReactElement, ReactNode, useEffect, useState } from 'react'
|
|
||||||
import { EthereumListsChain, getNetworkData } from '../../utils/wallet'
|
|
||||||
import { ReactComponent as External } from '../../images/external.svg'
|
|
||||||
import styles from './EtherscanLink.module.css'
|
|
||||||
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
|
||||||
|
|
||||||
const networksQuery = graphql`
|
|
||||||
query {
|
|
||||||
allNetworksMetadataJson {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
chain
|
|
||||||
network
|
|
||||||
networkId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default function EtherscanLink({
|
|
||||||
networkId,
|
|
||||||
path,
|
|
||||||
children
|
|
||||||
}: {
|
|
||||||
networkId: number
|
|
||||||
path: string
|
|
||||||
children: ReactNode
|
|
||||||
}): ReactElement {
|
|
||||||
const data = useStaticQuery(networksQuery)
|
|
||||||
const networksList: { node: EthereumListsChain }[] =
|
|
||||||
data.allNetworksMetadataJson.edges
|
|
||||||
|
|
||||||
const { appConfig } = useSiteMetadata()
|
|
||||||
const [url, setUrl] = useState<string>()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const networkData = networkId
|
|
||||||
? getNetworkData(networksList, networkId)
|
|
||||||
: null
|
|
||||||
const url =
|
|
||||||
(!networkId && appConfig.network === 'mainnet') || networkId === 1
|
|
||||||
? `https://etherscan.io`
|
|
||||||
: `https://${
|
|
||||||
networkData ? networkData.network : appConfig.network
|
|
||||||
}.etherscan.io`
|
|
||||||
|
|
||||||
setUrl(url)
|
|
||||||
}, [networkId, networksList, appConfig.network])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={`${url}/${path}`}
|
|
||||||
title="View on Etherscan"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className={styles.link}
|
|
||||||
>
|
|
||||||
{children} <External />
|
|
||||||
</a>
|
|
||||||
)
|
|
||||||
}
|
|
33
src/components/atoms/ExplorerLink.tsx
Normal file
33
src/components/atoms/ExplorerLink.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
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 { useOcean } from '../../providers/Ocean'
|
||||||
|
|
||||||
|
export default function ExplorerLink({
|
||||||
|
path,
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
networkId: number
|
||||||
|
path: string
|
||||||
|
children: ReactNode
|
||||||
|
}): ReactElement {
|
||||||
|
const { config } = useOcean()
|
||||||
|
const [url, setUrl] = useState<string>()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setUrl((config as ConfigHelperConfig).explorerUri)
|
||||||
|
}, [config])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={`${url}/${path}`}
|
||||||
|
title={`View on ${(config as ConfigHelperConfig).explorerUri}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className={styles.link}
|
||||||
|
>
|
||||||
|
{children} <External />
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
@ -12,7 +12,6 @@ const Markdown = ({
|
|||||||
// fix react-markdown \n transformation
|
// fix react-markdown \n transformation
|
||||||
// https://github.com/rexxars/react-markdown/issues/105#issuecomment-351585313
|
// https://github.com/rexxars/react-markdown/issues/105#issuecomment-351585313
|
||||||
const textCleaned = text.replace(/\\n/g, '\n ')
|
const textCleaned = text.replace(/\\n/g, '\n ')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
source={textCleaned}
|
source={textCleaned}
|
||||||
|
@ -7,6 +7,6 @@ export default {
|
|||||||
title: 'Atoms/Price'
|
title: 'Atoms/Price'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Normal = () => <Price ddo={ddo as DDO} />
|
export const Normal = () => <Price price={(ddo as DDO).price} />
|
||||||
|
|
||||||
export const Small = () => <Price ddo={ddo as DDO} small />
|
export const Small = () => <Price price={(ddo as DDO).price} small />
|
||||||
|
@ -1,25 +1,21 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { useMetadata } from '@oceanprotocol/react'
|
import { BestPrice } from '@oceanprotocol/lib'
|
||||||
import { DDO } from '@oceanprotocol/lib'
|
|
||||||
import Loader from '../Loader'
|
import Loader from '../Loader'
|
||||||
import Tooltip from '../Tooltip'
|
import Tooltip from '../Tooltip'
|
||||||
import PriceUnit from './PriceUnit'
|
import PriceUnit from './PriceUnit'
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
ddo,
|
price,
|
||||||
className,
|
className,
|
||||||
small,
|
small,
|
||||||
conversion
|
conversion
|
||||||
}: {
|
}: {
|
||||||
ddo: DDO
|
price: BestPrice
|
||||||
className?: string
|
className?: string
|
||||||
small?: boolean
|
small?: boolean
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
// price is not fetched from the chain anymore , will update one AssetProvider is implemented
|
|
||||||
const { price } = useMetadata(ddo)
|
|
||||||
|
|
||||||
return price?.value ? (
|
return price?.value ? (
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={`${price.value}`}
|
price={`${price.value}`}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import styles from './ProfileDetails.module.css'
|
import styles from './ProfileDetails.module.css'
|
||||||
import { Profile } from '../../../models/Profile'
|
import { Profile } from '../../../models/Profile'
|
||||||
import EtherscanLink from '../EtherscanLink'
|
import ExplorerLink from '../ExplorerLink'
|
||||||
import PublisherLinks from './PublisherLinks'
|
import PublisherLinks from './PublisherLinks'
|
||||||
|
|
||||||
export default function ProfileDetails({
|
export default function ProfileDetails({
|
||||||
@ -26,9 +26,9 @@ export default function ProfileDetails({
|
|||||||
{profile?.emoji} {profile?.name}
|
{profile?.emoji} {profile?.name}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<EtherscanLink networkId={networkId} path={`address/${account}`}>
|
<ExplorerLink networkId={networkId} path={`address/${account}`}>
|
||||||
<code>{account}</code>
|
<code>{account}</code>
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{profile?.description && (
|
{profile?.description && (
|
||||||
|
@ -5,13 +5,13 @@ import Tooltip from '../Tooltip'
|
|||||||
import { Profile } from '../../../models/Profile'
|
import { Profile } from '../../../models/Profile'
|
||||||
import { Link } from 'gatsby'
|
import { Link } from 'gatsby'
|
||||||
import get3BoxProfile from '../../../utils/profile'
|
import get3BoxProfile from '../../../utils/profile'
|
||||||
import EtherscanLink from '../EtherscanLink'
|
import ExplorerLink from '../ExplorerLink'
|
||||||
import { accountTruncate } from '../../../utils/wallet'
|
import { accountTruncate } from '../../../utils/web3'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { ReactComponent as Info } from '../../../images/info.svg'
|
import { ReactComponent as Info } from '../../../images/info.svg'
|
||||||
import ProfileDetails from './ProfileDetails'
|
import ProfileDetails from './ProfileDetails'
|
||||||
import Add from './Add'
|
import Add from './Add'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ export default function Publisher({
|
|||||||
minimal?: boolean
|
minimal?: boolean
|
||||||
className?: string
|
className?: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { networkId, accountId } = useOcean()
|
const { networkId, accountId } = useWeb3()
|
||||||
const [profile, setProfile] = useState<Profile>()
|
const [profile, setProfile] = useState<Profile>()
|
||||||
const [name, setName] = useState<string>()
|
const [name, setName] = useState<string>()
|
||||||
|
|
||||||
@ -88,9 +88,9 @@ export default function Publisher({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
{showAdd && <Add />}
|
{showAdd && <Add />}
|
||||||
<EtherscanLink networkId={networkId} path={`address/${account}`}>
|
<ExplorerLink networkId={networkId} path={`address/${account}`}>
|
||||||
Etherscan
|
Explorer
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
import { useSiteMetadata } from '../../hooks/useSiteMetadata'
|
||||||
|
import { isBrowser } from '../../utils'
|
||||||
|
|
||||||
export default function Seo({
|
export default function Seo({
|
||||||
title,
|
title,
|
||||||
@ -24,7 +25,7 @@ export default function Seo({
|
|||||||
>
|
>
|
||||||
<html lang="en" />
|
<html lang="en" />
|
||||||
|
|
||||||
{typeof window !== 'undefined' &&
|
{isBrowser &&
|
||||||
window.location &&
|
window.location &&
|
||||||
window.location.hostname !== 'oceanprotocol.com' && (
|
window.location.hostname !== 'oceanprotocol.com' && (
|
||||||
<meta name="robots" content="noindex,nofollow" />
|
<meta name="robots" content="noindex,nofollow" />
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { DDO } from '@oceanprotocol/lib'
|
import { DDO } from '@oceanprotocol/lib'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../providers/Ocean'
|
||||||
import { Link } from 'gatsby'
|
import { Link } from 'gatsby'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { retrieveDDO, getAssetsNames } from '../../utils/aquarius'
|
import { getAssetsNames } from '../../utils/aquarius'
|
||||||
import styles from './AssetListTitle.module.css'
|
import styles from './AssetListTitle.module.css'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import styles from './AssetTeaser.module.css'
|
|||||||
import { DDO } from '@oceanprotocol/lib'
|
import { DDO } from '@oceanprotocol/lib'
|
||||||
import removeMarkdown from 'remove-markdown'
|
import removeMarkdown from 'remove-markdown'
|
||||||
import Publisher from '../atoms/Publisher'
|
import Publisher from '../atoms/Publisher'
|
||||||
import { useMetadata } from '@oceanprotocol/react'
|
|
||||||
import Time from '../atoms/Time'
|
import Time from '../atoms/Time'
|
||||||
import AssetType from '../atoms/AssetType'
|
import AssetType from '../atoms/AssetType'
|
||||||
|
|
||||||
@ -15,12 +14,12 @@ declare type AssetTeaserProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
|
const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
|
||||||
const { owner } = useMetadata(ddo)
|
|
||||||
const { attributes } = ddo.findServiceByType('metadata')
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
const { name, type } = attributes.main
|
const { name, type } = attributes.main
|
||||||
const { dataTokenInfo } = ddo
|
const { dataTokenInfo } = ddo
|
||||||
const isCompute = Boolean(ddo?.findServiceByType('compute'))
|
const isCompute = Boolean(ddo?.findServiceByType('compute'))
|
||||||
const accessType = isCompute ? 'compute' : 'access'
|
const accessType = isCompute ? 'compute' : 'access'
|
||||||
|
const { owner } = ddo.publicKey[0]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className={`${styles.teaser} ${styles[type]}`}>
|
<article className={`${styles.teaser} ${styles[type]}`}>
|
||||||
@ -48,7 +47,7 @@ const AssetTeaser: React.FC<AssetTeaserProps> = ({ ddo }: AssetTeaserProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer className={styles.foot}>
|
<footer className={styles.foot}>
|
||||||
<Price ddo={ddo} small />
|
<Price price={ddo.price} small />
|
||||||
<p className={styles.date}>
|
<p className={styles.date}>
|
||||||
<Time date={ddo?.created} relative />
|
<Time date={ddo?.created} relative />
|
||||||
</p>
|
</p>
|
||||||
|
@ -2,7 +2,7 @@ import { useUserPreferences } from '../../providers/UserPreferences'
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Table from '../atoms/Table'
|
import Table from '../atoms/Table'
|
||||||
import { DDO, Logger } from '@oceanprotocol/lib'
|
import { DDO, Logger } from '@oceanprotocol/lib'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../providers/Ocean'
|
||||||
import Price from '../atoms/Price'
|
import Price from '../atoms/Price'
|
||||||
import Tooltip from '../atoms/Tooltip'
|
import Tooltip from '../atoms/Tooltip'
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
@ -73,7 +73,7 @@ const columns = [
|
|||||||
{
|
{
|
||||||
name: 'Price',
|
name: 'Price',
|
||||||
selector: function getAssetRow(row: DDO) {
|
selector: function getAssetRow(row: DDO) {
|
||||||
return <Price ddo={row} small />
|
return <Price price={row.price} small />
|
||||||
},
|
},
|
||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useField } from 'formik'
|
import { useField } from 'formik'
|
||||||
import { InputProps } from '../../../atoms/Input'
|
import { InputProps } from '../../../atoms/Input'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
import React, { ReactElement, useEffect } from 'react'
|
import React, { ReactElement, useEffect } from 'react'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { useField } from 'formik'
|
|||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import FileInfo from './Info'
|
import FileInfo from './Info'
|
||||||
import FileInput from './Input'
|
import FileInput from './Input'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
import { InputProps } from '../../../atoms/Input'
|
import { InputProps } from '../../../atoms/Input'
|
||||||
import { fileinfo } from '../../../../utils/provider'
|
import { fileinfo } from '../../../../utils/provider'
|
||||||
|
|
||||||
|
@ -22,8 +22,7 @@ export default function MarketStats(): ReactElement {
|
|||||||
const { data } = useQuery(getTotalPoolsValues)
|
const { data } = useQuery(getTotalPoolsValues)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data) return
|
if (!data || !data.poolFactories || data.poolFactories.length === 0) return
|
||||||
|
|
||||||
setTotalValueLocked(data.poolFactories[0].totalValueLocked)
|
setTotalValueLocked(data.poolFactories[0].totalValueLocked)
|
||||||
setTotalOceanLiquidity(data.poolFactories[0].totalOceanLiquidity)
|
setTotalOceanLiquidity(data.poolFactories[0].totalOceanLiquidity)
|
||||||
setPoolCount(data.poolFactories[0].finalizedPoolCount)
|
setPoolCount(data.poolFactories[0].finalizedPoolCount)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../providers/Ocean'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import EtherscanLink from '../atoms/EtherscanLink'
|
import ExplorerLink from '../atoms/ExplorerLink'
|
||||||
import Time from '../atoms/Time'
|
import Time from '../atoms/Time'
|
||||||
import Table from '../atoms/Table'
|
import Table from '../atoms/Table'
|
||||||
import AssetTitle from './AssetListTitle'
|
import AssetTitle from './AssetListTitle'
|
||||||
@ -15,6 +15,7 @@ import {
|
|||||||
} from '../../@types/apollo/TransactionHistory'
|
} from '../../@types/apollo/TransactionHistory'
|
||||||
|
|
||||||
import web3 from 'web3'
|
import web3 from 'web3'
|
||||||
|
import { useWeb3 } from '../../providers/Web3'
|
||||||
|
|
||||||
const txHistoryQueryByPool = gql`
|
const txHistoryQueryByPool = gql`
|
||||||
query TransactionHistoryByPool($user: String, $pool: String) {
|
query TransactionHistoryByPool($user: String, $pool: String) {
|
||||||
@ -129,7 +130,8 @@ async function getTitle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Title({ row }: { row: TransactionHistoryPoolTransactions }) {
|
function Title({ row }: { row: TransactionHistoryPoolTransactions }) {
|
||||||
const { ocean, networkId } = useOcean()
|
const { networkId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const [title, setTitle] = useState<string>()
|
const [title, setTitle] = useState<string>()
|
||||||
const { locale } = useUserPreferences()
|
const { locale } = useUserPreferences()
|
||||||
|
|
||||||
@ -144,9 +146,9 @@ function Title({ row }: { row: TransactionHistoryPoolTransactions }) {
|
|||||||
}, [ocean, row, locale])
|
}, [ocean, row, locale])
|
||||||
|
|
||||||
return title ? (
|
return title ? (
|
||||||
<EtherscanLink networkId={networkId} path={`/tx/${row.tx}`}>
|
<ExplorerLink networkId={networkId} path={`/tx/${row.tx}`}>
|
||||||
<span className={styles.titleText}>{title}</span>
|
<span className={styles.titleText}>{title}</span>
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +195,7 @@ export default function PoolTransactions({
|
|||||||
poolAddress?: string
|
poolAddress?: string
|
||||||
minimal?: boolean
|
minimal?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
const [logs, setLogs] = useState<TransactionHistoryPoolTransactions[]>()
|
const [logs, setLogs] = useState<TransactionHistoryPoolTransactions[]>()
|
||||||
|
|
||||||
const { data, loading } = useQuery<TransactionHistory>(
|
const { data, loading } = useQuery<TransactionHistory>(
|
||||||
|
19
src/components/molecules/UserPreferences/Chain.module.css
Normal file
19
src/components/molecules/UserPreferences/Chain.module.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
.buttons {
|
||||||
|
composes: buttons from './Appearance.module.css';
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
composes: button from './Appearance.module.css';
|
||||||
|
}
|
||||||
|
|
||||||
|
.button span {
|
||||||
|
display: block;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
font-family: var(--font-family-base);
|
||||||
|
font-weight: var(--font-weight-base);
|
||||||
|
margin-top: calc(var(--spacer) / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected {
|
||||||
|
composes: selected from './Appearance.module.css';
|
||||||
|
}
|
53
src/components/molecules/UserPreferences/Chain.tsx
Normal file
53
src/components/molecules/UserPreferences/Chain.tsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
|
import React, { ReactElement } from 'react'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import { getOceanConfig } from '../../../utils/ocean'
|
||||||
|
import Button from '../../atoms/Button'
|
||||||
|
import FormHelp from '../../atoms/Input/Help'
|
||||||
|
import Label from '../../atoms/Input/Label'
|
||||||
|
import styles from './Chain.module.css'
|
||||||
|
|
||||||
|
export default function Chain(): ReactElement {
|
||||||
|
const { web3 } = useWeb3()
|
||||||
|
const { config, connect } = useOcean()
|
||||||
|
|
||||||
|
async function connectOcean(networkName: string) {
|
||||||
|
const config = getOceanConfig(networkName)
|
||||||
|
await connect(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
const chains = [
|
||||||
|
{ name: 'ETH', oceanConfig: 'mainnet' },
|
||||||
|
{ name: 'Polygon/Matic', oceanConfig: 'polygon' }
|
||||||
|
]
|
||||||
|
|
||||||
|
// TODO: to fully solve https://github.com/oceanprotocol/market/issues/432
|
||||||
|
// there are more considerations for users with a wallet connected (wallet network vs. setting network).
|
||||||
|
// For now, only show the setting for non-wallet users.
|
||||||
|
return !web3 ? (
|
||||||
|
<li>
|
||||||
|
<Label htmlFor="">Chain</Label>
|
||||||
|
<div className={styles.buttons}>
|
||||||
|
{chains.map((button) => {
|
||||||
|
const selected =
|
||||||
|
(config as ConfigHelperConfig).network === button.oceanConfig
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={button.name}
|
||||||
|
className={`${styles.button} ${selected ? styles.selected : ''}`}
|
||||||
|
size="small"
|
||||||
|
style="text"
|
||||||
|
onClick={() => connectOcean(button.oceanConfig)}
|
||||||
|
>
|
||||||
|
{button.name}
|
||||||
|
<span>Mainnet</span>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<FormHelp>Switch the data source for the interface.</FormHelp>
|
||||||
|
</li>
|
||||||
|
) : null
|
||||||
|
}
|
@ -8,6 +8,7 @@ import { ReactComponent as Caret } from '../../../images/caret.svg'
|
|||||||
import useDarkMode from 'use-dark-mode'
|
import useDarkMode from 'use-dark-mode'
|
||||||
import Appearance from './Appearance'
|
import Appearance from './Appearance'
|
||||||
import { darkModeConfig } from '../../../../app.config'
|
import { darkModeConfig } from '../../../../app.config'
|
||||||
|
import Chain from './Chain'
|
||||||
|
|
||||||
export default function UserPreferences(): ReactElement {
|
export default function UserPreferences(): ReactElement {
|
||||||
// Calling this here because <Theme /> is not mounted on first load
|
// Calling this here because <Theme /> is not mounted on first load
|
||||||
@ -19,6 +20,7 @@ export default function UserPreferences(): ReactElement {
|
|||||||
<ul className={styles.preferencesDetails}>
|
<ul className={styles.preferencesDetails}>
|
||||||
<Currency />
|
<Currency />
|
||||||
<Appearance darkMode={darkMode} />
|
<Appearance darkMode={darkMode} />
|
||||||
|
<Chain />
|
||||||
<Debug />
|
<Debug />
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { toDataUrl } from 'ethereum-blockies'
|
import { toDataUrl } from 'ethereum-blockies'
|
||||||
import React, { FormEvent } from 'react'
|
import React, { FormEvent } from 'react'
|
||||||
import { ReactComponent as Caret } from '../../../images/caret.svg'
|
import { ReactComponent as Caret } from '../../../images/caret.svg'
|
||||||
import { accountTruncate } from '../../../utils/wallet'
|
import { accountTruncate } from '../../../utils/web3'
|
||||||
import Loader from '../../atoms/Loader'
|
import Loader from '../../atoms/Loader'
|
||||||
import Status from '../../atoms/Status'
|
|
||||||
import styles from './Account.module.css'
|
import styles from './Account.module.css'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
const Blockies = ({ account }: { account: string | undefined }) => {
|
const Blockies = ({ account }: { account: string | undefined }) => {
|
||||||
if (!account) return null
|
if (!account) return null
|
||||||
@ -24,8 +23,7 @@ const Blockies = ({ account }: { account: string | undefined }) => {
|
|||||||
// Forward ref for Tippy.js
|
// Forward ref for Tippy.js
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const Account = React.forwardRef((props, ref: any) => {
|
const Account = React.forwardRef((props, ref: any) => {
|
||||||
const { accountId, status, connect, web3Modal } = useOcean()
|
const { accountId, web3Modal, connect } = useWeb3()
|
||||||
const hasSuccess = status === 1
|
|
||||||
|
|
||||||
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
async function handleActivation(e: FormEvent<HTMLButtonElement>) {
|
||||||
// prevent accidentially submitting a form the button might be in
|
// prevent accidentially submitting a form the button might be in
|
||||||
@ -50,9 +48,6 @@ const Account = React.forwardRef((props, ref: any) => {
|
|||||||
<span className={styles.address} title={accountId}>
|
<span className={styles.address} title={accountId}>
|
||||||
{accountTruncate(accountId)}
|
{accountTruncate(accountId)}
|
||||||
</span>
|
</span>
|
||||||
{!hasSuccess && (
|
|
||||||
<Status className={styles.status} state="warning" aria-hidden />
|
|
||||||
)}
|
|
||||||
<Caret aria-hidden="true" />
|
<Caret aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.symbol {
|
.symbol {
|
||||||
width: 20%;
|
width: 22%;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-weight: var(--font-weight-base);
|
font-weight: var(--font-weight-base);
|
||||||
font-size: var(--font-size-small);
|
font-size: var(--font-size-small);
|
||||||
|
@ -1,28 +1,37 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Button from '../../atoms/Button'
|
import Button from '../../atoms/Button'
|
||||||
import styles from './Details.module.css'
|
import styles from './Details.module.css'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import Web3Feedback from './Feedback'
|
import Web3Feedback from './Feedback'
|
||||||
import { getProviderInfo, IProviderInfo } from 'web3modal'
|
import { getProviderInfo, IProviderInfo } from 'web3modal'
|
||||||
import Conversion from '../../atoms/Price/Conversion'
|
import Conversion from '../../atoms/Price/Conversion'
|
||||||
import { formatCurrency } from '@coingecko/cryptoformat'
|
import { formatCurrency } from '@coingecko/cryptoformat'
|
||||||
import { useUserPreferences } from '../../../providers/UserPreferences'
|
import { useUserPreferences } from '../../../providers/UserPreferences'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
export default function Details(): ReactElement {
|
export default function Details(): ReactElement {
|
||||||
const { balance, connect, logout, web3Provider } = useOcean()
|
const { web3Provider, connect, logout, networkData, networkId } = useWeb3()
|
||||||
|
const { balance } = useOcean()
|
||||||
const { locale } = useUserPreferences()
|
const { locale } = useUserPreferences()
|
||||||
|
|
||||||
const [providerInfo, setProviderInfo] = useState<IProviderInfo>()
|
const [providerInfo, setProviderInfo] = useState<IProviderInfo>()
|
||||||
|
const [mainCurrency, setMainCurrency] = useState<string>()
|
||||||
// const [portisNetwork, setPortisNetwork] = useState<string>()
|
// const [portisNetwork, setPortisNetwork] = useState<string>()
|
||||||
|
|
||||||
// Workaround cause getInjectedProviderName() always returns `MetaMask`
|
// Workaround cause getInjectedProviderName() always returns `MetaMask`
|
||||||
// https://github.com/oceanprotocol/market/issues/332
|
// https://github.com/oceanprotocol/market/issues/332
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!web3Provider) return
|
if (!web3Provider) return
|
||||||
|
|
||||||
const providerInfo = getProviderInfo(web3Provider)
|
const providerInfo = getProviderInfo(web3Provider)
|
||||||
setProviderInfo(providerInfo)
|
setProviderInfo(providerInfo)
|
||||||
}, [web3Provider])
|
}, [web3Provider])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!networkData) return
|
||||||
|
|
||||||
|
setMainCurrency(networkData.nativeCurrency.symbol)
|
||||||
|
}, [networkData])
|
||||||
|
|
||||||
// Handle network change for Portis
|
// Handle network change for Portis
|
||||||
// async function handlePortisNetworkChange(e: ChangeEvent<HTMLSelectElement>) {
|
// async function handlePortisNetworkChange(e: ChangeEvent<HTMLSelectElement>) {
|
||||||
// setPortisNetwork(e.target.value)
|
// setPortisNetwork(e.target.value)
|
||||||
@ -38,7 +47,13 @@ export default function Details(): ReactElement {
|
|||||||
<ul>
|
<ul>
|
||||||
{Object.entries(balance).map(([key, value]) => (
|
{Object.entries(balance).map(([key, value]) => (
|
||||||
<li className={styles.balance} key={key}>
|
<li className={styles.balance} key={key}>
|
||||||
<span className={styles.symbol}>{key.toUpperCase()}</span>{' '}
|
<span className={styles.symbol}>
|
||||||
|
{key === 'eth'
|
||||||
|
? mainCurrency
|
||||||
|
: key === 'ocean' && networkId === 137
|
||||||
|
? 'mOCEAN'
|
||||||
|
: key.toUpperCase()}
|
||||||
|
</span>{' '}
|
||||||
{formatCurrency(Number(value), '', locale, false, {
|
{formatCurrency(Number(value), '', locale, false, {
|
||||||
significantFigures: 4
|
significantFigures: 4
|
||||||
})}
|
})}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import Status from '../../atoms/Status'
|
import Status from '../../atoms/Status'
|
||||||
import styles from './Feedback.module.css'
|
import styles from './Feedback.module.css'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
|
|
||||||
export declare type Web3Error = {
|
export declare type Web3Error = {
|
||||||
status: 'error' | 'warning' | 'success'
|
status: 'error' | 'warning' | 'success'
|
||||||
@ -14,10 +14,8 @@ export default function Web3Feedback({
|
|||||||
}: {
|
}: {
|
||||||
isBalanceSufficient?: boolean
|
isBalanceSufficient?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { account, status } = useOcean()
|
const { account, ocean } = useOcean()
|
||||||
const isOceanConnectionError = status === -1
|
const showFeedback = !account || !ocean || isBalanceSufficient === false
|
||||||
const showFeedback =
|
|
||||||
!account || isOceanConnectionError || isBalanceSufficient === false
|
|
||||||
|
|
||||||
const state = !account
|
const state = !account
|
||||||
? 'error'
|
? 'error'
|
||||||
@ -27,7 +25,7 @@ export default function Web3Feedback({
|
|||||||
|
|
||||||
const title = !account
|
const title = !account
|
||||||
? 'No account connected'
|
? 'No account connected'
|
||||||
: isOceanConnectionError
|
: !ocean
|
||||||
? 'Error connecting to Ocean'
|
? 'Error connecting to Ocean'
|
||||||
: account
|
: account
|
||||||
? isBalanceSufficient === false
|
? isBalanceSufficient === false
|
||||||
@ -37,7 +35,7 @@ export default function Web3Feedback({
|
|||||||
|
|
||||||
const message = !account
|
const message = !account
|
||||||
? 'Please connect your Web3 wallet.'
|
? 'Please connect your Web3 wallet.'
|
||||||
: isOceanConnectionError
|
: !ocean
|
||||||
? 'Please try again.'
|
? 'Please try again.'
|
||||||
: isBalanceSufficient === false
|
: isBalanceSufficient === false
|
||||||
? 'You do not have enough OCEAN in your wallet to purchase this asset.'
|
? 'You do not have enough OCEAN in your wallet to purchase this asset.'
|
||||||
|
@ -1,43 +1,19 @@
|
|||||||
import React, { useState, useEffect, ReactElement } from 'react'
|
import React, { useState, useEffect, ReactElement } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import Status from '../../atoms/Status'
|
import Status from '../../atoms/Status'
|
||||||
import {
|
|
||||||
EthereumListsChain,
|
|
||||||
getNetworkData,
|
|
||||||
getNetworkDisplayName
|
|
||||||
} from '../../../utils/wallet'
|
|
||||||
import { ConfigHelper } from '@oceanprotocol/lib'
|
import { ConfigHelper } from '@oceanprotocol/lib'
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
import styles from './Network.module.css'
|
import styles from './Network.module.css'
|
||||||
import Badge from '../../atoms/Badge'
|
import Badge from '../../atoms/Badge'
|
||||||
import Tooltip from '../../atoms/Tooltip'
|
import Tooltip from '../../atoms/Tooltip'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
const networksQuery = graphql`
|
|
||||||
query NetworksQuery {
|
|
||||||
allNetworksMetadataJson {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
chain
|
|
||||||
network
|
|
||||||
networkId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export default function Network(): ReactElement {
|
export default function Network(): ReactElement {
|
||||||
const data = useStaticQuery(networksQuery)
|
const { networkId, networkDisplayName, isTestnet } = useWeb3()
|
||||||
const networksList: { node: EthereumListsChain }[] =
|
const { config } = useOcean()
|
||||||
data.allNetworksMetadataJson.edges
|
|
||||||
|
|
||||||
const { config, networkId } = useOcean()
|
|
||||||
const networkIdConfig = (config as ConfigHelperConfig).networkId
|
const networkIdConfig = (config as ConfigHelperConfig).networkId
|
||||||
|
|
||||||
const [isEthMainnet, setIsEthMainnet] = useState<boolean>()
|
const [isEthMainnet, setIsEthMainnet] = useState<boolean>()
|
||||||
const [networkName, setNetworkName] = useState<string>()
|
|
||||||
const [isTestnet, setIsTestnet] = useState<boolean>()
|
|
||||||
const [isSupportedNetwork, setIsSupportedNetwork] = useState<boolean>()
|
const [isSupportedNetwork, setIsSupportedNetwork] = useState<boolean>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -51,23 +27,16 @@ export default function Network(): ReactElement {
|
|||||||
// to figure out if network is supported.
|
// to figure out if network is supported.
|
||||||
const isSupportedNetwork = Boolean(new ConfigHelper().getConfig(network))
|
const isSupportedNetwork = Boolean(new ConfigHelper().getConfig(network))
|
||||||
setIsSupportedNetwork(isSupportedNetwork)
|
setIsSupportedNetwork(isSupportedNetwork)
|
||||||
|
}, [networkId, networkIdConfig])
|
||||||
|
|
||||||
// Figure out if we're on a chain's testnet, or not
|
return !isEthMainnet && networkDisplayName ? (
|
||||||
const networkData = getNetworkData(networksList, network)
|
|
||||||
setIsTestnet(networkData.network !== 'mainnet')
|
|
||||||
|
|
||||||
const networkName = getNetworkDisplayName(networkData, network)
|
|
||||||
setNetworkName(networkName)
|
|
||||||
}, [networkId, networkIdConfig, networksList])
|
|
||||||
|
|
||||||
return !isEthMainnet && networkName ? (
|
|
||||||
<div className={styles.network}>
|
<div className={styles.network}>
|
||||||
{!isSupportedNetwork && (
|
{!isSupportedNetwork && (
|
||||||
<Tooltip content="No Ocean Protocol contracts are deployed to this network.">
|
<Tooltip content="No Ocean Protocol contracts are deployed to this network.">
|
||||||
<Status state="error" className={styles.warning} />
|
<Status state="error" className={styles.warning} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<span className={styles.name}>{networkName}</span>
|
<span className={styles.name}>{networkDisplayName}</span>
|
||||||
{isTestnet && <Badge label="Test" className={styles.badge} />}
|
{isTestnet && <Badge label="Test" className={styles.badge} />}
|
||||||
</div>
|
</div>
|
||||||
) : null
|
) : null
|
||||||
|
@ -3,11 +3,11 @@ import Account from './Account'
|
|||||||
import Details from './Details'
|
import Details from './Details'
|
||||||
import Tooltip from '../../atoms/Tooltip'
|
import Tooltip from '../../atoms/Tooltip'
|
||||||
import Network from './Network'
|
import Network from './Network'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
export default function Wallet(): ReactElement {
|
export default function Wallet(): ReactElement {
|
||||||
const { accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wallet}>
|
<div className={styles.wallet}>
|
||||||
|
@ -1,22 +1,18 @@
|
|||||||
import React, { useState, ReactElement, ChangeEvent, useEffect } from 'react'
|
import React, { useState, ReactElement, ChangeEvent, useEffect } from 'react'
|
||||||
import { DDO, Logger } from '@oceanprotocol/lib'
|
import { DDO } from '@oceanprotocol/lib'
|
||||||
import Loader from '../../atoms/Loader'
|
import Loader from '../../atoms/Loader'
|
||||||
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
||||||
import Dropzone from '../../atoms/Dropzone'
|
|
||||||
import Price from '../../atoms/Price'
|
import Price from '../../atoms/Price'
|
||||||
import File from '../../atoms/File'
|
import File from '../../atoms/File'
|
||||||
import {
|
import { computeOptions, useCompute } from '../../../hooks/useCompute'
|
||||||
computeOptions,
|
|
||||||
useCompute,
|
|
||||||
readFileContent,
|
|
||||||
useOcean,
|
|
||||||
usePricing
|
|
||||||
} from '@oceanprotocol/react'
|
|
||||||
import styles from './Compute.module.css'
|
import styles from './Compute.module.css'
|
||||||
import Input from '../../atoms/Input'
|
import Input from '../../atoms/Input'
|
||||||
import Alert from '../../atoms/Alert'
|
import Alert from '../../atoms/Alert'
|
||||||
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
||||||
import checkPreviousOrder from '../../../utils/checkPreviousOrder'
|
import checkPreviousOrder from '../../../utils/checkPreviousOrder'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import { usePricing } from '../../../hooks/usePricing'
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
|
|
||||||
export default function Compute({
|
export default function Compute({
|
||||||
@ -29,12 +25,12 @@ export default function Compute({
|
|||||||
dtBalance: string
|
dtBalance: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { marketFeeAddress } = useSiteMetadata()
|
const { marketFeeAddress } = useSiteMetadata()
|
||||||
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const { type } = useAsset()
|
const { type } = useAsset()
|
||||||
const { ocean, accountId } = useOcean()
|
|
||||||
const { compute, isLoading, computeStepText, computeError } = useCompute()
|
const { compute, isLoading, computeStepText, computeError } = useCompute()
|
||||||
const { buyDT, dtSymbol } = usePricing(ddo)
|
const { buyDT, dtSymbol } = usePricing(ddo)
|
||||||
|
const { price } = useAsset()
|
||||||
const computeService = ddo.findServiceByType('compute')
|
const computeService = ddo.findServiceByType('compute')
|
||||||
const metadataService = ddo.findServiceByType('metadata')
|
const metadataService = ddo.findServiceByType('metadata')
|
||||||
|
|
||||||
@ -68,12 +64,6 @@ export default function Compute({
|
|||||||
checkPreviousOrders()
|
checkPreviousOrders()
|
||||||
}, [ocean, ddo, accountId])
|
}, [ocean, ddo, accountId])
|
||||||
|
|
||||||
const onDrop = async (files: File[]) => {
|
|
||||||
setFile(files[0])
|
|
||||||
const fileText = await readFileContent(files[0])
|
|
||||||
setAlgorithmRawCode(fileText)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSelectChange = (event: ChangeEvent<HTMLSelectElement>) => {
|
const handleSelectChange = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||||
const comType = event.target.value
|
const comType = event.target.value
|
||||||
setComputeType(comType)
|
setComputeType(comType)
|
||||||
@ -83,36 +73,36 @@ export default function Compute({
|
|||||||
setComputeContainer(selectedComputeOption.value)
|
setComputeContainer(selectedComputeOption.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const startJob = async () => {
|
// const startJob = async () => {
|
||||||
try {
|
// try {
|
||||||
if (!ocean) return
|
// if (!ocean) return
|
||||||
|
|
||||||
setIsJobStarting(true)
|
// setIsJobStarting(true)
|
||||||
setIsPublished(false)
|
// setIsPublished(false)
|
||||||
setError('')
|
// setError('')
|
||||||
|
|
||||||
!hasPreviousOrder && !hasDatatoken && (await buyDT('1'))
|
// !hasPreviousOrder && !hasDatatoken && (await buyDT('1'))
|
||||||
|
|
||||||
await compute(
|
// await compute(
|
||||||
ddo.id,
|
// ddo.id,
|
||||||
computeService,
|
// computeService,
|
||||||
ddo.dataToken,
|
// ddo.dataToken,
|
||||||
algorithmRawCode,
|
// algorithmRawCode,
|
||||||
computeContainer,
|
// computeContainer,
|
||||||
marketFeeAddress,
|
// marketFeeAddress,
|
||||||
previousOrderId
|
// previousOrderId
|
||||||
)
|
// )
|
||||||
|
|
||||||
setHasPreviousOrder(true)
|
// setHasPreviousOrder(true)
|
||||||
setIsPublished(true)
|
// setIsPublished(true)
|
||||||
setFile(null)
|
// setFile(null)
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
setError('Failed to start job!')
|
// setError('Failed to start job!')
|
||||||
Logger.error(error.message)
|
// Logger.error(error.message)
|
||||||
} finally {
|
// } finally {
|
||||||
setIsJobStarting(false)
|
// setIsJobStarting(false)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -121,7 +111,7 @@ export default function Compute({
|
|||||||
<File file={metadataService.attributes.main.files[0]} small />
|
<File file={metadataService.attributes.main.files[0]} small />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.pricewrapper}>
|
<div className={styles.pricewrapper}>
|
||||||
<Price ddo={ddo} conversion />
|
<Price price={price} conversion />
|
||||||
{hasDatatoken && (
|
{hasDatatoken && (
|
||||||
<div className={styles.hasTokens}>
|
<div className={styles.hasTokens}>
|
||||||
You own {dtBalance} {dtSymbol} allowing you to use this data set
|
You own {dtBalance} {dtSymbol} allowing you to use this data set
|
||||||
@ -154,7 +144,6 @@ export default function Compute({
|
|||||||
onChange={handleSelectChange}
|
onChange={handleSelectChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Dropzone multiple={false} handleOnDrop={onDrop} />
|
|
||||||
|
|
||||||
<div className={styles.actions}>
|
<div className={styles.actions}>
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
|
@ -7,14 +7,16 @@ import Price from '../../atoms/Price'
|
|||||||
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
||||||
import styles from './Consume.module.css'
|
import styles from './Consume.module.css'
|
||||||
import Loader from '../../atoms/Loader'
|
import Loader from '../../atoms/Loader'
|
||||||
import { useOcean, useConsume, usePricing } from '@oceanprotocol/react'
|
|
||||||
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
||||||
import checkPreviousOrder from '../../../utils/checkPreviousOrder'
|
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
import { secondsToString } from '../../../utils/metadata'
|
import { secondsToString } from '../../../utils/metadata'
|
||||||
import { gql, useQuery } from '@apollo/client'
|
import { gql, useQuery } from '@apollo/client'
|
||||||
import { OrdersData } from '../../../@types/apollo/OrdersData'
|
import { OrdersData } from '../../../@types/apollo/OrdersData'
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import { usePricing } from '../../../hooks/usePricing'
|
||||||
|
import { useConsume } from '../../../hooks/useConsume'
|
||||||
|
|
||||||
const previousOrderQuery = gql`
|
const previousOrderQuery = gql`
|
||||||
query PreviousOrder($id: String!, $account: String!) {
|
query PreviousOrder($id: String!, $account: String!) {
|
||||||
@ -61,7 +63,8 @@ export default function Consume({
|
|||||||
isBalanceSufficient: boolean
|
isBalanceSufficient: boolean
|
||||||
dtBalance: string
|
dtBalance: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { ocean, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const { marketFeeAddress } = useSiteMetadata()
|
const { marketFeeAddress } = useSiteMetadata()
|
||||||
const [hasPreviousOrder, setHasPreviousOrder] = useState(false)
|
const [hasPreviousOrder, setHasPreviousOrder] = useState(false)
|
||||||
const [previousOrderId, setPreviousOrderId] = useState<string>()
|
const [previousOrderId, setPreviousOrderId] = useState<string>()
|
||||||
@ -141,7 +144,7 @@ export default function Consume({
|
|||||||
])
|
])
|
||||||
|
|
||||||
async function handleConsume() {
|
async function handleConsume() {
|
||||||
!hasPreviousOrder && !hasDatatoken && (await buyDT('1'))
|
!hasPreviousOrder && !hasDatatoken && (await buyDT('1', price))
|
||||||
await consume(
|
await consume(
|
||||||
ddo.id,
|
ddo.id,
|
||||||
ddo.dataToken,
|
ddo.dataToken,
|
||||||
@ -191,7 +194,7 @@ export default function Consume({
|
|||||||
<File file={file} />
|
<File file={file} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.pricewrapper}>
|
<div className={styles.pricewrapper}>
|
||||||
<Price ddo={ddo} conversion />
|
<Price price={price} conversion />
|
||||||
{!isInPurgatory && <PurchaseButton />}
|
{!isInPurgatory && <PurchaseButton />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -3,10 +3,11 @@ import styles from './FormEditMetadata.module.css'
|
|||||||
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
import { Field, Form, FormikContextType, useFormikContext } from 'formik'
|
||||||
import Button from '../../../atoms/Button'
|
import Button from '../../../atoms/Button'
|
||||||
import Input from '../../../atoms/Input'
|
import Input from '../../../atoms/Input'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { FormFieldProps } from '../../../../@types/Form'
|
import { FormFieldProps } from '../../../../@types/Form'
|
||||||
import { MetadataPublishFormDataset } from '../../../../@types/MetaData'
|
import { MetadataPublishFormDataset } from '../../../../@types/MetaData'
|
||||||
import { checkIfTimeoutInPredefinedValues } from '../../../../utils/metadata'
|
import { checkIfTimeoutInPredefinedValues } from '../../../../utils/metadata'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
|
||||||
function handleTimeoutCustomOption(
|
function handleTimeoutCustomOption(
|
||||||
data: FormFieldProps[],
|
data: FormFieldProps[],
|
||||||
@ -53,7 +54,8 @@ export default function FormEditMetadata({
|
|||||||
setTimeoutStringValue: (value: string) => void
|
setTimeoutStringValue: (value: string) => void
|
||||||
values: Partial<MetadataPublishFormDataset>
|
values: Partial<MetadataPublishFormDataset>
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { ocean, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const {
|
const {
|
||||||
isValid,
|
isValid,
|
||||||
validateField,
|
validateField,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { Formik } from 'formik'
|
import { Formik } from 'formik'
|
||||||
import React, { ReactElement, useState } from 'react'
|
import React, { ReactElement, useState } from 'react'
|
||||||
import { MetadataEditForm } from '../../../../@types/MetaData'
|
import { MetadataEditForm } from '../../../../@types/MetaData'
|
||||||
@ -17,6 +16,8 @@ import styles from './index.module.css'
|
|||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import MetadataFeedback from '../../../molecules/MetadataFeedback'
|
import MetadataFeedback from '../../../molecules/MetadataFeedback'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query EditMetadataQuery {
|
query EditMetadataQuery {
|
||||||
@ -57,7 +58,8 @@ export default function Edit({
|
|||||||
const content = data.content.edges[0].node.childPagesJson
|
const content = data.content.edges[0].node.childPagesJson
|
||||||
|
|
||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
const { ocean, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const { metadata, ddo, refreshDdo } = useAsset()
|
const { metadata, ddo, refreshDdo } = useAsset()
|
||||||
const [success, setSuccess] = useState<string>()
|
const [success, setSuccess] = useState<string>()
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
|
@ -2,9 +2,10 @@ import React, { ReactElement } from 'react'
|
|||||||
import Loader from '../../../atoms/Loader'
|
import Loader from '../../../atoms/Loader'
|
||||||
import Button from '../../../atoms/Button'
|
import Button from '../../../atoms/Button'
|
||||||
import styles from './Actions.module.css'
|
import styles from './Actions.module.css'
|
||||||
import EtherscanLink from '../../../atoms/EtherscanLink'
|
import ExplorerLink from '../../../atoms/ExplorerLink'
|
||||||
import SuccessConfetti from '../../../atoms/SuccessConfetti'
|
import SuccessConfetti from '../../../atoms/SuccessConfetti'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
|
||||||
export default function Actions({
|
export default function Actions({
|
||||||
isLoading,
|
isLoading,
|
||||||
@ -23,7 +24,8 @@ export default function Actions({
|
|||||||
action: () => void
|
action: () => void
|
||||||
isDisabled?: boolean
|
isDisabled?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { networkId, ocean } = useOcean()
|
const { networkId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -46,9 +48,9 @@ export default function Actions({
|
|||||||
className={styles.success}
|
className={styles.success}
|
||||||
success={successMessage}
|
success={successMessage}
|
||||||
action={
|
action={
|
||||||
<EtherscanLink networkId={networkId} path={`/tx/${txId}`}>
|
<ExplorerLink networkId={networkId} path={`/tx/${txId}`}>
|
||||||
See on Etherscan
|
View transaction
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
@ -10,9 +10,9 @@ import {
|
|||||||
import Button from '../../../../atoms/Button'
|
import Button from '../../../../atoms/Button'
|
||||||
import CoinSelect from '../CoinSelect'
|
import CoinSelect from '../CoinSelect'
|
||||||
import { FormAddLiquidity } from '.'
|
import { FormAddLiquidity } from '.'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { PoolBalance } from '../../../../../@types/TokenBalance'
|
||||||
import TokenBalance from '../../../../../@types/TokenBalance'
|
|
||||||
import UserLiquidity from '../../../../atoms/UserLiquidity'
|
import UserLiquidity from '../../../../atoms/UserLiquidity'
|
||||||
|
import { useOcean } from '../../../../../providers/Ocean'
|
||||||
|
|
||||||
export default function FormAdd({
|
export default function FormAdd({
|
||||||
coin,
|
coin,
|
||||||
@ -32,7 +32,7 @@ export default function FormAdd({
|
|||||||
amountMax: string
|
amountMax: string
|
||||||
setCoin: (value: string) => void
|
setCoin: (value: string) => void
|
||||||
totalPoolTokens: string
|
totalPoolTokens: string
|
||||||
totalBalance: TokenBalance
|
totalBalance: PoolBalance
|
||||||
poolAddress: string
|
poolAddress: string
|
||||||
setNewPoolTokens: (value: string) => void
|
setNewPoolTokens: (value: string) => void
|
||||||
setNewPoolShare: (value: string) => void
|
setNewPoolShare: (value: string) => void
|
||||||
|
@ -2,7 +2,7 @@ import { FormikContextType, useFormikContext } from 'formik'
|
|||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { FormAddLiquidity } from '.'
|
import { FormAddLiquidity } from '.'
|
||||||
import TokenBalance from '../../../../../@types/TokenBalance'
|
import { PoolBalance } from '../../../../../@types/TokenBalance'
|
||||||
import FormHelp from '../../../../atoms/Input/Help'
|
import FormHelp from '../../../../atoms/Input/Help'
|
||||||
import Token from '../Token'
|
import Token from '../Token'
|
||||||
import styles from './Output.module.css'
|
import styles from './Output.module.css'
|
||||||
@ -44,7 +44,7 @@ export default function Output({
|
|||||||
swapFee: string
|
swapFee: string
|
||||||
dtSymbol: string
|
dtSymbol: string
|
||||||
totalPoolTokens: string
|
totalPoolTokens: string
|
||||||
totalBalance: TokenBalance
|
totalBalance: PoolBalance
|
||||||
coin: string
|
coin: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { ReactElement, useState, useEffect } from 'react'
|
import React, { ReactElement, useState, useEffect } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import Header from '../Header'
|
import Header from '../Header'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import Actions from '../Actions'
|
import Actions from '../Actions'
|
||||||
@ -9,10 +8,12 @@ import { Formik } from 'formik'
|
|||||||
import FormAdd from './FormAdd'
|
import FormAdd from './FormAdd'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import Alert from '../../../../atoms/Alert'
|
import Alert from '../../../../atoms/Alert'
|
||||||
import TokenBalance from '../../../../../@types/TokenBalance'
|
import { PoolBalance } from '../../../../../@types/TokenBalance'
|
||||||
import { useUserPreferences } from '../../../../../providers/UserPreferences'
|
import { useUserPreferences } from '../../../../../providers/UserPreferences'
|
||||||
import Output from './Output'
|
import Output from './Output'
|
||||||
import DebugOutput from '../../../../atoms/DebugOutput'
|
import DebugOutput from '../../../../atoms/DebugOutput'
|
||||||
|
import { useOcean } from '../../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../../providers/Web3'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query PoolAddQuery {
|
query PoolAddQuery {
|
||||||
@ -56,7 +57,7 @@ export default function Add({
|
|||||||
refreshInfo: () => void
|
refreshInfo: () => void
|
||||||
poolAddress: string
|
poolAddress: string
|
||||||
totalPoolTokens: string
|
totalPoolTokens: string
|
||||||
totalBalance: TokenBalance
|
totalBalance: PoolBalance
|
||||||
swapFee: string
|
swapFee: string
|
||||||
dtSymbol: string
|
dtSymbol: string
|
||||||
dtAddress: string
|
dtAddress: string
|
||||||
@ -64,7 +65,8 @@ export default function Add({
|
|||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const content = data.content.edges[0].node.childContentJson.pool.add
|
const content = data.content.edges[0].node.childContentJson.pool.add
|
||||||
|
|
||||||
const { ocean, accountId, balance } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean, balance } = useOcean()
|
||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
const [txId, setTxId] = useState<string>()
|
const [txId, setTxId] = useState<string>()
|
||||||
const [coin, setCoin] = useState('OCEAN')
|
const [coin, setCoin] = useState('OCEAN')
|
||||||
|
@ -7,7 +7,6 @@ import React, {
|
|||||||
useRef
|
useRef
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import styles from './Remove.module.css'
|
import styles from './Remove.module.css'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import Header from './Header'
|
import Header from './Header'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import Actions from './Actions'
|
import Actions from './Actions'
|
||||||
@ -19,6 +18,8 @@ import { getMaxPercentRemove } from './utils'
|
|||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
import UserLiquidity from '../../../atoms/UserLiquidity'
|
import UserLiquidity from '../../../atoms/UserLiquidity'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query PoolRemoveQuery {
|
query PoolRemoveQuery {
|
||||||
@ -63,7 +64,8 @@ export default function Remove({
|
|||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const content = data.content.edges[0].node.childContentJson.pool.remove
|
const content = data.content.edges[0].node.childContentJson.pool.remove
|
||||||
|
|
||||||
const { ocean, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const [amountPercent, setAmountPercent] = useState('0')
|
const [amountPercent, setAmountPercent] = useState('0')
|
||||||
const [amountMaxPercent, setAmountMaxPercent] = useState('100')
|
const [amountMaxPercent, setAmountMaxPercent] = useState('100')
|
||||||
const [amountPoolShares, setAmountPoolShares] = useState('0')
|
const [amountPoolShares, setAmountPoolShares] = useState('0')
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import stylesActions from './Actions.module.css'
|
import stylesActions from './Actions.module.css'
|
||||||
@ -8,16 +7,18 @@ import Button from '../../../atoms/Button'
|
|||||||
import Add from './Add'
|
import Add from './Add'
|
||||||
import Remove from './Remove'
|
import Remove from './Remove'
|
||||||
import Tooltip from '../../../atoms/Tooltip'
|
import Tooltip from '../../../atoms/Tooltip'
|
||||||
import EtherscanLink from '../../../atoms/EtherscanLink'
|
import ExplorerLink from '../../../atoms/ExplorerLink'
|
||||||
import Token from './Token'
|
import Token from './Token'
|
||||||
import TokenList from './TokenList'
|
import TokenList from './TokenList'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import TokenBalance from '../../../../@types/TokenBalance'
|
import { PoolBalance } from '../../../../@types/TokenBalance'
|
||||||
import Transactions from './Transactions'
|
import Transactions from './Transactions'
|
||||||
import Graph from './Graph'
|
import Graph from './Graph'
|
||||||
import { useAsset } from '../../../../providers/Asset'
|
import { useAsset } from '../../../../providers/Asset'
|
||||||
import { gql, useQuery } from '@apollo/client'
|
import { gql, useQuery } from '@apollo/client'
|
||||||
import { PoolLiquidity } from '../../../../@types/apollo/PoolLiquidity'
|
import { PoolLiquidity } from '../../../../@types/apollo/PoolLiquidity'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query PoolQuery {
|
query PoolQuery {
|
||||||
@ -60,20 +61,14 @@ export default function Pool(): ReactElement {
|
|||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const content = data.content.edges[0].node.childContentJson.pool
|
const content = data.content.edges[0].node.childContentJson.pool
|
||||||
|
|
||||||
const { ocean, accountId, networkId } = useOcean()
|
const { accountId, networkId } = useWeb3()
|
||||||
const {
|
const { ocean } = useOcean()
|
||||||
isInPurgatory,
|
const { isInPurgatory, ddo, owner, price, refreshInterval } = useAsset()
|
||||||
ddo,
|
|
||||||
owner,
|
|
||||||
price,
|
|
||||||
refreshInterval,
|
|
||||||
refreshPrice
|
|
||||||
} = useAsset()
|
|
||||||
const dtSymbol = ddo?.dataTokenInfo.symbol
|
const dtSymbol = ddo?.dataTokenInfo.symbol
|
||||||
|
|
||||||
const [poolTokens, setPoolTokens] = useState<string>()
|
const [poolTokens, setPoolTokens] = useState<string>()
|
||||||
const [totalPoolTokens, setTotalPoolTokens] = useState<string>()
|
const [totalPoolTokens, setTotalPoolTokens] = useState<string>()
|
||||||
const [userLiquidity, setUserLiquidity] = useState<TokenBalance>()
|
const [userLiquidity, setUserLiquidity] = useState<PoolBalance>()
|
||||||
const [swapFee, setSwapFee] = useState<string>()
|
const [swapFee, setSwapFee] = useState<string>()
|
||||||
const [weightOcean, setWeightOcean] = useState<string>()
|
const [weightOcean, setWeightOcean] = useState<string>()
|
||||||
const [weightDt, setWeightDt] = useState<string>()
|
const [weightDt, setWeightDt] = useState<string>()
|
||||||
@ -91,7 +86,7 @@ export default function Pool(): ReactElement {
|
|||||||
creatorTotalLiquidityInOcean,
|
creatorTotalLiquidityInOcean,
|
||||||
setCreatorTotalLiquidityInOcean
|
setCreatorTotalLiquidityInOcean
|
||||||
] = useState(0)
|
] = useState(0)
|
||||||
const [creatorLiquidity, setCreatorLiquidity] = useState<TokenBalance>()
|
const [creatorLiquidity, setCreatorLiquidity] = useState<PoolBalance>()
|
||||||
const [creatorPoolTokens, setCreatorPoolTokens] = useState<string>()
|
const [creatorPoolTokens, setCreatorPoolTokens] = useState<string>()
|
||||||
const [creatorPoolShare, setCreatorPoolShare] = useState<string>()
|
const [creatorPoolShare, setCreatorPoolShare] = useState<string>()
|
||||||
|
|
||||||
@ -209,7 +204,9 @@ export default function Pool(): ReactElement {
|
|||||||
|
|
||||||
const refreshInfo = async () => {
|
const refreshInfo = async () => {
|
||||||
setRefreshPool(!refreshPool)
|
setRefreshPool(!refreshPool)
|
||||||
await refreshPrice()
|
|
||||||
|
// need some form of replacement or something.
|
||||||
|
// await refreshPrice()
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -244,18 +241,22 @@ export default function Pool(): ReactElement {
|
|||||||
<PriceUnit price={`${price?.value}`} />
|
<PriceUnit price={`${price?.value}`} />
|
||||||
<Tooltip content={content.tooltips.price} />
|
<Tooltip content={content.tooltips.price} />
|
||||||
<div className={styles.dataTokenLinks}>
|
<div className={styles.dataTokenLinks}>
|
||||||
<EtherscanLink
|
<ExplorerLink
|
||||||
networkId={networkId}
|
networkId={networkId}
|
||||||
path={`address/${price?.address}`}
|
path={`address/${price?.address}`}
|
||||||
>
|
>
|
||||||
Pool
|
Pool
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
<EtherscanLink
|
<ExplorerLink
|
||||||
networkId={networkId}
|
networkId={networkId}
|
||||||
path={`token/${ddo.dataToken}`}
|
path={
|
||||||
|
networkId === 137
|
||||||
|
? `tokens/${ddo.dataToken}`
|
||||||
|
: `token/${ddo.dataToken}`
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Datatoken
|
Datatoken
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { ReactElement, useState } from 'react'
|
import React, { ReactElement, useState } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { BestPrice, DDO, Logger } from '@oceanprotocol/lib'
|
import { BestPrice, DDO, Logger } from '@oceanprotocol/lib'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { Formik } from 'formik'
|
import { Formik } from 'formik'
|
||||||
@ -8,11 +7,13 @@ import { graphql, useStaticQuery } from 'gatsby'
|
|||||||
import { useUserPreferences } from '../../../../providers/UserPreferences'
|
import { useUserPreferences } from '../../../../providers/UserPreferences'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import Swap from './Swap'
|
import Swap from './Swap'
|
||||||
import TokenBalance from '../../../../@types/TokenBalance'
|
import { PoolBalance } from '../../../../@types/TokenBalance'
|
||||||
import Alert from '../../../atoms/Alert'
|
import Alert from '../../../atoms/Alert'
|
||||||
import styles from './FormTrade.module.css'
|
import styles from './FormTrade.module.css'
|
||||||
import { FormTradeData, initialValues } from '../../../../models/FormTrade'
|
import { FormTradeData, initialValues } from '../../../../models/FormTrade'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query TradeQuery {
|
query TradeQuery {
|
||||||
@ -39,14 +40,15 @@ export default function FormTrade({
|
|||||||
price
|
price
|
||||||
}: {
|
}: {
|
||||||
ddo: DDO
|
ddo: DDO
|
||||||
balance: TokenBalance
|
balance: PoolBalance
|
||||||
maxDt: number
|
maxDt: number
|
||||||
maxOcean: number
|
maxOcean: number
|
||||||
price: BestPrice
|
price: BestPrice
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const content = data.content.edges[0].node.childContentJson.trade
|
const content = data.content.edges[0].node.childContentJson.trade
|
||||||
const { ocean, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean } = useOcean()
|
||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
const [txId, setTxId] = useState<string>()
|
const [txId, setTxId] = useState<string>()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { FormikContextType, useFormikContext } from 'formik'
|
import { FormikContextType, useFormikContext } from 'formik'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { FormTradeData } from '../../../../models/FormTrade'
|
import { FormTradeData } from '../../../../models/FormTrade'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
import Token from '../Pool/Token'
|
import Token from '../Pool/Token'
|
||||||
import styles from './Output.module.css'
|
import styles from './Output.module.css'
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { BestPrice, DDO } from '@oceanprotocol/lib'
|
import { BestPrice, DDO } from '@oceanprotocol/lib'
|
||||||
import styles from './Swap.module.css'
|
import styles from './Swap.module.css'
|
||||||
import TradeInput from './TradeInput'
|
import TradeInput from './TradeInput'
|
||||||
import Button from '../../../atoms/Button'
|
import Button from '../../../atoms/Button'
|
||||||
import { ReactComponent as Arrow } from '../../../../images/arrow.svg'
|
import { ReactComponent as Arrow } from '../../../../images/arrow.svg'
|
||||||
import { FormikContextType, useFormikContext } from 'formik'
|
import { FormikContextType, useFormikContext } from 'formik'
|
||||||
import TokenBalance from '../../../../@types/TokenBalance'
|
import { PoolBalance } from '../../../../@types/TokenBalance'
|
||||||
import Output from './Output'
|
import Output from './Output'
|
||||||
import Slippage from './Slippage'
|
import Slippage from './Slippage'
|
||||||
import { FormTradeData, TradeItem } from '../../../../models/FormTrade'
|
import { FormTradeData, TradeItem } from '../../../../models/FormTrade'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
|
||||||
export default function Swap({
|
export default function Swap({
|
||||||
ddo,
|
ddo,
|
||||||
@ -23,7 +23,7 @@ export default function Swap({
|
|||||||
ddo: DDO
|
ddo: DDO
|
||||||
maxDt: number
|
maxDt: number
|
||||||
maxOcean: number
|
maxOcean: number
|
||||||
balance: TokenBalance
|
balance: PoolBalance
|
||||||
price: BestPrice
|
price: BestPrice
|
||||||
setMaximumDt: (value: number) => void
|
setMaximumDt: (value: number) => void
|
||||||
setMaximumOcean: (value: number) => void
|
setMaximumOcean: (value: number) => void
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
import React, { ChangeEvent, ReactElement } from 'react'
|
import React, { ChangeEvent, ReactElement } from 'react'
|
||||||
import styles from './TradeInput.module.css'
|
import styles from './TradeInput.module.css'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Field,
|
Field,
|
||||||
FieldInputProps,
|
FieldInputProps,
|
||||||
FormikContextType,
|
FormikContextType,
|
||||||
useFormikContext
|
useFormikContext
|
||||||
} from 'formik'
|
} from 'formik'
|
||||||
|
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import Input from '../../../atoms/Input'
|
import Input from '../../../atoms/Input'
|
||||||
import Button from '../../../atoms/Button'
|
import Button from '../../../atoms/Button'
|
||||||
import UserLiquidity from '../../../atoms/UserLiquidity'
|
import UserLiquidity from '../../../atoms/UserLiquidity'
|
||||||
import { FormTradeData, TradeItem } from '../../../../models/FormTrade'
|
import { FormTradeData, TradeItem } from '../../../../models/FormTrade'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
|
||||||
export default function TradeInput({
|
export default function TradeInput({
|
||||||
name,
|
name,
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import FormTrade from './FormTrade'
|
import FormTrade from './FormTrade'
|
||||||
import TokenBalance from '../../../../@types/TokenBalance'
|
import { PoolBalance } from '../../../../@types/TokenBalance'
|
||||||
import { useAsset } from '../../../../providers/Asset'
|
import { useAsset } from '../../../../providers/Asset'
|
||||||
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
|
|
||||||
export default function Trade(): ReactElement {
|
export default function Trade(): ReactElement {
|
||||||
const { ocean, balance, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
const [tokenBalance, setTokenBalance] = useState<TokenBalance>()
|
const { ocean, balance } = useOcean()
|
||||||
|
const [tokenBalance, setTokenBalance] = useState<PoolBalance>()
|
||||||
const { price, ddo } = useAsset()
|
const { price, ddo } = useAsset()
|
||||||
const [maxDt, setMaxDt] = useState(0)
|
const [maxDt, setMaxDt] = useState(0)
|
||||||
const [maxOcean, setMaxOcean] = useState(0)
|
const [maxOcean, setMaxOcean] = useState(0)
|
||||||
|
@ -4,14 +4,16 @@ import Compute from './Compute'
|
|||||||
import Consume from './Consume'
|
import Consume from './Consume'
|
||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import Tabs from '../../atoms/Tabs'
|
import Tabs from '../../atoms/Tabs'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import compareAsBN from '../../../utils/compareAsBN'
|
import compareAsBN from '../../../utils/compareAsBN'
|
||||||
import Pool from './Pool'
|
import Pool from './Pool'
|
||||||
import Trade from './Trade'
|
import Trade from './Trade'
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
export default function AssetActions(): ReactElement {
|
export default function AssetActions(): ReactElement {
|
||||||
const { ocean, balance, accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean, balance, account } = useOcean()
|
||||||
const { price, ddo, metadata } = useAsset()
|
const { price, ddo, metadata } = useAsset()
|
||||||
|
|
||||||
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>()
|
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>()
|
||||||
@ -39,7 +41,7 @@ export default function AssetActions(): ReactElement {
|
|||||||
|
|
||||||
// Check user balance against price
|
// Check user balance against price
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!price?.value || !accountId || !balance?.ocean || !dtBalance) return
|
if (!price?.value || !account || !balance?.ocean || !dtBalance) return
|
||||||
|
|
||||||
setIsBalanceSufficient(
|
setIsBalanceSufficient(
|
||||||
compareAsBN(balance.ocean, `${price.value}`) || Number(dtBalance) >= 1
|
compareAsBN(balance.ocean, `${price.value}`) || Number(dtBalance) >= 1
|
||||||
@ -48,7 +50,7 @@ export default function AssetActions(): ReactElement {
|
|||||||
return () => {
|
return () => {
|
||||||
setIsBalanceSufficient(false)
|
setIsBalanceSufficient(false)
|
||||||
}
|
}
|
||||||
}, [balance, accountId, price, dtBalance])
|
}, [balance, account, price, dtBalance])
|
||||||
|
|
||||||
const UseContent = isCompute ? (
|
const UseContent = isCompute ? (
|
||||||
<Compute
|
<Compute
|
||||||
|
@ -2,8 +2,8 @@ import { useUserPreferences } from '../../../providers/UserPreferences'
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import styles from './Bookmark.module.css'
|
import styles from './Bookmark.module.css'
|
||||||
import { ReactComponent as BookmarkIcon } from '../../../images/bookmark.svg'
|
import { ReactComponent as BookmarkIcon } from '../../../images/bookmark.svg'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
|
||||||
export default function Bookmark({ did }: { did: string }): ReactElement {
|
export default function Bookmark({ did }: { did: string }): ReactElement {
|
||||||
const { config } = useOcean()
|
const { config } = useOcean()
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
import EtherscanLink from '../../atoms/EtherscanLink'
|
import ExplorerLink from '../../atoms/ExplorerLink'
|
||||||
import Time from '../../atoms/Time'
|
import Time from '../../atoms/Time'
|
||||||
import styles from './EditHistory.module.css'
|
import styles from './EditHistory.module.css'
|
||||||
import { gql, useQuery } from '@apollo/client'
|
import { gql, useQuery } from '@apollo/client'
|
||||||
import { ReceiptData_datatokens_updates as ReceiptData } from '../../../@types/apollo/ReceiptData'
|
import { ReceiptData_datatokens_updates as ReceiptData } from '../../../@types/apollo/ReceiptData'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
const getReceipts = gql`
|
const getReceipts = gql`
|
||||||
query ReceiptData($address: ID!) {
|
query ReceiptData($address: ID!) {
|
||||||
datatokens(where: { id: $address }) {
|
datatokens(where: { id: $address }) {
|
||||||
createTime
|
|
||||||
tx
|
|
||||||
updates(orderBy: timestamp, orderDirection: desc) {
|
updates(orderBy: timestamp, orderDirection: desc) {
|
||||||
id
|
id
|
||||||
tx
|
tx
|
||||||
@ -22,7 +20,7 @@ const getReceipts = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
export default function EditHistory(): ReactElement {
|
export default function EditHistory(): ReactElement {
|
||||||
const { networkId } = useOcean()
|
const { networkId } = useWeb3()
|
||||||
const { ddo } = useAsset()
|
const { ddo } = useAsset()
|
||||||
const { data } = useQuery(getReceipts, {
|
const { data } = useQuery(getReceipts, {
|
||||||
variables: { address: ddo?.dataToken.toLowerCase() }
|
variables: { address: ddo?.dataToken.toLowerCase() }
|
||||||
@ -33,8 +31,15 @@ export default function EditHistory(): ReactElement {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!data || data.datatokens.length === 0) return
|
if (!data || data.datatokens.length === 0) return
|
||||||
setReceipts(data.datatokens[0].updates)
|
|
||||||
setCreationTx(data.datatokens[0].tx)
|
const receiptCollectionLength = data.datatokens[0].updates.length
|
||||||
|
const creationData = data.datatokens[0].updates[receiptCollectionLength - 1]
|
||||||
|
setCreationTx(creationData.tx)
|
||||||
|
|
||||||
|
const receiptCollection = [...data.datatokens[0].updates]
|
||||||
|
receiptCollection.splice(-1, 1)
|
||||||
|
|
||||||
|
setReceipts(receiptCollection)
|
||||||
}, [data])
|
}, [data])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -43,16 +48,16 @@ export default function EditHistory(): ReactElement {
|
|||||||
<ul className={styles.history}>
|
<ul className={styles.history}>
|
||||||
{receipts?.map((receipt) => (
|
{receipts?.map((receipt) => (
|
||||||
<li key={receipt.id} className={styles.item}>
|
<li key={receipt.id} className={styles.item}>
|
||||||
<EtherscanLink networkId={networkId} path={`/tx/${receipt.tx}`}>
|
<ExplorerLink networkId={networkId} path={`/tx/${receipt.tx}`}>
|
||||||
edited{' '}
|
edited{' '}
|
||||||
<Time date={receipt.timestamp.toString()} relative isUnix />
|
<Time date={receipt.timestamp.toString()} relative isUnix />
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
<li className={styles.item}>
|
<li className={styles.item}>
|
||||||
<EtherscanLink networkId={networkId} path={`/tx/${creationTx}`}>
|
<ExplorerLink networkId={networkId} path={`/tx/${creationTx}`}>
|
||||||
published <Time date={ddo.created} relative />
|
published <Time date={ddo.created} relative />
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</>
|
</>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import Time from '../../atoms/Time'
|
|
||||||
import MetaItem from './MetaItem'
|
import MetaItem from './MetaItem'
|
||||||
import styles from './MetaFull.module.css'
|
import styles from './MetaFull.module.css'
|
||||||
import Publisher from '../../atoms/Publisher'
|
import Publisher from '../../atoms/Publisher'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
import EtherscanLink from '../../atoms/EtherscanLink'
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import ExplorerLink from '../../atoms/ExplorerLink'
|
||||||
import Publisher from '../../atoms/Publisher'
|
import Publisher from '../../atoms/Publisher'
|
||||||
import Time from '../../atoms/Time'
|
import Time from '../../atoms/Time'
|
||||||
import styles from './MetaMain.module.css'
|
import styles from './MetaMain.module.css'
|
||||||
@ -9,16 +9,23 @@ import AssetType from '../../atoms/AssetType'
|
|||||||
|
|
||||||
export default function MetaMain(): ReactElement {
|
export default function MetaMain(): ReactElement {
|
||||||
const { ddo, owner, type } = useAsset()
|
const { ddo, owner, type } = useAsset()
|
||||||
const { networkId } = useOcean()
|
const { networkId } = useWeb3()
|
||||||
const isCompute = Boolean(ddo?.findServiceByType('compute'))
|
const isCompute = Boolean(ddo?.findServiceByType('compute'))
|
||||||
const accessType = isCompute ? 'compute' : 'access'
|
const accessType = isCompute ? 'compute' : 'access'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className={styles.meta}>
|
<aside className={styles.meta}>
|
||||||
<p>
|
<p>
|
||||||
<EtherscanLink networkId={networkId} path={`token/${ddo?.dataToken}`}>
|
<ExplorerLink
|
||||||
|
networkId={networkId}
|
||||||
|
path={
|
||||||
|
networkId === 137
|
||||||
|
? `tokens/${ddo?.dataToken}`
|
||||||
|
: `token/${ddo?.dataToken}`
|
||||||
|
}
|
||||||
|
>
|
||||||
{`${ddo?.dataTokenInfo.name} — ${ddo?.dataTokenInfo.symbol}`}
|
{`${ddo?.dataTokenInfo.name} — ${ddo?.dataTokenInfo.symbol}`}
|
||||||
</EtherscanLink>
|
</ExplorerLink>
|
||||||
</p>
|
</p>
|
||||||
<div>
|
<div>
|
||||||
Published By <Publisher account={owner} />
|
Published By <Publisher account={owner} />
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React, { ChangeEvent, ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import stylesIndex from './index.module.css'
|
import stylesIndex from './index.module.css'
|
||||||
import styles from './Coin.module.css'
|
import styles from './Coin.module.css'
|
||||||
import InputElement from '../../../../atoms/Input/InputElement'
|
import InputElement from '../../../../atoms/Input/InputElement'
|
||||||
import { ReactComponent as Logo } from '../../../../../images/logo.svg'
|
import { ReactComponent as Logo } from '../../../../../images/logo.svg'
|
||||||
import Conversion from '../../../../atoms/Price/Conversion'
|
import Conversion from '../../../../atoms/Price/Conversion'
|
||||||
import { DataTokenOptions } from '@oceanprotocol/react'
|
import { DataTokenOptions } from '../../../../../hooks/usePublish'
|
||||||
import { useField } from 'formik'
|
import { useField } from 'formik'
|
||||||
import Error from './Error'
|
import Error from './Error'
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useOcean, usePricing } from '@oceanprotocol/react'
|
|
||||||
import PriceUnit from '../../../../atoms/Price/PriceUnit'
|
import PriceUnit from '../../../../atoms/Price/PriceUnit'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Alert from '../../../../atoms/Alert'
|
import Alert from '../../../../atoms/Alert'
|
||||||
@ -14,8 +13,8 @@ import { PriceOptionsMarket } from '../../../../../@types/MetaData'
|
|||||||
import { DDO } from '@oceanprotocol/lib'
|
import { DDO } from '@oceanprotocol/lib'
|
||||||
import Price from './Price'
|
import Price from './Price'
|
||||||
import Decimal from 'decimal.js'
|
import Decimal from 'decimal.js'
|
||||||
|
import { useOcean } from '../../../../../providers/Ocean'
|
||||||
const refreshInterval = 10000 // 10 sec.
|
import { useWeb3 } from '../../../../../providers/Web3'
|
||||||
|
|
||||||
export default function Dynamic({
|
export default function Dynamic({
|
||||||
ddo,
|
ddo,
|
||||||
@ -24,7 +23,8 @@ export default function Dynamic({
|
|||||||
ddo: DDO
|
ddo: DDO
|
||||||
content: any
|
content: any
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { account, balance, networkId, refreshBalance } = useOcean()
|
const { networkId } = useWeb3()
|
||||||
|
const { account, balance } = useOcean()
|
||||||
const [firstPrice, setFirstPrice] = useState<string>()
|
const [firstPrice, setFirstPrice] = useState<string>()
|
||||||
|
|
||||||
// Connect with form
|
// Connect with form
|
||||||
@ -69,18 +69,6 @@ export default function Dynamic({
|
|||||||
}
|
}
|
||||||
}, [price, networkId, account, balance])
|
}, [price, networkId, account, balance])
|
||||||
|
|
||||||
// refetch balance periodically
|
|
||||||
useEffect(() => {
|
|
||||||
if (!account) return
|
|
||||||
|
|
||||||
refreshBalance()
|
|
||||||
const balanceInterval = setInterval(() => refreshBalance(), refreshInterval)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearInterval(balanceInterval)
|
|
||||||
}
|
|
||||||
}, [networkId, account])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.dynamic}>
|
<div className={styles.dynamic}>
|
||||||
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { usePricing } from '@oceanprotocol/react'
|
|
||||||
import Conversion from '../../../../atoms/Price/Conversion'
|
import Conversion from '../../../../atoms/Price/Conversion'
|
||||||
import { useField } from 'formik'
|
import { useField } from 'formik'
|
||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
@ -7,6 +6,7 @@ import styles from './Price.module.css'
|
|||||||
import Error from './Error'
|
import Error from './Error'
|
||||||
import { DDO } from '@oceanprotocol/lib'
|
import { DDO } from '@oceanprotocol/lib'
|
||||||
import PriceUnit from '../../../../atoms/Price/PriceUnit'
|
import PriceUnit from '../../../../atoms/Price/PriceUnit'
|
||||||
|
import usePricing from '../../../../../hooks/usePricing'
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
ddo,
|
ddo,
|
||||||
|
@ -2,7 +2,6 @@ import React, { FormEvent, ReactElement, useState } from 'react'
|
|||||||
import { Formik } from 'formik'
|
import { Formik } from 'formik'
|
||||||
import { initialValues, validationSchema } from '../../../../models/FormPricing'
|
import { initialValues, validationSchema } from '../../../../models/FormPricing'
|
||||||
import { DDO, Logger } from '@oceanprotocol/lib'
|
import { DDO, Logger } from '@oceanprotocol/lib'
|
||||||
import { usePricing } from '@oceanprotocol/react'
|
|
||||||
import { PriceOptionsMarket } from '../../../../@types/MetaData'
|
import { PriceOptionsMarket } from '../../../../@types/MetaData'
|
||||||
import Alert from '../../../atoms/Alert'
|
import Alert from '../../../atoms/Alert'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
@ -10,6 +9,7 @@ import FormPricing from './FormPricing'
|
|||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import Feedback from './Feedback'
|
import Feedback from './Feedback'
|
||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
|
import { usePricing } from '../../../../hooks/usePricing'
|
||||||
|
|
||||||
const query = graphql`
|
const query = graphql`
|
||||||
query PricingQuery {
|
query PricingQuery {
|
||||||
|
@ -7,7 +7,6 @@ import styles from './index.module.css'
|
|||||||
import AssetActions from '../AssetActions'
|
import AssetActions from '../AssetActions'
|
||||||
import { useUserPreferences } from '../../../providers/UserPreferences'
|
import { useUserPreferences } from '../../../providers/UserPreferences'
|
||||||
import Pricing from './Pricing'
|
import Pricing from './Pricing'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import Bookmark from './Bookmark'
|
import Bookmark from './Bookmark'
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
import Alert from '../../atoms/Alert'
|
import Alert from '../../atoms/Alert'
|
||||||
@ -16,6 +15,7 @@ import Edit from '../AssetActions/Edit'
|
|||||||
import DebugOutput from '../../atoms/DebugOutput'
|
import DebugOutput from '../../atoms/DebugOutput'
|
||||||
import MetaMain from './MetaMain'
|
import MetaMain from './MetaMain'
|
||||||
import EditHistory from './EditHistory'
|
import EditHistory from './EditHistory'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
export interface AssetContentProps {
|
export interface AssetContentProps {
|
||||||
path?: string
|
path?: string
|
||||||
@ -42,7 +42,7 @@ export default function AssetContent(props: AssetContentProps): ReactElement {
|
|||||||
const data = useStaticQuery(contentQuery)
|
const data = useStaticQuery(contentQuery)
|
||||||
const content = data.purgatory.edges[0].node.childContentJson.asset
|
const content = data.purgatory.edges[0].node.childContentJson.asset
|
||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
const { accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
const { owner, isInPurgatory, purgatoryData } = useAsset()
|
const { owner, isInPurgatory, purgatoryData } = useAsset()
|
||||||
const [showPricing, setShowPricing] = useState(false)
|
const [showPricing, setShowPricing] = useState(false)
|
||||||
const [showEdit, setShowEdit] = useState<boolean>()
|
const [showEdit, setShowEdit] = useState<boolean>()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Loader from '../../atoms/Loader'
|
import Loader from '../../atoms/Loader'
|
||||||
import Modal from '../../atoms/Modal'
|
import Modal from '../../atoms/Modal'
|
||||||
@ -9,6 +8,7 @@ import shortid from 'shortid'
|
|||||||
import styles from './ComputeDetails.module.css'
|
import styles from './ComputeDetails.module.css'
|
||||||
import { Status } from './ComputeJobs'
|
import { Status } from './ComputeJobs'
|
||||||
import { ListItem } from '../../atoms/Lists'
|
import { ListItem } from '../../atoms/Lists'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
|
||||||
export default function ComputeDetailsModal({
|
export default function ComputeDetailsModal({
|
||||||
computeJob,
|
computeJob,
|
||||||
@ -19,7 +19,7 @@ export default function ComputeDetailsModal({
|
|||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onToggleModal: () => void
|
onToggleModal: () => void
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { ocean, status, account } = useOcean()
|
const { ocean, account } = useOcean()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
const isFinished = computeJob.dateFinished !== null
|
const isFinished = computeJob.dateFinished !== null
|
||||||
@ -48,7 +48,7 @@ export default function ComputeDetailsModal({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
getDetails()
|
getDetails()
|
||||||
}, [ocean, status, account, isOpen, computeJob, isFinished])
|
}, [ocean, account, isOpen, computeJob, isFinished])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Time from '../../atoms/Time'
|
import Time from '../../atoms/Time'
|
||||||
import styles from './ComputeJobs.module.css'
|
import styles from './ComputeJobs.module.css'
|
||||||
@ -9,6 +8,7 @@ import { Link } from 'gatsby'
|
|||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import Dotdotdot from 'react-dotdotdot'
|
import Dotdotdot from 'react-dotdotdot'
|
||||||
import Table from '../../atoms/Table'
|
import Table from '../../atoms/Table'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
|
||||||
function DetailsButton({ row }: { row: ComputeJobMetaData }): ReactElement {
|
function DetailsButton({ row }: { row: ComputeJobMetaData }): ReactElement {
|
||||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import Table from '../../atoms/Table'
|
import Table from '../../atoms/Table'
|
||||||
import { gql, useQuery } from '@apollo/client'
|
import { gql, useQuery } from '@apollo/client'
|
||||||
import Time from '../../atoms/Time'
|
import Time from '../../atoms/Time'
|
||||||
import { OrdersData_tokenOrders as OrdersDataTokenOrders } from '../../../@types/apollo/OrdersData'
|
import { OrdersData_tokenOrders as OrdersDataTokenOrders } from '../../../@types/apollo/OrdersData'
|
||||||
import web3 from 'web3'
|
import web3 from 'web3'
|
||||||
import AssetTitle from '../../molecules/AssetListTitle'
|
import AssetTitle from '../../molecules/AssetListTitle'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
const getTokenOrders = gql`
|
const getTokenOrders = gql`
|
||||||
query OrdersData($user: String!) {
|
query OrdersData($user: String!) {
|
||||||
@ -50,7 +50,7 @@ const columns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default function ComputeDownloads(): ReactElement {
|
export default function ComputeDownloads(): ReactElement {
|
||||||
const { accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
const [orders, setOrders] = useState<OrdersDataTokenOrders[]>()
|
const [orders, setOrders] = useState<OrdersDataTokenOrders[]>()
|
||||||
const { data } = useQuery(getTokenOrders, {
|
const { data } = useQuery(getTokenOrders, {
|
||||||
variables: { user: accountId?.toLowerCase() }
|
variables: { user: accountId?.toLowerCase() }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Table from '../../atoms/Table'
|
import Table from '../../atoms/Table'
|
||||||
import Conversion from '../../atoms/Price/Conversion'
|
import Conversion from '../../atoms/Price/Conversion'
|
||||||
@ -12,6 +11,7 @@ import {
|
|||||||
} from '../../../@types/apollo/PoolShares'
|
} from '../../../@types/apollo/PoolShares'
|
||||||
import web3 from 'web3'
|
import web3 from 'web3'
|
||||||
import Token from '../../organisms/AssetActions/Pool/Token'
|
import Token from '../../organisms/AssetActions/Pool/Token'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
|
||||||
const poolSharesQuery = gql`
|
const poolSharesQuery = gql`
|
||||||
query PoolShares($user: String) {
|
query PoolShares($user: String) {
|
||||||
@ -139,7 +139,7 @@ const columns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
export default function PoolShares(): ReactElement {
|
export default function PoolShares(): ReactElement {
|
||||||
const { accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
const [assets, setAssets] = useState<Asset[]>()
|
const [assets, setAssets] = useState<Asset[]>()
|
||||||
const { data, loading } = useQuery<PoolSharesList>(poolSharesQuery, {
|
const { data, loading } = useQuery<PoolSharesList>(poolSharesQuery, {
|
||||||
variables: {
|
variables: {
|
||||||
|
@ -1,20 +1,23 @@
|
|||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
|
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
import Loader from '../../atoms/Loader'
|
import Loader from '../../atoms/Loader'
|
||||||
import AssetList from '../../organisms/AssetList'
|
import AssetList from '../../organisms/AssetList'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { queryMetadata } from '../../../utils/aquarius'
|
import { queryMetadata } from '../../../utils/aquarius'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
|
||||||
export default function PublishedList(): ReactElement {
|
export default function PublishedList(): ReactElement {
|
||||||
const { accountId } = useOcean()
|
const { accountId } = useWeb3()
|
||||||
|
const { config } = useOcean()
|
||||||
|
|
||||||
const [queryResult, setQueryResult] = useState<QueryResult>()
|
const [queryResult, setQueryResult] = useState<QueryResult>()
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const { config } = useOcean()
|
|
||||||
const source = axios.CancelToken.source()
|
|
||||||
const [page, setPage] = useState<number>(1)
|
const [page, setPage] = useState<number>(1)
|
||||||
|
|
||||||
|
const source = axios.CancelToken.source()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function getPublished() {
|
async function getPublished() {
|
||||||
if (!accountId) return
|
if (!accountId) return
|
||||||
|
@ -5,7 +5,7 @@ import AssetList from '../organisms/AssetList'
|
|||||||
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
|
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
|
||||||
import Container from '../atoms/Container'
|
import Container from '../atoms/Container'
|
||||||
import Loader from '../atoms/Loader'
|
import Loader from '../atoms/Loader'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../providers/Ocean'
|
||||||
import Button from '../atoms/Button'
|
import Button from '../atoms/Button'
|
||||||
import Bookmarks from '../molecules/Bookmarks'
|
import Bookmarks from '../molecules/Bookmarks'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
@ -7,7 +7,7 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { useStaticQuery, graphql } from 'gatsby'
|
import { useStaticQuery, graphql } from 'gatsby'
|
||||||
import styles from './FormPublish.module.css'
|
import styles from './FormPublish.module.css'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import { useFormikContext, Field, Form, FormikContextType } from 'formik'
|
import { useFormikContext, Field, Form, FormikContextType } from 'formik'
|
||||||
import Input from '../../atoms/Input'
|
import Input from '../../atoms/Input'
|
||||||
import Button from '../../atoms/Button'
|
import Button from '../../atoms/Button'
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import React, { ReactElement, useEffect, FormEvent, ChangeEvent } from 'react'
|
import React, { ReactElement, useEffect, FormEvent, ChangeEvent } from 'react'
|
||||||
import { useStaticQuery, graphql } from 'gatsby'
|
import { useStaticQuery, graphql } from 'gatsby'
|
||||||
import styles from './FormPublish.module.css'
|
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { useFormikContext, Field, Form, FormikContextType } from 'formik'
|
import { useFormikContext, Field, Form, FormikContextType } from 'formik'
|
||||||
import Input from '../../atoms/Input'
|
import Input from '../../atoms/Input'
|
||||||
import Button from '../../atoms/Button'
|
import Button from '../../atoms/Button'
|
||||||
import { FormContent, FormFieldProps } from '../../../@types/Form'
|
import { FormContent, FormFieldProps } from '../../../@types/Form'
|
||||||
import { MetadataPublishFormDataset } from '../../../@types/MetaData'
|
import { MetadataPublishFormDataset } from '../../../@types/MetaData'
|
||||||
import { initialValues as initialValuesDataset } from '../../../models/FormAlgoPublish'
|
import { initialValues as initialValuesDataset } from '../../../models/FormAlgoPublish'
|
||||||
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import stylesIndex from './index.module.css'
|
import stylesIndex from './index.module.css'
|
||||||
|
import styles from './FormPublish.module.css'
|
||||||
|
|
||||||
const query = graphql`
|
const query = graphql`
|
||||||
query {
|
query {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { ReactElement, useState, useEffect } from 'react'
|
import React, { ReactElement, useState, useEffect } from 'react'
|
||||||
import { Formik, FormikState } from 'formik'
|
import { Formik, FormikState } from 'formik'
|
||||||
import { usePublish, useOcean } from '@oceanprotocol/react'
|
import { usePublish } from '../../../hooks/usePublish'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import FormPublish from './FormPublish'
|
import FormPublish from './FormPublish'
|
||||||
import FormAlgoPublish from './FormAlgoPublish'
|
import FormAlgoPublish from './FormAlgoPublish'
|
||||||
@ -31,6 +31,9 @@ import { Persist } from '../../atoms/FormikPersist'
|
|||||||
import Debug from './Debug'
|
import Debug from './Debug'
|
||||||
import Alert from '../../atoms/Alert'
|
import Alert from '../../atoms/Alert'
|
||||||
import MetadataFeedback from '../../molecules/MetadataFeedback'
|
import MetadataFeedback from '../../molecules/MetadataFeedback'
|
||||||
|
import { useAccountPurgatory } from '../../../hooks/useAccountPurgatory'
|
||||||
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
|
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
||||||
|
|
||||||
const formNameDatasets = 'ocean-publish-form-datasets'
|
const formNameDatasets = 'ocean-publish-form-datasets'
|
||||||
const formNameAlgorithms = 'ocean-publish-form-algorithms'
|
const formNameAlgorithms = 'ocean-publish-form-algorithms'
|
||||||
@ -66,9 +69,11 @@ export default function PublishPage({
|
|||||||
}: {
|
}: {
|
||||||
content: { warning: string }
|
content: { warning: string }
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
|
const { warningPolygonPublish } = useSiteMetadata()
|
||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
|
const { accountId, networkId } = useWeb3()
|
||||||
|
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||||
const { publish, publishError, isLoading, publishStepText } = usePublish()
|
const { publish, publishError, isLoading, publishStepText } = usePublish()
|
||||||
const { isInPurgatory, purgatoryData } = useOcean()
|
|
||||||
const [success, setSuccess] = useState<string>()
|
const [success, setSuccess] = useState<string>()
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
const [title, setTitle] = useState<string>()
|
const [title, setTitle] = useState<string>()
|
||||||
|
@ -10,7 +10,7 @@ import { getResults } from './utils'
|
|||||||
import { navigate } from 'gatsby'
|
import { navigate } from 'gatsby'
|
||||||
import { updateQueryStringParameter } from '../../../utils'
|
import { updateQueryStringParameter } from '../../../utils'
|
||||||
import Loader from '../../atoms/Loader'
|
import Loader from '../../atoms/Loader'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
|
|
||||||
export default function SearchPage({
|
export default function SearchPage({
|
||||||
location,
|
location,
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
import React, { ReactElement, useEffect } from 'react'
|
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
|
||||||
import { getOceanConfig } from './wrapRootElement'
|
|
||||||
import { Logger } from '@oceanprotocol/lib'
|
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
|
||||||
import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
|
|
||||||
|
|
||||||
const refreshInterval = 5000 // 5 sec.
|
|
||||||
|
|
||||||
export function getDevelopmentConfig(): Partial<ConfigHelperConfig> {
|
|
||||||
return {
|
|
||||||
factoryAddress: contractAddresses.development?.DTFactory,
|
|
||||||
poolFactoryAddress: contractAddresses.development?.BFactory,
|
|
||||||
fixedRateExchangeAddress: contractAddresses.development?.FixedRateExchange,
|
|
||||||
metadataContractAddress: contractAddresses.development?.Metadata,
|
|
||||||
oceanTokenAddress: contractAddresses.development?.Ocean,
|
|
||||||
// There is no subgraph in barge so we hardcode the Rinkeby one for now
|
|
||||||
subgraphUri: 'https://subgraph.rinkeby.oceanprotocol.com'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetworkMonitor(): ReactElement {
|
|
||||||
const {
|
|
||||||
connect,
|
|
||||||
web3Provider,
|
|
||||||
web3,
|
|
||||||
networkId,
|
|
||||||
config,
|
|
||||||
refreshBalance,
|
|
||||||
account
|
|
||||||
} = useOcean()
|
|
||||||
|
|
||||||
async function handleNetworkChanged(chainId: string | number) {
|
|
||||||
const initialNewConfig = getOceanConfig(
|
|
||||||
typeof chainId === 'string' ? Number(chainId.replace('0x', '')) : chainId
|
|
||||||
)
|
|
||||||
|
|
||||||
const newConfig = {
|
|
||||||
...initialNewConfig,
|
|
||||||
|
|
||||||
// add local dev values
|
|
||||||
...(chainId === '8996' && {
|
|
||||||
...getDevelopmentConfig()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await connect(newConfig)
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error(error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Periodically refresh wallet balance
|
|
||||||
useEffect(() => {
|
|
||||||
if (!account) return
|
|
||||||
|
|
||||||
refreshBalance()
|
|
||||||
const balanceInterval = setInterval(() => refreshBalance(), refreshInterval)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearInterval(balanceInterval)
|
|
||||||
}
|
|
||||||
}, [networkId, account])
|
|
||||||
|
|
||||||
// Re-connect on mount when network is different from user network.
|
|
||||||
// Bit nasty to just overwrite the initialConfig passed to OceanProvider
|
|
||||||
// while it's connecting to that, but YOLO.
|
|
||||||
useEffect(() => {
|
|
||||||
if (!web3 || !networkId) return
|
|
||||||
|
|
||||||
async function init() {
|
|
||||||
const chainIdWeb3 = await web3.eth.getChainId()
|
|
||||||
const chainIdConfig = (config as ConfigHelperConfig).networkId
|
|
||||||
|
|
||||||
// HEADS UP! MetaMask built-in `Localhost 8545` network selection
|
|
||||||
// will have `1337` as chainId but we use `8996` in our config
|
|
||||||
if (
|
|
||||||
chainIdWeb3 === chainIdConfig ||
|
|
||||||
(chainIdWeb3 === 1337 && chainIdConfig === 8996)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
await handleNetworkChanged(networkId)
|
|
||||||
}
|
|
||||||
init()
|
|
||||||
}, [web3, networkId])
|
|
||||||
|
|
||||||
// Handle network change events
|
|
||||||
useEffect(() => {
|
|
||||||
if (!web3Provider) return
|
|
||||||
|
|
||||||
web3Provider.on('chainChanged', handleNetworkChanged)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
web3Provider.removeListener('chainChanged', handleNetworkChanged)
|
|
||||||
}
|
|
||||||
}, [web3Provider])
|
|
||||||
|
|
||||||
return <></>
|
|
||||||
}
|
|
@ -1,25 +1,11 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { OceanProvider } from '@oceanprotocol/react'
|
import Web3Provider from '../providers/Web3'
|
||||||
import { ConfigHelper, Config } from '@oceanprotocol/lib'
|
|
||||||
import { web3ModalOpts } from '../utils/wallet'
|
|
||||||
import { getDevelopmentConfig, NetworkMonitor } from './NetworkMonitor'
|
|
||||||
import appConfig from '../../app.config'
|
import appConfig from '../../app.config'
|
||||||
import {
|
|
||||||
ConfigHelperNetworkName,
|
|
||||||
ConfigHelperNetworkId
|
|
||||||
} from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
|
||||||
import { UserPreferencesProvider } from '../providers/UserPreferences'
|
import { UserPreferencesProvider } from '../providers/UserPreferences'
|
||||||
import PricesProvider from '../providers/Prices'
|
import PricesProvider from '../providers/Prices'
|
||||||
import ApolloClientProvider from '../providers/ApolloClientProvider'
|
import ApolloClientProvider from '../providers/ApolloClientProvider'
|
||||||
|
import OceanProvider from '../providers/Ocean'
|
||||||
export function getOceanConfig(
|
import { getDevelopmentConfig, getOceanConfig } from '../utils/ocean'
|
||||||
network: ConfigHelperNetworkName | ConfigHelperNetworkId
|
|
||||||
): Config {
|
|
||||||
return new ConfigHelper().getConfig(
|
|
||||||
network,
|
|
||||||
process.env.GATSBY_INFURA_PROJECT_ID
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function wrapRootElement({
|
export default function wrapRootElement({
|
||||||
element
|
element
|
||||||
@ -37,16 +23,14 @@ export default function wrapRootElement({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OceanProvider
|
<Web3Provider>
|
||||||
initialConfig={oceanInitialConfig}
|
<OceanProvider initialConfig={oceanInitialConfig}>
|
||||||
web3ModalOpts={web3ModalOpts}
|
<ApolloClientProvider>
|
||||||
>
|
<UserPreferencesProvider>
|
||||||
<ApolloClientProvider>
|
<PricesProvider>{element}</PricesProvider>
|
||||||
<UserPreferencesProvider>
|
</UserPreferencesProvider>
|
||||||
<NetworkMonitor />
|
</ApolloClientProvider>
|
||||||
<PricesProvider>{element}</PricesProvider>
|
</OceanProvider>
|
||||||
</UserPreferencesProvider>
|
</Web3Provider>
|
||||||
</ApolloClientProvider>
|
|
||||||
</OceanProvider>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
51
src/hooks/useAccountPurgatory.ts
Normal file
51
src/hooks/useAccountPurgatory.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
|
import {
|
||||||
|
PurgatoryDataAccount,
|
||||||
|
getAccountPurgatoryData
|
||||||
|
} from '../utils/purgatory'
|
||||||
|
|
||||||
|
interface UseAccountPurgatory {
|
||||||
|
isInPurgatory: boolean
|
||||||
|
purgatoryData: PurgatoryDataAccount
|
||||||
|
isLoading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function useAccountPurgatory(accountId: string): UseAccountPurgatory {
|
||||||
|
const [isInPurgatory, setIsInPurgatory] = useState(false)
|
||||||
|
const [purgatoryData, setPurgatoryData] = useState<PurgatoryDataAccount>()
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
const setAccountPurgatory = useCallback(
|
||||||
|
async (address: string): Promise<void> => {
|
||||||
|
if (!address) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
setIsLoading(true)
|
||||||
|
const result = await getAccountPurgatoryData(address)
|
||||||
|
const isInPurgatory = result?.address !== undefined
|
||||||
|
setIsInPurgatory(isInPurgatory)
|
||||||
|
isInPurgatory && setPurgatoryData(result)
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(error)
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!accountId) return
|
||||||
|
setAccountPurgatory(accountId)
|
||||||
|
}, [accountId, setAccountPurgatory])
|
||||||
|
|
||||||
|
return {
|
||||||
|
isInPurgatory,
|
||||||
|
purgatoryData,
|
||||||
|
isLoading
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useAccountPurgatory, UseAccountPurgatory }
|
||||||
|
export default useAccountPurgatory
|
156
src/hooks/useCompute.ts
Normal file
156
src/hooks/useCompute.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { Logger, ServiceCompute } from '@oceanprotocol/lib'
|
||||||
|
import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm'
|
||||||
|
import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/ComputeJob'
|
||||||
|
import { computeFeedback } from '../utils/feedback'
|
||||||
|
import { useOcean } from '../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../providers/Web3'
|
||||||
|
|
||||||
|
interface ComputeValue {
|
||||||
|
entrypoint: string
|
||||||
|
image: string
|
||||||
|
tag: string
|
||||||
|
}
|
||||||
|
interface ComputeOption {
|
||||||
|
name: string
|
||||||
|
value: ComputeValue
|
||||||
|
}
|
||||||
|
|
||||||
|
const computeOptions: ComputeOption[] = [
|
||||||
|
{
|
||||||
|
name: 'nodejs',
|
||||||
|
value: {
|
||||||
|
entrypoint: 'node $ALGO',
|
||||||
|
image: 'node',
|
||||||
|
tag: '10'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'python3.7',
|
||||||
|
value: {
|
||||||
|
entrypoint: 'python $ALGO',
|
||||||
|
image: 'oceanprotocol/algo_dockers',
|
||||||
|
tag: 'python-panda'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
interface UseCompute {
|
||||||
|
compute: (
|
||||||
|
did: string,
|
||||||
|
computeService: ServiceCompute,
|
||||||
|
dataTokenAddress: string,
|
||||||
|
algorithmRawCode: string,
|
||||||
|
computeContainer: ComputeValue,
|
||||||
|
marketFeeAddress?: string,
|
||||||
|
orderId?: string
|
||||||
|
) => Promise<ComputeJob | void>
|
||||||
|
computeStep?: number
|
||||||
|
computeStepText?: string
|
||||||
|
computeError?: string
|
||||||
|
isLoading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const rawAlgorithmMeta: MetadataAlgorithm = {
|
||||||
|
rawcode: `console.log('Hello world'!)`,
|
||||||
|
format: 'docker-image',
|
||||||
|
version: '0.1',
|
||||||
|
container: {
|
||||||
|
entrypoint: '',
|
||||||
|
image: '',
|
||||||
|
tag: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function useCompute(): UseCompute {
|
||||||
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean, account } = useOcean()
|
||||||
|
const [computeStep, setComputeStep] = useState<number | undefined>()
|
||||||
|
const [computeStepText, setComputeStepText] = useState<string | undefined>()
|
||||||
|
const [computeError, setComputeError] = useState<string | undefined>()
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
function setStep(index?: number) {
|
||||||
|
if (!index) {
|
||||||
|
setComputeStep(undefined)
|
||||||
|
setComputeStepText(undefined)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setComputeStep(index)
|
||||||
|
setComputeStepText(computeFeedback[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function compute(
|
||||||
|
did: string,
|
||||||
|
computeService: ServiceCompute,
|
||||||
|
dataTokenAddress: string,
|
||||||
|
algorithmRawCode: string,
|
||||||
|
computeContainer: ComputeValue,
|
||||||
|
marketFeeAddress?: string,
|
||||||
|
orderId?: string
|
||||||
|
): Promise<ComputeJob | void> {
|
||||||
|
if (!ocean || !account) return
|
||||||
|
setComputeError(undefined)
|
||||||
|
try {
|
||||||
|
setIsLoading(true)
|
||||||
|
setStep(0)
|
||||||
|
rawAlgorithmMeta.container = computeContainer
|
||||||
|
rawAlgorithmMeta.rawcode = algorithmRawCode
|
||||||
|
const output = {}
|
||||||
|
if (!orderId) {
|
||||||
|
const userOwnedTokens = await ocean.accounts.getTokenBalance(
|
||||||
|
dataTokenAddress,
|
||||||
|
account
|
||||||
|
)
|
||||||
|
if (parseFloat(userOwnedTokens) < 1) {
|
||||||
|
setComputeError('Not enough datatokens')
|
||||||
|
} else {
|
||||||
|
Logger.log(
|
||||||
|
'compute order',
|
||||||
|
accountId,
|
||||||
|
did,
|
||||||
|
computeService,
|
||||||
|
rawAlgorithmMeta,
|
||||||
|
marketFeeAddress
|
||||||
|
)
|
||||||
|
orderId = await ocean.compute.orderAsset(
|
||||||
|
accountId,
|
||||||
|
did,
|
||||||
|
computeService.index,
|
||||||
|
undefined,
|
||||||
|
rawAlgorithmMeta,
|
||||||
|
marketFeeAddress
|
||||||
|
)
|
||||||
|
setStep(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setStep(2)
|
||||||
|
if (orderId) {
|
||||||
|
const response = await ocean.compute.start(
|
||||||
|
did,
|
||||||
|
orderId,
|
||||||
|
dataTokenAddress,
|
||||||
|
account,
|
||||||
|
undefined,
|
||||||
|
rawAlgorithmMeta,
|
||||||
|
output,
|
||||||
|
`${computeService.index}`,
|
||||||
|
computeService.type
|
||||||
|
)
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(error)
|
||||||
|
setComputeError(error.message)
|
||||||
|
} finally {
|
||||||
|
setStep(undefined)
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { compute, computeStep, computeStepText, computeError, isLoading }
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useCompute, UseCompute, ComputeValue, ComputeOption, computeOptions }
|
||||||
|
export default UseCompute
|
93
src/hooks/useConsume.ts
Normal file
93
src/hooks/useConsume.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
|
import { consumeFeedback } from '../utils/feedback'
|
||||||
|
import { DID, Logger, ServiceType } from '@oceanprotocol/lib'
|
||||||
|
import { useOcean } from '../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../providers/Web3'
|
||||||
|
|
||||||
|
interface UseConsume {
|
||||||
|
consume: (
|
||||||
|
did: DID | string,
|
||||||
|
dataTokenAddress: string,
|
||||||
|
serviceType: ServiceType,
|
||||||
|
marketFeeAddress: string,
|
||||||
|
orderId?: string
|
||||||
|
) => Promise<void>
|
||||||
|
consumeStep?: number
|
||||||
|
consumeStepText?: string
|
||||||
|
consumeError?: string
|
||||||
|
isLoading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function useConsume(): UseConsume {
|
||||||
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean, account } = useOcean()
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [consumeStep, setConsumeStep] = useState<number | undefined>()
|
||||||
|
const [consumeStepText, setConsumeStepText] = useState<string | undefined>()
|
||||||
|
const [consumeError, setConsumeError] = useState<string | undefined>()
|
||||||
|
|
||||||
|
function setStep(index: number) {
|
||||||
|
setConsumeStep(index)
|
||||||
|
setConsumeStepText(consumeFeedback[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function consume(
|
||||||
|
did: DID | string,
|
||||||
|
dataTokenAddress: string,
|
||||||
|
serviceType: ServiceType = 'access',
|
||||||
|
marketFeeAddress: string,
|
||||||
|
orderId?: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (!ocean || !account || !accountId) return
|
||||||
|
|
||||||
|
setIsLoading(true)
|
||||||
|
setConsumeError(undefined)
|
||||||
|
|
||||||
|
try {
|
||||||
|
setStep(0)
|
||||||
|
if (!orderId) {
|
||||||
|
// if we don't have a previous valid order, get one
|
||||||
|
const userOwnedTokens = await ocean.accounts.getTokenBalance(
|
||||||
|
dataTokenAddress,
|
||||||
|
account
|
||||||
|
)
|
||||||
|
if (parseFloat(userOwnedTokens) < 1) {
|
||||||
|
setConsumeError('Not enough datatokens')
|
||||||
|
} else {
|
||||||
|
setStep(1)
|
||||||
|
orderId = await ocean.assets.order(
|
||||||
|
did as string,
|
||||||
|
serviceType,
|
||||||
|
accountId,
|
||||||
|
undefined,
|
||||||
|
marketFeeAddress
|
||||||
|
)
|
||||||
|
Logger.log('order created', orderId)
|
||||||
|
setStep(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setStep(3)
|
||||||
|
if (orderId)
|
||||||
|
await ocean.assets.download(
|
||||||
|
did as string,
|
||||||
|
orderId,
|
||||||
|
dataTokenAddress,
|
||||||
|
account,
|
||||||
|
''
|
||||||
|
)
|
||||||
|
setStep(4)
|
||||||
|
} catch (error) {
|
||||||
|
setConsumeError(error.message)
|
||||||
|
Logger.error(error)
|
||||||
|
} finally {
|
||||||
|
setConsumeStep(undefined)
|
||||||
|
setConsumeStepText(undefined)
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { consume, consumeStep, consumeStepText, consumeError, isLoading }
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useConsume, UseConsume }
|
||||||
|
export default useConsume
|
299
src/hooks/usePricing.ts
Normal file
299
src/hooks/usePricing.ts
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
import { DDO, Logger, BestPrice } from '@oceanprotocol/lib'
|
||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { TransactionReceipt } from 'web3-core'
|
||||||
|
import { Decimal } from 'decimal.js'
|
||||||
|
import { getFirstPoolPrice } from '../utils/dtUtils'
|
||||||
|
import {
|
||||||
|
getCreatePricingPoolFeedback,
|
||||||
|
getCreatePricingExchangeFeedback,
|
||||||
|
getBuyDTFeedback,
|
||||||
|
getSellDTFeedback
|
||||||
|
} from '../utils/feedback'
|
||||||
|
import { sleep } from '../utils'
|
||||||
|
|
||||||
|
import { useOcean } from '../providers/Ocean'
|
||||||
|
import { useWeb3 } from '../providers/Web3'
|
||||||
|
|
||||||
|
interface PriceOptions {
|
||||||
|
price: number
|
||||||
|
dtAmount: number
|
||||||
|
oceanAmount: number
|
||||||
|
type: 'fixed' | 'dynamic' | string
|
||||||
|
weightOnDataToken: string
|
||||||
|
swapFee: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UsePricing {
|
||||||
|
dtSymbol?: string
|
||||||
|
dtName?: string
|
||||||
|
createPricing: (
|
||||||
|
priceOptions: PriceOptions
|
||||||
|
) => Promise<TransactionReceipt | string | void>
|
||||||
|
sellDT: (dtAmount: number | string) => Promise<TransactionReceipt | void>
|
||||||
|
mint: (tokensToMint: string) => Promise<TransactionReceipt | void>
|
||||||
|
buyDT: (
|
||||||
|
dtAmount: number | string,
|
||||||
|
price: BestPrice
|
||||||
|
) => Promise<TransactionReceipt | void>
|
||||||
|
pricingStep?: number
|
||||||
|
pricingStepText?: string
|
||||||
|
pricingError?: string
|
||||||
|
pricingIsLoading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function usePricing(ddo: DDO): UsePricing {
|
||||||
|
const { accountId } = useWeb3()
|
||||||
|
const { ocean, config } = useOcean()
|
||||||
|
const [pricingIsLoading, setPricingIsLoading] = useState(false)
|
||||||
|
const [pricingStep, setPricingStep] = useState<number>()
|
||||||
|
const [pricingStepText, setPricingStepText] = useState<string>()
|
||||||
|
const [pricingError, setPricingError] = useState<string>()
|
||||||
|
const [dtSymbol, setDtSymbol] = useState<string>()
|
||||||
|
const [dtName, setDtName] = useState<string>()
|
||||||
|
|
||||||
|
const { dataToken, dataTokenInfo } = ddo
|
||||||
|
|
||||||
|
// Get Datatoken info, from DDO first, then from chain
|
||||||
|
useEffect(() => {
|
||||||
|
if (!dataToken) return
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const dtSymbol = dataTokenInfo
|
||||||
|
? dataTokenInfo.symbol
|
||||||
|
: await ocean?.datatokens.getSymbol(dataToken)
|
||||||
|
setDtSymbol(dtSymbol)
|
||||||
|
|
||||||
|
const dtName = dataTokenInfo
|
||||||
|
? dataTokenInfo.name
|
||||||
|
: await ocean?.datatokens.getName(dataToken)
|
||||||
|
setDtName(dtName)
|
||||||
|
}
|
||||||
|
init()
|
||||||
|
}, [ocean, dataToken, dataTokenInfo])
|
||||||
|
|
||||||
|
// Helper for setting steps & feedback for all flows
|
||||||
|
function setStep(index: number, type: 'pool' | 'exchange' | 'buy' | 'sell') {
|
||||||
|
setPricingStep(index)
|
||||||
|
if (!dtSymbol) return
|
||||||
|
|
||||||
|
let messages
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'pool':
|
||||||
|
messages = getCreatePricingPoolFeedback(dtSymbol)
|
||||||
|
break
|
||||||
|
case 'exchange':
|
||||||
|
messages = getCreatePricingExchangeFeedback(dtSymbol)
|
||||||
|
break
|
||||||
|
case 'buy':
|
||||||
|
messages = getBuyDTFeedback(dtSymbol)
|
||||||
|
break
|
||||||
|
case 'sell':
|
||||||
|
messages = getSellDTFeedback(dtSymbol)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
setPricingStepText(messages[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
async function mint(
|
||||||
|
tokensToMint: string
|
||||||
|
): Promise<TransactionReceipt | void> {
|
||||||
|
Logger.log('mint function', dataToken, accountId)
|
||||||
|
const balance = new Decimal(
|
||||||
|
await ocean.datatokens.balance(dataToken, accountId)
|
||||||
|
)
|
||||||
|
const tokens = new Decimal(tokensToMint)
|
||||||
|
if (tokens.greaterThan(balance)) {
|
||||||
|
const mintAmount = tokens.minus(balance)
|
||||||
|
const tx = await ocean.datatokens.mint(
|
||||||
|
dataToken,
|
||||||
|
accountId,
|
||||||
|
mintAmount.toString()
|
||||||
|
)
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buyDT(
|
||||||
|
dtAmount: number | string,
|
||||||
|
price: BestPrice
|
||||||
|
): Promise<TransactionReceipt | void> {
|
||||||
|
if (!ocean || !accountId) return
|
||||||
|
|
||||||
|
let tx
|
||||||
|
|
||||||
|
try {
|
||||||
|
setPricingIsLoading(true)
|
||||||
|
setPricingError(undefined)
|
||||||
|
setStep(1, 'buy')
|
||||||
|
|
||||||
|
Logger.log('Price found for buying', price)
|
||||||
|
switch (price?.type) {
|
||||||
|
case 'pool': {
|
||||||
|
const oceanAmmount = new Decimal(price.value).times(1.05).toString()
|
||||||
|
const maxPrice = new Decimal(price.value).times(2).toString()
|
||||||
|
setStep(2, 'buy')
|
||||||
|
Logger.log('Buying token from pool', price, accountId, price)
|
||||||
|
tx = await ocean.pool.buyDT(
|
||||||
|
accountId,
|
||||||
|
price.address,
|
||||||
|
String(dtAmount),
|
||||||
|
oceanAmmount,
|
||||||
|
maxPrice
|
||||||
|
)
|
||||||
|
setStep(3, 'buy')
|
||||||
|
Logger.log('DT buy response', tx)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'exchange': {
|
||||||
|
if (!config.oceanTokenAddress) {
|
||||||
|
Logger.error(`'oceanTokenAddress' not set in config`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!config.fixedRateExchangeAddress) {
|
||||||
|
Logger.error(`'fixedRateExchangeAddress' not set in config`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Logger.log('Buying token from exchange', price, accountId)
|
||||||
|
await ocean.datatokens.approve(
|
||||||
|
config.oceanTokenAddress,
|
||||||
|
config.fixedRateExchangeAddress,
|
||||||
|
`${price.value}`,
|
||||||
|
accountId
|
||||||
|
)
|
||||||
|
setStep(2, 'buy')
|
||||||
|
tx = await ocean.fixedRateExchange.buyDT(
|
||||||
|
price.address,
|
||||||
|
`${dtAmount}`,
|
||||||
|
accountId
|
||||||
|
)
|
||||||
|
setStep(3, 'buy')
|
||||||
|
Logger.log('DT exchange buy response', tx)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
setPricingError(error.message)
|
||||||
|
Logger.error(error)
|
||||||
|
} finally {
|
||||||
|
setStep(0, 'buy')
|
||||||
|
setPricingStepText(undefined)
|
||||||
|
setPricingIsLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sellDT(
|
||||||
|
dtAmount: number | string
|
||||||
|
): Promise<TransactionReceipt | void> {
|
||||||
|
if (!ocean || !accountId) return
|
||||||
|
|
||||||
|
if (!config.oceanTokenAddress) {
|
||||||
|
Logger.error(`'oceanTokenAddress' not set in config`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setPricingIsLoading(true)
|
||||||
|
setPricingError(undefined)
|
||||||
|
setStep(1, 'sell')
|
||||||
|
const pool = await getFirstPoolPrice(ocean, dataToken)
|
||||||
|
if (!pool || pool.value === 0) return
|
||||||
|
const price = new Decimal(pool.value).times(0.95).toString()
|
||||||
|
setStep(2, 'sell')
|
||||||
|
Logger.log('Selling token to pool', pool, accountId, price)
|
||||||
|
const tx = await ocean.pool.sellDT(
|
||||||
|
accountId,
|
||||||
|
pool.address,
|
||||||
|
`${dtAmount}`,
|
||||||
|
price
|
||||||
|
)
|
||||||
|
setStep(3, 'sell')
|
||||||
|
Logger.log('DT sell response', tx)
|
||||||
|
return tx
|
||||||
|
} catch (error) {
|
||||||
|
setPricingError(error.message)
|
||||||
|
Logger.error(error)
|
||||||
|
} finally {
|
||||||
|
setStep(0, 'sell')
|
||||||
|
setPricingStepText(undefined)
|
||||||
|
setPricingIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createPricing(
|
||||||
|
priceOptions: PriceOptions
|
||||||
|
): Promise<TransactionReceipt | void> {
|
||||||
|
if (!ocean || !accountId || !dtSymbol) return
|
||||||
|
|
||||||
|
const {
|
||||||
|
type,
|
||||||
|
oceanAmount,
|
||||||
|
price,
|
||||||
|
weightOnDataToken,
|
||||||
|
swapFee
|
||||||
|
} = priceOptions
|
||||||
|
|
||||||
|
let { dtAmount } = priceOptions
|
||||||
|
const isPool = type === 'dynamic'
|
||||||
|
|
||||||
|
if (!isPool && !config.fixedRateExchangeAddress) {
|
||||||
|
Logger.error(`'fixedRateExchangeAddress' not set in config.`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setPricingIsLoading(true)
|
||||||
|
setPricingError(undefined)
|
||||||
|
|
||||||
|
setStep(99, 'pool')
|
||||||
|
|
||||||
|
try {
|
||||||
|
// if fixedPrice set dt to max amount
|
||||||
|
if (!isPool) dtAmount = 1000
|
||||||
|
await mint(`${dtAmount}`)
|
||||||
|
|
||||||
|
// dtAmount for fixed price is set to max
|
||||||
|
const tx = isPool
|
||||||
|
? await ocean.pool
|
||||||
|
.create(
|
||||||
|
accountId,
|
||||||
|
dataToken,
|
||||||
|
`${dtAmount}`,
|
||||||
|
weightOnDataToken,
|
||||||
|
`${oceanAmount}`,
|
||||||
|
swapFee
|
||||||
|
)
|
||||||
|
.next((step: number) => setStep(step, 'pool'))
|
||||||
|
: await ocean.fixedRateExchange
|
||||||
|
.create(dataToken, `${price}`, accountId, `${dtAmount}`)
|
||||||
|
.next((step: number) => setStep(step, 'exchange'))
|
||||||
|
await sleep(20000)
|
||||||
|
return tx
|
||||||
|
} catch (error) {
|
||||||
|
setPricingError(error.message)
|
||||||
|
Logger.error(error)
|
||||||
|
} finally {
|
||||||
|
setPricingStep(0)
|
||||||
|
setPricingStepText(undefined)
|
||||||
|
setPricingIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
dtSymbol,
|
||||||
|
dtName,
|
||||||
|
createPricing,
|
||||||
|
buyDT,
|
||||||
|
sellDT,
|
||||||
|
mint,
|
||||||
|
pricingStep,
|
||||||
|
pricingStepText,
|
||||||
|
pricingIsLoading,
|
||||||
|
pricingError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { usePricing, UsePricing, PriceOptions }
|
||||||
|
export default usePricing
|
171
src/hooks/usePublish.ts
Normal file
171
src/hooks/usePublish.ts
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import { DDO, Logger, Metadata } from '@oceanprotocol/lib'
|
||||||
|
import {
|
||||||
|
Service,
|
||||||
|
ServiceComputePrivacy,
|
||||||
|
ServiceType
|
||||||
|
} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { sleep } from '../utils'
|
||||||
|
import { publishFeedback } from '../utils/feedback'
|
||||||
|
import { useOcean } from '../providers/Ocean'
|
||||||
|
|
||||||
|
interface DataTokenOptions {
|
||||||
|
cap?: string
|
||||||
|
name?: string
|
||||||
|
symbol?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UsePublish {
|
||||||
|
publish: (
|
||||||
|
asset: Metadata,
|
||||||
|
serviceType: ServiceType,
|
||||||
|
dataTokenOptions?: DataTokenOptions,
|
||||||
|
timeout?: number,
|
||||||
|
providerUri?: string
|
||||||
|
) => Promise<DDO | undefined | null>
|
||||||
|
publishStep?: number
|
||||||
|
publishStepText?: string
|
||||||
|
publishError?: string
|
||||||
|
isLoading: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function usePublish(): UsePublish {
|
||||||
|
const { ocean, account } = useOcean()
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [publishStep, setPublishStep] = useState<number | undefined>()
|
||||||
|
const [publishStepText, setPublishStepText] = useState<string | undefined>()
|
||||||
|
const [publishError, setPublishError] = useState<string | undefined>()
|
||||||
|
|
||||||
|
function setStep(index?: number) {
|
||||||
|
setPublishStep(index)
|
||||||
|
index && setPublishStepText(publishFeedback[index])
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Publish an asset. It also creates the datatoken, mints tokens and gives the market allowance
|
||||||
|
* @param {Metadata} asset The metadata of the asset.
|
||||||
|
* @param {PriceOptions} priceOptions : number of tokens to mint, datatoken weight , liquidity fee, type : fixed, dynamic
|
||||||
|
* @param {ServiceType} serviceType Desired service type of the asset access or compute
|
||||||
|
* @param {DataTokenOptions} dataTokenOptions custom name, symbol and cap for datatoken
|
||||||
|
* @return {Promise<DDO>} Returns the newly published ddo
|
||||||
|
*/
|
||||||
|
async function publish(
|
||||||
|
asset: Metadata,
|
||||||
|
serviceType: ServiceType,
|
||||||
|
dataTokenOptions?: DataTokenOptions,
|
||||||
|
timeout?: number,
|
||||||
|
providerUri?: string
|
||||||
|
): Promise<DDO | undefined | null> {
|
||||||
|
if (!ocean || !account) return null
|
||||||
|
setIsLoading(true)
|
||||||
|
setPublishError(undefined)
|
||||||
|
setStep(0)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const publishedDate =
|
||||||
|
new Date(Date.now()).toISOString().split('.')[0] + 'Z'
|
||||||
|
const services: Service[] = []
|
||||||
|
const price = '1'
|
||||||
|
|
||||||
|
switch (serviceType) {
|
||||||
|
case 'access': {
|
||||||
|
if (!timeout) timeout = 0
|
||||||
|
const accessService = await ocean.assets.createAccessServiceAttributes(
|
||||||
|
account,
|
||||||
|
price,
|
||||||
|
publishedDate,
|
||||||
|
timeout,
|
||||||
|
providerUri
|
||||||
|
)
|
||||||
|
Logger.log('access service created', accessService)
|
||||||
|
services.push(accessService)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'compute': {
|
||||||
|
if (!timeout) timeout = 3600
|
||||||
|
const cluster = ocean.compute.createClusterAttributes(
|
||||||
|
'Kubernetes',
|
||||||
|
'http://10.0.0.17/xxx'
|
||||||
|
)
|
||||||
|
const servers = [
|
||||||
|
ocean.compute.createServerAttributes(
|
||||||
|
'1',
|
||||||
|
'xlsize',
|
||||||
|
'50',
|
||||||
|
'16',
|
||||||
|
'0',
|
||||||
|
'128gb',
|
||||||
|
'160gb',
|
||||||
|
timeout
|
||||||
|
)
|
||||||
|
]
|
||||||
|
const containers = [
|
||||||
|
ocean.compute.createContainerAttributes(
|
||||||
|
'tensorflow/tensorflow',
|
||||||
|
'latest',
|
||||||
|
'sha256:cb57ecfa6ebbefd8ffc7f75c0f00e57a7fa739578a429b6f72a0df19315deadc'
|
||||||
|
)
|
||||||
|
]
|
||||||
|
const provider = ocean.compute.createProviderAttributes(
|
||||||
|
'Azure',
|
||||||
|
'Compute service with 16gb ram for each node.',
|
||||||
|
cluster,
|
||||||
|
containers,
|
||||||
|
servers
|
||||||
|
)
|
||||||
|
const origComputePrivacy: ServiceComputePrivacy = {
|
||||||
|
allowRawAlgorithm: true,
|
||||||
|
allowNetworkAccess: false,
|
||||||
|
publisherTrustedAlgorithms: []
|
||||||
|
}
|
||||||
|
const computeService = ocean.compute.createComputeService(
|
||||||
|
account,
|
||||||
|
price,
|
||||||
|
publishedDate,
|
||||||
|
provider,
|
||||||
|
origComputePrivacy,
|
||||||
|
timeout,
|
||||||
|
providerUri
|
||||||
|
)
|
||||||
|
services.push(computeService)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.log('services created', services)
|
||||||
|
|
||||||
|
const ddo = await ocean.assets
|
||||||
|
.create(
|
||||||
|
asset,
|
||||||
|
account,
|
||||||
|
services,
|
||||||
|
undefined,
|
||||||
|
dataTokenOptions?.cap,
|
||||||
|
dataTokenOptions?.name,
|
||||||
|
dataTokenOptions?.symbol,
|
||||||
|
providerUri
|
||||||
|
)
|
||||||
|
.next(setStep)
|
||||||
|
Logger.log('ddo created', ddo)
|
||||||
|
await sleep(20000)
|
||||||
|
setStep(7)
|
||||||
|
return ddo
|
||||||
|
} catch (error) {
|
||||||
|
setPublishError(error.message)
|
||||||
|
Logger.error(error)
|
||||||
|
setStep()
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
publish,
|
||||||
|
publishStep,
|
||||||
|
publishStepText,
|
||||||
|
isLoading,
|
||||||
|
publishError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { usePublish, UsePublish, DataTokenOptions }
|
||||||
|
export default usePublish
|
@ -14,6 +14,8 @@ const query = graphql`
|
|||||||
link
|
link
|
||||||
}
|
}
|
||||||
warning
|
warning
|
||||||
|
warningPolygon
|
||||||
|
warningPolygonPublish
|
||||||
appConfig {
|
appConfig {
|
||||||
infuraProjectId
|
infuraProjectId
|
||||||
network
|
network
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import TokenBalance from '../@types/TokenBalance'
|
import { PoolBalance } from '../@types/TokenBalance'
|
||||||
|
|
||||||
export interface FormTradeData extends TokenBalance {
|
export interface FormTradeData extends PoolBalance {
|
||||||
// in reference to datatoken, buy = swap from ocean to dt ( buy dt) , sell = swap from dt to ocean (sell dt)
|
// in reference to datatoken, buy = swap from ocean to dt ( buy dt) , sell = swap from dt to ocean (sell dt)
|
||||||
type: 'buy' | 'sell'
|
type: 'buy' | 'sell'
|
||||||
slippage: string
|
slippage: string
|
||||||
|
@ -3,7 +3,7 @@ import PageSearch from '../components/templates/Search'
|
|||||||
import { PageProps } from 'gatsby'
|
import { PageProps } from 'gatsby'
|
||||||
import Page from '../components/templates/Page'
|
import Page from '../components/templates/Page'
|
||||||
import queryString from 'query-string'
|
import queryString from 'query-string'
|
||||||
import { accountTruncate } from '../utils/wallet'
|
import { accountTruncate } from '../utils/web3'
|
||||||
import ethereumAddress from 'ethereum-address'
|
import ethereumAddress from 'ethereum-address'
|
||||||
|
|
||||||
export default function PageGatsbySearch(props: PageProps): ReactElement {
|
export default function PageGatsbySearch(props: PageProps): ReactElement {
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
} from '@apollo/client'
|
} from '@apollo/client'
|
||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from './Ocean'
|
||||||
import fetch from 'cross-fetch'
|
import fetch from 'cross-fetch'
|
||||||
import React, { useState, useEffect, ReactNode, ReactElement } from 'react'
|
import React, { useState, useEffect, ReactNode, ReactElement } from 'react'
|
||||||
|
|
||||||
|
@ -9,12 +9,14 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { Logger, DDO, BestPrice, MetadataMain } from '@oceanprotocol/lib'
|
import { Logger, DDO, BestPrice, MetadataMain } from '@oceanprotocol/lib'
|
||||||
import { PurgatoryData } from '@oceanprotocol/lib/dist/node/ddo/interfaces/PurgatoryData'
|
import { PurgatoryData } from '@oceanprotocol/lib/dist/node/ddo/interfaces/PurgatoryData'
|
||||||
import { getDataTokenPrice, useOcean } from '@oceanprotocol/react'
|
|
||||||
import getAssetPurgatoryData from '../utils/purgatory'
|
import getAssetPurgatoryData from '../utils/purgatory'
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
|
||||||
import axios, { CancelToken } from 'axios'
|
import axios, { CancelToken } from 'axios'
|
||||||
import { retrieveDDO } from '../utils/aquarius'
|
import { retrieveDDO } from '../utils/aquarius'
|
||||||
import { MetadataMarket } from '../@types/MetaData'
|
import { MetadataMarket } from '../@types/MetaData'
|
||||||
|
import { useOcean } from './Ocean'
|
||||||
|
import { gql, useQuery } from '@apollo/client'
|
||||||
|
import { PoolPrice } from '../@types/apollo/PoolPrice'
|
||||||
|
import { FrePrice } from '../@types/apollo/FrePrice'
|
||||||
|
|
||||||
interface AssetProviderValue {
|
interface AssetProviderValue {
|
||||||
isInPurgatory: boolean
|
isInPurgatory: boolean
|
||||||
@ -29,9 +31,24 @@ interface AssetProviderValue {
|
|||||||
error?: string
|
error?: string
|
||||||
refreshInterval: number
|
refreshInterval: number
|
||||||
refreshDdo: (token?: CancelToken) => Promise<void>
|
refreshDdo: (token?: CancelToken) => Promise<void>
|
||||||
refreshPrice: () => Promise<void>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const poolQuery = gql`
|
||||||
|
query PoolPrice($datatoken: String) {
|
||||||
|
pools(where: { datatokenAddress: $datatoken }) {
|
||||||
|
spotPrice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const freQuery = gql`
|
||||||
|
query FrePrice($datatoken: String) {
|
||||||
|
fixedRateExchanges(orderBy: id, where: { datatoken: $datatoken }) {
|
||||||
|
rate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const AssetContext = createContext({} as AssetProviderValue)
|
const AssetContext = createContext({} as AssetProviderValue)
|
||||||
|
|
||||||
const refreshInterval = 10000 // 10 sec.
|
const refreshInterval = 10000 // 10 sec.
|
||||||
@ -43,7 +60,7 @@ function AssetProvider({
|
|||||||
asset: string | DDO
|
asset: string | DDO
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { ocean, status, config, networkId } = useOcean()
|
const { config } = useOcean()
|
||||||
const [isInPurgatory, setIsInPurgatory] = useState(false)
|
const [isInPurgatory, setIsInPurgatory] = useState(false)
|
||||||
const [purgatoryData, setPurgatoryData] = useState<PurgatoryData>()
|
const [purgatoryData, setPurgatoryData] = useState<PurgatoryData>()
|
||||||
const [ddo, setDDO] = useState<DDO>()
|
const [ddo, setDDO] = useState<DDO>()
|
||||||
@ -54,27 +71,51 @@ function AssetProvider({
|
|||||||
const [owner, setOwner] = useState<string>()
|
const [owner, setOwner] = useState<string>()
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
const [type, setType] = useState<MetadataMain['type']>()
|
const [type, setType] = useState<MetadataMain['type']>()
|
||||||
|
const [variables, setVariables] = useState({})
|
||||||
|
|
||||||
const refreshPrice = useCallback(async () => {
|
const {
|
||||||
if (
|
refetch: refetchFre,
|
||||||
!ddo ||
|
startPolling: startPollingFre,
|
||||||
status !== 1 ||
|
data: frePrice
|
||||||
networkId !== (config as ConfigHelperConfig).networkId
|
} = useQuery<FrePrice>(freQuery, {
|
||||||
)
|
variables,
|
||||||
return
|
skip: true
|
||||||
|
})
|
||||||
|
const {
|
||||||
|
refetch: refetchPool,
|
||||||
|
startPolling: startPollingPool,
|
||||||
|
data: poolPrice
|
||||||
|
} = useQuery<PoolPrice>(poolQuery, {
|
||||||
|
variables,
|
||||||
|
skip: true
|
||||||
|
})
|
||||||
|
|
||||||
const newPrice = await getDataTokenPrice(
|
useEffect(() => {
|
||||||
ocean,
|
if (!ddo || !variables) return
|
||||||
ddo.dataToken,
|
if (ddo.price.type === 'exchange') {
|
||||||
ddo?.price?.type,
|
refetchFre(variables)
|
||||||
ddo.price.address
|
startPollingFre(refreshInterval)
|
||||||
)
|
} else {
|
||||||
setPrice(newPrice)
|
refetchPool(variables)
|
||||||
Logger.log(`Refreshed asset price: ${newPrice?.value}`, newPrice)
|
startPollingPool(refreshInterval)
|
||||||
}, [ocean, config, ddo, networkId, status])
|
}
|
||||||
|
}, [ddo, variables])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!frePrice || frePrice.fixedRateExchanges.length === 0) return
|
||||||
|
price.value = frePrice.fixedRateExchanges[0].rate
|
||||||
|
setPrice(price)
|
||||||
|
}, [frePrice])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!poolPrice || poolPrice.pools.length === 0) return
|
||||||
|
price.value = poolPrice.pools[0].spotPrice
|
||||||
|
price.value = 3222222
|
||||||
|
setPrice(price)
|
||||||
|
}, [poolPrice])
|
||||||
|
|
||||||
const fetchDdo = async (token?: CancelToken) => {
|
const fetchDdo = async (token?: CancelToken) => {
|
||||||
Logger.log('Init asset, get ddo')
|
Logger.log('[asset] Init asset, get DDO')
|
||||||
const ddo = await retrieveDDO(
|
const ddo = await retrieveDDO(
|
||||||
asset as string,
|
asset as string,
|
||||||
config.metadataCacheUri,
|
config.metadataCacheUri,
|
||||||
@ -83,7 +124,7 @@ function AssetProvider({
|
|||||||
|
|
||||||
if (!ddo) {
|
if (!ddo) {
|
||||||
setError(
|
setError(
|
||||||
`The DDO for ${asset} was not found in MetadataCache. If you just published a new data set, wait some seconds and refresh this page.`
|
`[asset] The DDO for ${asset} was not found in MetadataCache. If you just published a new data set, wait some seconds and refresh this page.`
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
setError(undefined)
|
setError(undefined)
|
||||||
@ -93,9 +134,10 @@ function AssetProvider({
|
|||||||
|
|
||||||
const refreshDdo = async (token?: CancelToken) => {
|
const refreshDdo = async (token?: CancelToken) => {
|
||||||
const ddo = await fetchDdo(token)
|
const ddo = await fetchDdo(token)
|
||||||
Logger.debug('DDO', ddo)
|
Logger.debug('[asset] Got DDO', ddo)
|
||||||
setDDO(ddo)
|
setDDO(ddo)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Get and set DDO based on passed DDO or DID
|
// Get and set DDO based on passed DDO or DID
|
||||||
//
|
//
|
||||||
@ -104,12 +146,11 @@ function AssetProvider({
|
|||||||
|
|
||||||
const source = axios.CancelToken.source()
|
const source = axios.CancelToken.source()
|
||||||
let isMounted = true
|
let isMounted = true
|
||||||
Logger.log('Init asset, get ddo')
|
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const ddo = await fetchDdo(source.token)
|
const ddo = await fetchDdo(source.token)
|
||||||
if (!isMounted) return
|
if (!isMounted) return
|
||||||
Logger.debug('DDO', ddo)
|
Logger.debug('[asset] Got DDO', ddo)
|
||||||
setDDO(ddo)
|
setDDO(ddo)
|
||||||
setDID(asset as string)
|
setDID(asset as string)
|
||||||
}
|
}
|
||||||
@ -120,57 +161,37 @@ function AssetProvider({
|
|||||||
}
|
}
|
||||||
}, [asset, config?.metadataCacheUri])
|
}, [asset, config?.metadataCacheUri])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Re-fetch price periodically, triggering re-calculation of everything
|
|
||||||
let isMounted = true
|
|
||||||
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
if (!isMounted) return
|
|
||||||
refreshPrice()
|
|
||||||
}, refreshInterval)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
clearInterval(interval)
|
|
||||||
isMounted = false
|
|
||||||
}
|
|
||||||
}, [ddo, networkId, refreshPrice])
|
|
||||||
|
|
||||||
const setPurgatory = useCallback(async (did: string): Promise<void> => {
|
const setPurgatory = useCallback(async (did: string): Promise<void> => {
|
||||||
if (!did) return
|
if (!did) return
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await getAssetPurgatoryData(did)
|
const result = await getAssetPurgatoryData(did)
|
||||||
|
const isInPurgatory = result?.did !== undefined
|
||||||
if (result?.did !== undefined) {
|
setIsInPurgatory(isInPurgatory)
|
||||||
setIsInPurgatory(true)
|
isInPurgatory && setPurgatoryData(result)
|
||||||
setPurgatoryData(result)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsInPurgatory(false)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error(error)
|
Logger.error(error)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const initMetadata = useCallback(
|
const initMetadata = useCallback(async (ddo: DDO): Promise<void> => {
|
||||||
async (ddo: DDO): Promise<void> => {
|
if (!ddo) return
|
||||||
if (!ddo) return
|
|
||||||
|
|
||||||
Logger.log('Init metadata')
|
// Set price & metadata from DDO first
|
||||||
// Set price & metadata from DDO first
|
setPrice(ddo.price)
|
||||||
setPrice(ddo.price)
|
setVariables({ datatoken: ddo?.dataToken.toLowerCase() })
|
||||||
const { attributes } = ddo.findServiceByType('metadata')
|
|
||||||
setMetadata((attributes as unknown) as MetadataMarket)
|
|
||||||
setTitle(attributes?.main.name)
|
|
||||||
setType(attributes.main.type)
|
|
||||||
setOwner(ddo.publicKey[0].owner)
|
|
||||||
setIsInPurgatory(ddo.isInPurgatory === 'true')
|
|
||||||
|
|
||||||
await setPurgatory(ddo.id)
|
// Get metadata from DDO
|
||||||
await refreshPrice()
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
},
|
setMetadata((attributes as unknown) as MetadataMarket)
|
||||||
[refreshPrice, setPurgatory]
|
setTitle(attributes?.main.name)
|
||||||
)
|
setType(attributes.main.type)
|
||||||
|
setOwner(ddo.publicKey[0].owner)
|
||||||
|
Logger.log('[asset] Got Metadata from DDO', attributes)
|
||||||
|
|
||||||
|
setIsInPurgatory(ddo.isInPurgatory === 'true')
|
||||||
|
await setPurgatory(ddo.id)
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ddo) return
|
if (!ddo) return
|
||||||
@ -192,8 +213,7 @@ function AssetProvider({
|
|||||||
isInPurgatory,
|
isInPurgatory,
|
||||||
purgatoryData,
|
purgatoryData,
|
||||||
refreshInterval,
|
refreshInterval,
|
||||||
refreshDdo,
|
refreshDdo
|
||||||
refreshPrice
|
|
||||||
} as AssetProviderValue
|
} as AssetProviderValue
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
163
src/providers/Ocean.tsx
Normal file
163
src/providers/Ocean.tsx
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
import React, {
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
createContext,
|
||||||
|
ReactElement,
|
||||||
|
useCallback,
|
||||||
|
ReactNode,
|
||||||
|
useEffect
|
||||||
|
} from 'react'
|
||||||
|
import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib'
|
||||||
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
|
import { useWeb3 } from './Web3'
|
||||||
|
import {
|
||||||
|
getDevelopmentConfig,
|
||||||
|
getOceanConfig,
|
||||||
|
getUserInfo
|
||||||
|
} from '../utils/ocean'
|
||||||
|
import { UserBalance } from '../@types/TokenBalance'
|
||||||
|
|
||||||
|
const refreshInterval = 20000 // 20 sec.
|
||||||
|
|
||||||
|
interface OceanProviderValue {
|
||||||
|
ocean: Ocean
|
||||||
|
config: ConfigHelperConfig | Config
|
||||||
|
account: Account
|
||||||
|
balance: UserBalance
|
||||||
|
connect: (config?: Config) => Promise<void>
|
||||||
|
refreshBalance: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
const OceanContext = createContext({} as OceanProviderValue)
|
||||||
|
|
||||||
|
function OceanProvider({
|
||||||
|
initialConfig,
|
||||||
|
children
|
||||||
|
}: {
|
||||||
|
initialConfig: Config | ConfigHelperConfig
|
||||||
|
children: ReactNode
|
||||||
|
}): ReactElement {
|
||||||
|
const { web3, accountId, networkId } = useWeb3()
|
||||||
|
const [ocean, setOcean] = useState<Ocean>()
|
||||||
|
const [account, setAccount] = useState<Account>()
|
||||||
|
const [balance, setBalance] = useState<UserBalance>({
|
||||||
|
eth: undefined,
|
||||||
|
ocean: undefined
|
||||||
|
})
|
||||||
|
const [config, setConfig] = useState<ConfigHelperConfig | Config>(
|
||||||
|
initialConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Create Ocean instance
|
||||||
|
// -----------------------------------
|
||||||
|
const connect = useCallback(
|
||||||
|
async (newConfig?: ConfigHelperConfig | Config) => {
|
||||||
|
try {
|
||||||
|
const usedConfig = newConfig || config
|
||||||
|
Logger.log('[ocean] Connecting Ocean...', usedConfig)
|
||||||
|
|
||||||
|
usedConfig.web3Provider = web3 || initialConfig.web3Provider
|
||||||
|
|
||||||
|
if (newConfig) {
|
||||||
|
setConfig(usedConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usedConfig.web3Provider) {
|
||||||
|
const newOcean = await Ocean.getInstance(usedConfig)
|
||||||
|
setOcean(newOcean)
|
||||||
|
Logger.log('[ocean] Ocean instance created.', newOcean)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('[ocean] Error: ', error.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[web3, config, initialConfig.web3Provider]
|
||||||
|
)
|
||||||
|
|
||||||
|
async function refreshBalance() {
|
||||||
|
if (!ocean || !account || !web3) return
|
||||||
|
|
||||||
|
const { balance } = await getUserInfo(ocean)
|
||||||
|
setBalance(balance)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Initial connection
|
||||||
|
// -----------------------------------
|
||||||
|
useEffect(() => {
|
||||||
|
async function init() {
|
||||||
|
await connect()
|
||||||
|
}
|
||||||
|
init()
|
||||||
|
|
||||||
|
// init periodic refresh of wallet balance
|
||||||
|
const balanceInterval = setInterval(() => refreshBalance(), refreshInterval)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(balanceInterval)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Get user info, handle account change from web3
|
||||||
|
// -----------------------------------
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ocean || !accountId || !web3) return
|
||||||
|
|
||||||
|
async function getInfo() {
|
||||||
|
const { account, balance } = await getUserInfo(ocean)
|
||||||
|
setAccount(account)
|
||||||
|
setBalance(balance)
|
||||||
|
}
|
||||||
|
getInfo()
|
||||||
|
}, [ocean, accountId, web3])
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Handle network change from web3
|
||||||
|
// -----------------------------------
|
||||||
|
useEffect(() => {
|
||||||
|
if (!networkId) return
|
||||||
|
|
||||||
|
async function reconnect() {
|
||||||
|
const newConfig = {
|
||||||
|
...getOceanConfig(networkId),
|
||||||
|
|
||||||
|
// add local dev values
|
||||||
|
...(networkId === 8996 && {
|
||||||
|
...getDevelopmentConfig()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await connect(newConfig)
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('[ocean] Error: ', error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reconnect()
|
||||||
|
}, [networkId])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OceanContext.Provider
|
||||||
|
value={
|
||||||
|
{
|
||||||
|
ocean,
|
||||||
|
account,
|
||||||
|
balance,
|
||||||
|
config,
|
||||||
|
connect,
|
||||||
|
refreshBalance
|
||||||
|
} as OceanProviderValue
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</OceanContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper hook to access the provider values
|
||||||
|
const useOcean = (): OceanProviderValue => useContext(OceanContext)
|
||||||
|
|
||||||
|
export { OceanProvider, useOcean, OceanProviderValue, OceanContext }
|
||||||
|
export default OceanProvider
|
@ -39,7 +39,7 @@ export default function PricesProvider({
|
|||||||
|
|
||||||
const onSuccess = async (data: { [tokenId]: { [key: string]: number } }) => {
|
const onSuccess = async (data: { [tokenId]: { [key: string]: number } }) => {
|
||||||
if (!data) return
|
if (!data) return
|
||||||
Logger.log(`Got new prices. ${JSON.stringify(data[tokenId])}`)
|
Logger.log('[prices] Got new OCEAN spot prices.', data[tokenId])
|
||||||
setPrices(data[tokenId])
|
setPrices(data[tokenId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,9 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import { Logger } from '@oceanprotocol/lib'
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
import { LogLevel } from '@oceanprotocol/lib/dist/node/utils/Logger'
|
import { LogLevel } from '@oceanprotocol/lib/dist/node/utils/Logger'
|
||||||
import { useOcean } from '@oceanprotocol/react'
|
import { useOcean } from './Ocean'
|
||||||
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
|
import { isBrowser } from '../utils'
|
||||||
|
|
||||||
interface UserPreferencesValue {
|
interface UserPreferencesValue {
|
||||||
debug: boolean
|
debug: boolean
|
||||||
@ -30,14 +31,13 @@ const localStorageKey = 'ocean-user-preferences'
|
|||||||
|
|
||||||
function getLocalStorage(): UserPreferencesValue {
|
function getLocalStorage(): UserPreferencesValue {
|
||||||
const storageParsed =
|
const storageParsed =
|
||||||
typeof window !== 'undefined' &&
|
isBrowser && JSON.parse(window.localStorage.getItem(localStorageKey))
|
||||||
JSON.parse(window.localStorage.getItem(localStorageKey))
|
|
||||||
return storageParsed
|
return storageParsed
|
||||||
}
|
}
|
||||||
|
|
||||||
function setLocalStorage(values: Partial<UserPreferencesValue>) {
|
function setLocalStorage(values: Partial<UserPreferencesValue>) {
|
||||||
return (
|
return (
|
||||||
typeof window !== 'undefined' &&
|
isBrowser &&
|
||||||
window.localStorage.setItem(localStorageKey, JSON.stringify(values))
|
window.localStorage.setItem(localStorageKey, JSON.stringify(values))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
253
src/providers/Web3.tsx
Normal file
253
src/providers/Web3.tsx
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
import React, {
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
useEffect,
|
||||||
|
createContext,
|
||||||
|
ReactElement,
|
||||||
|
ReactNode,
|
||||||
|
useCallback
|
||||||
|
} from 'react'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import Web3Modal from 'web3modal'
|
||||||
|
import { infuraProjectId as infuraId, portisId } from '../../app.config'
|
||||||
|
import WalletConnectProvider from '@walletconnect/web3-provider'
|
||||||
|
import { Logger } from '@oceanprotocol/lib'
|
||||||
|
import { isBrowser } from '../utils'
|
||||||
|
import {
|
||||||
|
EthereumListsChain,
|
||||||
|
getNetworkData,
|
||||||
|
getNetworkDisplayName
|
||||||
|
} from '../utils/web3'
|
||||||
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
|
|
||||||
|
interface Web3ProviderValue {
|
||||||
|
web3: Web3
|
||||||
|
web3Provider: any
|
||||||
|
web3Modal: Web3Modal
|
||||||
|
accountId: string
|
||||||
|
networkId: number
|
||||||
|
networkDisplayName: string
|
||||||
|
networkData: EthereumListsChain
|
||||||
|
isTestnet: boolean
|
||||||
|
connect: () => Promise<void>
|
||||||
|
logout: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
const web3ModalTheme = {
|
||||||
|
background: 'var(--background-body)',
|
||||||
|
main: 'var(--font-color-heading)',
|
||||||
|
secondary: 'var(--brand-grey-light)',
|
||||||
|
border: 'var(--border-color)',
|
||||||
|
hover: 'var(--background-highlight)'
|
||||||
|
}
|
||||||
|
|
||||||
|
// HEADS UP! We inline-require some packages so the Gatsby SSR build does not break.
|
||||||
|
// We only need them client-side.
|
||||||
|
const providerOptions = isBrowser
|
||||||
|
? {
|
||||||
|
walletconnect: {
|
||||||
|
package: WalletConnectProvider,
|
||||||
|
options: { infuraId }
|
||||||
|
},
|
||||||
|
portis: {
|
||||||
|
package: require('@portis/web3'),
|
||||||
|
options: {
|
||||||
|
id: portisId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// torus: {
|
||||||
|
// package: require('@toruslabs/torus-embed')
|
||||||
|
// // options: {
|
||||||
|
// // networkParams: {
|
||||||
|
// // host: oceanConfig.url, // optional
|
||||||
|
// // chainId: 1337, // optional
|
||||||
|
// // networkId: 1337 // optional
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
|
||||||
|
export const web3ModalOpts = {
|
||||||
|
cacheProvider: true,
|
||||||
|
providerOptions,
|
||||||
|
theme: web3ModalTheme
|
||||||
|
}
|
||||||
|
|
||||||
|
const networksQuery = graphql`
|
||||||
|
query {
|
||||||
|
allNetworksMetadataJson {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
chain
|
||||||
|
network
|
||||||
|
networkId
|
||||||
|
chainId
|
||||||
|
nativeCurrency {
|
||||||
|
name
|
||||||
|
symbol
|
||||||
|
decimals
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const Web3Context = createContext({} as Web3ProviderValue)
|
||||||
|
|
||||||
|
function Web3Provider({ children }: { children: ReactNode }): ReactElement {
|
||||||
|
const data = useStaticQuery(networksQuery)
|
||||||
|
const networksList: { node: EthereumListsChain }[] =
|
||||||
|
data.allNetworksMetadataJson.edges
|
||||||
|
|
||||||
|
const [web3, setWeb3] = useState<Web3>()
|
||||||
|
const [web3Provider, setWeb3Provider] = useState<any>()
|
||||||
|
const [web3Modal, setWeb3Modal] = useState<Web3Modal>()
|
||||||
|
const [networkId, setNetworkId] = useState<number>()
|
||||||
|
const [networkDisplayName, setNetworkDisplayName] = useState<string>()
|
||||||
|
const [networkData, setNetworkData] = useState<EthereumListsChain>()
|
||||||
|
const [isTestnet, setIsTestnet] = useState<boolean>()
|
||||||
|
const [accountId, setAccountId] = useState<string>()
|
||||||
|
|
||||||
|
const connect = useCallback(async () => {
|
||||||
|
if (!web3Modal) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
Logger.log('[web3] Connecting Web3...')
|
||||||
|
|
||||||
|
const provider = await web3Modal?.connect()
|
||||||
|
setWeb3Provider(provider)
|
||||||
|
|
||||||
|
const web3 = new Web3(provider)
|
||||||
|
setWeb3(web3)
|
||||||
|
Logger.log('[web3] Web3 created.', web3)
|
||||||
|
|
||||||
|
const networkId = await web3.eth.net.getId()
|
||||||
|
setNetworkId(networkId)
|
||||||
|
Logger.log('[web3] network id ', networkId)
|
||||||
|
|
||||||
|
const accountId = (await web3.eth.getAccounts())[0]
|
||||||
|
setAccountId(accountId)
|
||||||
|
Logger.log('[web3] account id', accountId)
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('[web3] Error: ', error.message)
|
||||||
|
}
|
||||||
|
}, [web3Modal])
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Create initial Web3Modal instance
|
||||||
|
// -----------------------------------
|
||||||
|
useEffect(() => {
|
||||||
|
if (web3Modal) return
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
// note: needs artificial await here so the log message is reached and output
|
||||||
|
const web3ModalInstance = await new Web3Modal(web3ModalOpts)
|
||||||
|
setWeb3Modal(web3ModalInstance)
|
||||||
|
Logger.log('[web3] Web3Modal instance created.', web3ModalInstance)
|
||||||
|
}
|
||||||
|
init()
|
||||||
|
}, [connect, web3Modal])
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Reconnect automatically for returning users
|
||||||
|
// -----------------------------------
|
||||||
|
useEffect(() => {
|
||||||
|
if (!web3Modal?.cachedProvider) return
|
||||||
|
|
||||||
|
async function connectCached() {
|
||||||
|
Logger.log(
|
||||||
|
'[web3] Connecting to cached provider: ',
|
||||||
|
web3Modal.cachedProvider
|
||||||
|
)
|
||||||
|
await connect()
|
||||||
|
}
|
||||||
|
connectCached()
|
||||||
|
}, [connect, web3Modal])
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Get and set network metadata
|
||||||
|
// -----------------------------------
|
||||||
|
useEffect(() => {
|
||||||
|
if (!networkId) return
|
||||||
|
|
||||||
|
const networkData = getNetworkData(networksList, networkId)
|
||||||
|
setNetworkData(networkData)
|
||||||
|
Logger.log('[web3] Network metadata found.', networkData)
|
||||||
|
|
||||||
|
// Construct network display name
|
||||||
|
const networkDisplayName = getNetworkDisplayName(networkData, networkId)
|
||||||
|
setNetworkDisplayName(networkDisplayName)
|
||||||
|
|
||||||
|
// Figure out if we're on a chain's testnet, or not
|
||||||
|
setIsTestnet(networkData.network !== 'mainnet')
|
||||||
|
|
||||||
|
Logger.log(`[web3] Network display name set to: ${networkDisplayName}`)
|
||||||
|
}, [networkId, networksList])
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Logout helper
|
||||||
|
// -----------------------------------
|
||||||
|
async function logout() {
|
||||||
|
web3Modal?.clearCachedProvider()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------
|
||||||
|
// Handle change events
|
||||||
|
// -----------------------------------
|
||||||
|
async function handleNetworkChanged(networkId: string) {
|
||||||
|
Logger.log('[web3] Network changed', networkId)
|
||||||
|
// const networkId = Number(chainId.replace('0x', ''))
|
||||||
|
setNetworkId(Number(networkId))
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleAccountsChanged(accounts: string[]) {
|
||||||
|
Logger.log('[web3] Account changed', accounts[0])
|
||||||
|
setAccountId(accounts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!web3Provider || !web3) return
|
||||||
|
|
||||||
|
//
|
||||||
|
// HEADS UP! We should rather listen to `chainChanged` exposing the `chainId`
|
||||||
|
// but for whatever reason the exposed `chainId` is wildly different from
|
||||||
|
// what is shown on https://chainid.network, in turn breaking our network/config
|
||||||
|
// mapping. The networkChanged is deprecated but works as expected for our case.
|
||||||
|
// See: https://eips.ethereum.org/EIPS/eip-1193#chainchanged
|
||||||
|
//
|
||||||
|
web3Provider.on('networkChanged', handleNetworkChanged)
|
||||||
|
web3Provider.on('accountsChanged', handleAccountsChanged)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
web3Provider.removeListener('networkChanged')
|
||||||
|
web3Provider.removeListener('accountsChanged')
|
||||||
|
}
|
||||||
|
}, [web3Provider, web3])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Web3Context.Provider
|
||||||
|
value={{
|
||||||
|
web3,
|
||||||
|
web3Provider,
|
||||||
|
web3Modal,
|
||||||
|
accountId,
|
||||||
|
networkId,
|
||||||
|
networkDisplayName,
|
||||||
|
networkData,
|
||||||
|
isTestnet,
|
||||||
|
connect,
|
||||||
|
logout
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Web3Context.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper hook to access the provider values
|
||||||
|
const useWeb3 = (): Web3ProviderValue => useContext(Web3Context)
|
||||||
|
|
||||||
|
export { Web3Provider, useWeb3, Web3ProviderValue, Web3Context }
|
||||||
|
export default Web3Provider
|
93
src/utils/dtUtils.ts
Normal file
93
src/utils/dtUtils.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import { Ocean, BestPrice, Logger } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
|
const priceError: BestPrice = {
|
||||||
|
type: '',
|
||||||
|
address: '',
|
||||||
|
pools: [],
|
||||||
|
datatoken: 0,
|
||||||
|
value: 0,
|
||||||
|
isConsumable: ''
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getFirstExchangePrice(
|
||||||
|
ocean: Ocean,
|
||||||
|
dataTokenAddress: string
|
||||||
|
): Promise<BestPrice> {
|
||||||
|
try {
|
||||||
|
const tokenExchanges = await ocean.fixedRateExchange.searchforDT(
|
||||||
|
dataTokenAddress,
|
||||||
|
'1'
|
||||||
|
)
|
||||||
|
if (tokenExchanges === undefined || tokenExchanges.length === 0) {
|
||||||
|
return priceError
|
||||||
|
}
|
||||||
|
|
||||||
|
const [tokenExchange] = tokenExchanges
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'exchange',
|
||||||
|
pools: [],
|
||||||
|
address: tokenExchange.exchangeID || '',
|
||||||
|
value: Number(tokenExchange.fixedRate),
|
||||||
|
ocean: 0,
|
||||||
|
datatoken: Number(tokenExchange.supply),
|
||||||
|
isConsumable: Number(tokenExchange.supply) > 0 ? 'true' : 'false'
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
Logger.log(err)
|
||||||
|
return priceError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getFirstPoolPrice(
|
||||||
|
ocean: Ocean,
|
||||||
|
dataTokenAddress: string,
|
||||||
|
poolAddress?: string
|
||||||
|
): Promise<BestPrice> {
|
||||||
|
let firstPoolAddress = poolAddress
|
||||||
|
if (!poolAddress) {
|
||||||
|
const tokenPools = await ocean.pool.searchPoolforDT(dataTokenAddress)
|
||||||
|
|
||||||
|
if (tokenPools === undefined || tokenPools.length === 0) {
|
||||||
|
return priceError
|
||||||
|
}
|
||||||
|
;[firstPoolAddress] = tokenPools
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!firstPoolAddress) return priceError
|
||||||
|
|
||||||
|
const firstPoolPrice = await ocean.pool.calcInGivenOut(
|
||||||
|
firstPoolAddress,
|
||||||
|
ocean.pool.oceanAddress,
|
||||||
|
dataTokenAddress,
|
||||||
|
'1'
|
||||||
|
)
|
||||||
|
const usePrice = await ocean.pool.getOceanNeeded(firstPoolAddress, '1')
|
||||||
|
const oceanReserve = await ocean.pool.getOceanReserve(firstPoolAddress)
|
||||||
|
|
||||||
|
const dtReserve = await ocean.pool.getDTReserve(firstPoolAddress)
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'pool',
|
||||||
|
pools: [firstPoolAddress],
|
||||||
|
address: firstPoolAddress,
|
||||||
|
value: Number(firstPoolPrice),
|
||||||
|
ocean: Number(oceanReserve),
|
||||||
|
datatoken: Number(dtReserve),
|
||||||
|
isConsumable: Number(usePrice) > 0 ? 'true' : 'false'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDataTokenPrice(
|
||||||
|
ocean: Ocean,
|
||||||
|
dataTokenAddress: string,
|
||||||
|
type: string,
|
||||||
|
poolAddress?: string
|
||||||
|
): Promise<BestPrice> {
|
||||||
|
const price =
|
||||||
|
type === 'pool'
|
||||||
|
? await getFirstPoolPrice(ocean, dataTokenAddress, poolAddress)
|
||||||
|
: await getFirstExchangePrice(ocean, dataTokenAddress)
|
||||||
|
|
||||||
|
return price
|
||||||
|
}
|
69
src/utils/feedback.ts
Normal file
69
src/utils/feedback.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
export const feedback: { [key in number]: string } = {
|
||||||
|
99: 'Decrypting file URL...',
|
||||||
|
0: '1/3 Looking for data token. Buying if none found...',
|
||||||
|
1: '2/3 Transfering data token.',
|
||||||
|
2: '3/3 Payment confirmed. Requesting access...'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const publishFeedback: { [key in number]: string } = {
|
||||||
|
0: '1/5 Creating datatoken ...',
|
||||||
|
2: '2/5 Encrypting files ...',
|
||||||
|
4: '3/5 Storing ddo ...',
|
||||||
|
6: '4/5 Minting tokens ...',
|
||||||
|
8: '5/5 Asset published succesfully'
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do something with this object,
|
||||||
|
// consumeStep should probably return one of those strings
|
||||||
|
// instead of just a number
|
||||||
|
export const consumeFeedback: { [key in number]: string } = {
|
||||||
|
...feedback,
|
||||||
|
3: '3/3 Access granted. Consuming file...'
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: customize for compute
|
||||||
|
export const computeFeedback: { [key in number]: string } = {
|
||||||
|
0: '1/3 Ordering asset...',
|
||||||
|
1: '2/3 Transfering data token.',
|
||||||
|
2: '3/3 Access granted. Starting job...'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCreatePricingPoolFeedback(
|
||||||
|
dtSymbol: string
|
||||||
|
): { [key: number]: string } {
|
||||||
|
return {
|
||||||
|
99: `Minting ${dtSymbol} ...`,
|
||||||
|
0: 'Creating pool ...',
|
||||||
|
1: `Approving ${dtSymbol} ...`,
|
||||||
|
2: 'Approving OCEAN ...',
|
||||||
|
3: 'Setup pool ...',
|
||||||
|
4: 'Pool created.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCreatePricingExchangeFeedback(
|
||||||
|
dtSymbol: string
|
||||||
|
): { [key: number]: string } {
|
||||||
|
return {
|
||||||
|
99: `Minting ${dtSymbol} ...`,
|
||||||
|
0: 'Creating exchange ...',
|
||||||
|
1: `Approving ${dtSymbol} ...`,
|
||||||
|
2: 'Fixed exchange created.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBuyDTFeedback(dtSymbol: string): { [key: number]: string } {
|
||||||
|
return {
|
||||||
|
1: '1/3 Approving OCEAN ...',
|
||||||
|
2: `2/3 Buying ${dtSymbol} ...`,
|
||||||
|
3: `3/3 ${dtSymbol} bought.`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSellDTFeedback(dtSymbol: string): { [key: number]: string } {
|
||||||
|
return {
|
||||||
|
1: '1/3 Approving OCEAN ...',
|
||||||
|
2: `2/3 Selling ${dtSymbol} ...`,
|
||||||
|
3: `3/3 ${dtSymbol} sold.`
|
||||||
|
}
|
||||||
|
}
|
@ -54,16 +54,8 @@ export async function fetchData(url: string): Promise<AxiosResponse['data']> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDid(did: string | undefined): boolean {
|
export function sleep(ms: number): Promise<void> {
|
||||||
const didMatch = (did as string).match(/^did:op:([a-f0-9]{64})$/i)
|
return new Promise((resolve) => {
|
||||||
return !!didMatch
|
setTimeout(resolve, ms)
|
||||||
}
|
})
|
||||||
|
|
||||||
export function formatBytes(a: number, b: number): string {
|
|
||||||
if (a === 0) return '0 Bytes'
|
|
||||||
const c = 1024
|
|
||||||
const d = b || 2
|
|
||||||
const e = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
||||||
const f = Math.floor(Math.log(a) / Math.log(c))
|
|
||||||
return parseFloat((a / Math.pow(c, f)).toFixed(d)) + ' ' + e[f]
|
|
||||||
}
|
}
|
||||||
|
47
src/utils/ocean.ts
Normal file
47
src/utils/ocean.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { Account, Config, Logger, Ocean } from '@oceanprotocol/lib'
|
||||||
|
import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
|
||||||
|
import {
|
||||||
|
ConfigHelper,
|
||||||
|
ConfigHelperConfig,
|
||||||
|
ConfigHelperNetworkId,
|
||||||
|
ConfigHelperNetworkName
|
||||||
|
} from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
||||||
|
import { UserBalance } from '../@types/TokenBalance'
|
||||||
|
|
||||||
|
export function getOceanConfig(
|
||||||
|
network: ConfigHelperNetworkName | ConfigHelperNetworkId
|
||||||
|
): Config {
|
||||||
|
return new ConfigHelper().getConfig(
|
||||||
|
network,
|
||||||
|
process.env.GATSBY_INFURA_PROJECT_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDevelopmentConfig(): Partial<ConfigHelperConfig> {
|
||||||
|
return {
|
||||||
|
factoryAddress: contractAddresses.development?.DTFactory,
|
||||||
|
poolFactoryAddress: contractAddresses.development?.BFactory,
|
||||||
|
fixedRateExchangeAddress: contractAddresses.development?.FixedRateExchange,
|
||||||
|
metadataContractAddress: contractAddresses.development?.Metadata,
|
||||||
|
oceanTokenAddress: contractAddresses.development?.Ocean,
|
||||||
|
// There is no subgraph in barge so we hardcode the Rinkeby one for now
|
||||||
|
subgraphUri: 'https://subgraph.rinkeby.oceanprotocol.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserInfo(
|
||||||
|
ocean: Ocean
|
||||||
|
): Promise<{ account: Account; balance: UserBalance }> {
|
||||||
|
if (!ocean) return { account: null, balance: { eth: '0', ocean: '0' } }
|
||||||
|
|
||||||
|
const account = (await ocean.accounts.list())[0]
|
||||||
|
Logger.log('[ocean] Account: ', account)
|
||||||
|
|
||||||
|
const balance = {
|
||||||
|
eth: await account.getEtherBalance(),
|
||||||
|
ocean: await account.getOceanBalance()
|
||||||
|
}
|
||||||
|
Logger.log('[ocean] Balance: ', JSON.stringify(balance))
|
||||||
|
|
||||||
|
return { account, balance }
|
||||||
|
}
|
15
src/utils/pricingFeedback.ts
Normal file
15
src/utils/pricingFeedback.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export function getBuyDTFeedback(dtSymbol: string): { [key: number]: string } {
|
||||||
|
return {
|
||||||
|
1: '1/3 Approving OCEAN ...',
|
||||||
|
2: `2/3 Buying ${dtSymbol} ...`,
|
||||||
|
3: `3/3 ${dtSymbol} bought.`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSellDTFeedback(dtSymbol: string): { [key: number]: string } {
|
||||||
|
return {
|
||||||
|
1: '1/3 Approving OCEAN ...',
|
||||||
|
2: `2/3 Selling ${dtSymbol} ...`,
|
||||||
|
3: `3/3 ${dtSymbol} sold.`
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,23 @@
|
|||||||
import { PurgatoryData } from '@oceanprotocol/lib'
|
import { PurgatoryData as PurgatoryDataAsset } from '@oceanprotocol/lib'
|
||||||
import axios from 'axios'
|
import { fetchData } from '.'
|
||||||
|
|
||||||
const purgatoryUrl = 'https://market-purgatory.oceanprotocol.com/api/'
|
const purgatoryUrl = 'https://market-purgatory.oceanprotocol.com/api/'
|
||||||
|
|
||||||
|
export interface PurgatoryDataAccount {
|
||||||
|
address: string
|
||||||
|
reason: string
|
||||||
|
}
|
||||||
|
|
||||||
export default async function getAssetPurgatoryData(
|
export default async function getAssetPurgatoryData(
|
||||||
did: string
|
did: string
|
||||||
): Promise<PurgatoryData> {
|
): Promise<PurgatoryDataAsset> {
|
||||||
const response = await axios(`${purgatoryUrl}asset?did=${did}`)
|
const data = await fetchData(`${purgatoryUrl}asset?did=${did}`)
|
||||||
const responseJson = await response.data[0]
|
return { did: data[0]?.did, reason: data[0]?.reason }
|
||||||
return { did: responseJson?.did, reason: responseJson?.reason }
|
}
|
||||||
|
|
||||||
|
export async function getAccountPurgatoryData(
|
||||||
|
address: string
|
||||||
|
): Promise<PurgatoryDataAccount> {
|
||||||
|
const data = await fetchData(`${purgatoryUrl}account?address=${address}`)
|
||||||
|
return { address: data[0]?.address, reason: data[0]?.reason }
|
||||||
}
|
}
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
import { infuraProjectId as infuraId, portisId } from '../../app.config'
|
|
||||||
import WalletConnectProvider from '@walletconnect/web3-provider'
|
|
||||||
|
|
||||||
export interface EthereumListsChain {
|
|
||||||
name: string
|
|
||||||
chainId: number
|
|
||||||
shortName: string
|
|
||||||
chain: string
|
|
||||||
network: string
|
|
||||||
networkId: number
|
|
||||||
nativeCurrency: { name: string; symbol: string; decimals: number }
|
|
||||||
rpc: string[]
|
|
||||||
faucets: string[]
|
|
||||||
infoURL: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const web3ModalTheme = {
|
|
||||||
background: 'var(--background-body)',
|
|
||||||
main: 'var(--font-color-heading)',
|
|
||||||
secondary: 'var(--brand-grey-light)',
|
|
||||||
border: 'var(--border-color)',
|
|
||||||
hover: 'var(--background-highlight)'
|
|
||||||
}
|
|
||||||
|
|
||||||
// HEADS UP! We inline-require some packages so the Gatsby SSR build does not break.
|
|
||||||
// We only need them client-side.
|
|
||||||
const providerOptions =
|
|
||||||
typeof window !== 'undefined'
|
|
||||||
? {
|
|
||||||
walletconnect: {
|
|
||||||
package: WalletConnectProvider,
|
|
||||||
options: { infuraId }
|
|
||||||
},
|
|
||||||
portis: {
|
|
||||||
package: require('@portis/web3'),
|
|
||||||
options: {
|
|
||||||
id: portisId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// torus: {
|
|
||||||
// package: require('@toruslabs/torus-embed')
|
|
||||||
// // options: {
|
|
||||||
// // networkParams: {
|
|
||||||
// // host: oceanConfig.url, // optional
|
|
||||||
// // chainId: 1337, // optional
|
|
||||||
// // networkId: 1337 // optional
|
|
||||||
// // }
|
|
||||||
// // }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
: {}
|
|
||||||
|
|
||||||
export const web3ModalOpts = {
|
|
||||||
cacheProvider: true,
|
|
||||||
providerOptions,
|
|
||||||
theme: web3ModalTheme
|
|
||||||
}
|
|
||||||
|
|
||||||
export function accountTruncate(account: string): string {
|
|
||||||
if (!account) return
|
|
||||||
const middle = account.substring(6, 38)
|
|
||||||
const truncated = account.replace(middle, '…')
|
|
||||||
return truncated
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getNetworkDisplayName(
|
|
||||||
data: EthereumListsChain,
|
|
||||||
networkId: number
|
|
||||||
): string {
|
|
||||||
const displayName = data
|
|
||||||
? `${data.chain} ${data.network === 'mainnet' ? '' : data.network}`
|
|
||||||
: networkId === 8996
|
|
||||||
? 'Development'
|
|
||||||
: 'Unknown'
|
|
||||||
|
|
||||||
return displayName
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getNetworkData(
|
|
||||||
data: { node: EthereumListsChain }[],
|
|
||||||
networkId: number
|
|
||||||
): EthereumListsChain {
|
|
||||||
const networkData = data.filter(
|
|
||||||
({ node }: { node: EthereumListsChain }) => node.networkId === networkId
|
|
||||||
)[0]
|
|
||||||
return networkData.node
|
|
||||||
}
|
|
42
src/utils/web3.ts
Normal file
42
src/utils/web3.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
export interface EthereumListsChain {
|
||||||
|
name: string
|
||||||
|
chainId: number
|
||||||
|
shortName: string
|
||||||
|
chain: string
|
||||||
|
network: string
|
||||||
|
networkId: number
|
||||||
|
nativeCurrency: { name: string; symbol: string; decimals: number }
|
||||||
|
rpc: string[]
|
||||||
|
faucets: string[]
|
||||||
|
infoURL: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function accountTruncate(account: string): string {
|
||||||
|
if (!account) return
|
||||||
|
const middle = account.substring(6, 38)
|
||||||
|
const truncated = account.replace(middle, '…')
|
||||||
|
return truncated
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNetworkDisplayName(
|
||||||
|
data: EthereumListsChain,
|
||||||
|
networkId: number
|
||||||
|
): string {
|
||||||
|
const displayName = data
|
||||||
|
? `${data.chain} ${data.network === 'mainnet' ? '' : data.network}`
|
||||||
|
: networkId === 8996
|
||||||
|
? 'Development'
|
||||||
|
: 'Unknown'
|
||||||
|
|
||||||
|
return displayName
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNetworkData(
|
||||||
|
data: { node: EthereumListsChain }[],
|
||||||
|
networkId: number
|
||||||
|
): EthereumListsChain {
|
||||||
|
const networkData = data.filter(
|
||||||
|
({ node }: { node: EthereumListsChain }) => node.networkId === networkId
|
||||||
|
)[0]
|
||||||
|
return networkData.node
|
||||||
|
}
|
@ -19,30 +19,7 @@ const reactMock = {
|
|||||||
accountId: '0x0000000011111111aaaaaaaabbbbbbbb22222222',
|
accountId: '0x0000000011111111aaaaaaaabbbbbbbb22222222',
|
||||||
balance: '0.12'
|
balance: '0.12'
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
useConsume: () => {
|
|
||||||
return {
|
|
||||||
consume: () => null as any,
|
|
||||||
consumeStepText: '',
|
|
||||||
isLoading: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useCompute: () => {
|
|
||||||
return {
|
|
||||||
compute: () => null as any,
|
|
||||||
isLoading: false,
|
|
||||||
computeStepText: 0,
|
|
||||||
computeError: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
useMetadata: () => {
|
|
||||||
return {
|
|
||||||
getCuration: () => {
|
|
||||||
return Promise.resolve({ rating: 0, numVotes: 0 })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computeOptions: ['', '']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default reactMock
|
export default reactMock
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import '@testing-library/jest-dom/extend-expect'
|
import '@testing-library/jest-dom/extend-expect'
|
||||||
import * as Gatsby from 'gatsby'
|
import * as Gatsby from 'gatsby'
|
||||||
import siteMetadata from './__fixtures__/siteMetadata.json'
|
import siteMetadata from './__fixtures__/siteMetadata.json'
|
||||||
// import mockReact from './__mocks__/@oceanprotocol/react'
|
|
||||||
|
|
||||||
if (typeof window.IntersectionObserver === 'undefined') {
|
if (typeof window.IntersectionObserver === 'undefined') {
|
||||||
import('intersection-observer')
|
import('intersection-observer')
|
||||||
@ -20,7 +19,6 @@ export const globalMock = {
|
|||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
jest.mock('web3')
|
jest.mock('web3')
|
||||||
jest.mock('@oceanprotocol/lib')
|
jest.mock('@oceanprotocol/lib')
|
||||||
jest.mock('@oceanprotocol/react')
|
|
||||||
|
|
||||||
// useOcean.mockImplementation(() => mockReact.useOcean())
|
// useOcean.mockImplementation(() => mockReact.useOcean())
|
||||||
useStaticQuery.mockImplementation(() => globalMock)
|
useStaticQuery.mockImplementation(() => globalMock)
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
import axios, { AxiosResponse } from 'axios'
|
import { toStringNoMS, updateQueryStringParameter } from '../../../src/utils'
|
||||||
|
|
||||||
import {
|
|
||||||
toStringNoMS,
|
|
||||||
updateQueryStringParameter,
|
|
||||||
isDid
|
|
||||||
} from '../../../src/utils'
|
|
||||||
|
|
||||||
jest.mock('axios')
|
|
||||||
|
|
||||||
describe('updateQueryStringParameter()', () => {
|
describe('updateQueryStringParameter()', () => {
|
||||||
it('transform a URI', () => {
|
it('transform a URI', () => {
|
||||||
@ -26,17 +18,3 @@ describe('toStringNoMS()', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('isDid()', () => {
|
|
||||||
it('checks correct DID', () => {
|
|
||||||
expect(
|
|
||||||
isDid(
|
|
||||||
'did:op:bb6b9e960b2e40e3840ca5eafc8eb97af431b4d190b54e2f9926e1f792cdc54f'
|
|
||||||
)
|
|
||||||
).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('errors when no DID', () => {
|
|
||||||
expect(isDid('hello')).toBe(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
Loading…
Reference in New Issue
Block a user