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

merged branch main into feature/account_page

This commit is contained in:
Bogdan Fazakas 2021-08-04 15:35:25 +03:00
commit cfd5b6558e
29 changed files with 5794 additions and 634 deletions

View File

@ -44,6 +44,13 @@
"options": ["Forever", "1 day", "1 week", "1 month", "1 year"],
"sortOptions": false,
"required": true
},
{
"name": "author",
"label": "New Author",
"placeholder": "e.g. Mrs McJellyfish",
"help": "Give proper attribution for your data set.",
"required": false
}
]
}

View File

@ -10,7 +10,11 @@
},
"fixed": {
"title": "Fixed",
"info": "Set your price for accessing this data set. The datatoken for this data set will be worth the entered amount of OCEAN."
"info": "Set your price for accessing this data set. The datatoken for this data set will be worth the entered amount of OCEAN.",
"tooltips": {
"communityFee": "Explain community fee...",
"marketplaceFee": "Explain marketplace fee..."
}
},
"dynamic": {
"title": "Dynamic",

5981
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -28,13 +28,13 @@
"@coingecko/cryptoformat": "^0.4.2",
"@loadable/component": "^5.15.0",
"@oceanprotocol/art": "^3.0.0",
"@oceanprotocol/lib": "^0.16.6",
"@oceanprotocol/lib": "^0.17.0",
"@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.4",
"@sindresorhus/slugify": "^2.1.0",
"@tippyjs/react": "^4.2.5",
"@urql/introspection": "^0.3.0",
"@walletconnect/web3-provider": "^1.5.0-rc.7",
"@walletconnect/web3-provider": "^1.5.2",
"axios": "^0.21.1",
"chart.js": "^2.9.4",
"classnames": "^2.3.1",
@ -86,7 +86,7 @@
"swr": "^0.5.6",
"urql": "^2.0.3",
"use-dark-mode": "^2.3.1",
"web3": "^1.4.0",
"web3": "^1.5.0",
"web3modal": "^1.9.3",
"yup": "^0.32.9"
},

View File

@ -64,6 +64,7 @@ export interface MetadataEditForm {
timeout: string
price?: number
links?: string | EditableMetadataLinks[]
author?: string
}
export interface ServiceMetadataMarket extends ServiceMetadata {

View File

@ -45,7 +45,8 @@
margin-bottom: 0;
}
.action {
.action,
button.action {
margin-top: calc(var(--spacer) / 2);
}

View File

@ -1,26 +1,22 @@
import { useField } from 'formik'
import { InputProps } from '../../../atoms/Input'
import { useOcean } from '../../../../providers/Ocean'
import React, { ReactElement, useEffect } from 'react'
import { utils } from '@oceanprotocol/lib'
import { InputProps } from '../../../atoms/Input'
import RefreshName from './RefreshName'
import styles from './index.module.css'
import RefreshName from './RefreshName'
export default function Datatoken(props: InputProps): ReactElement {
const { ocean } = useOcean()
const [field, meta, helpers] = useField(props.name)
function generateName() {
if (!ocean) return
const dataTokenOptions = ocean.datatokens.generateDtName()
async function generateName() {
const dataTokenOptions = utils.generateDatatokenName()
helpers.setValue({ ...dataTokenOptions })
}
// Generate new DT name & symbol
// Generate new DT name & symbol on first mount
useEffect(() => {
if (!ocean) return
generateName()
}, [ocean])
}, [])
return (
<div className={styles.datatoken}>

View File

@ -1,7 +1,7 @@
import Alert from '../atoms/Alert'
import Button from '../atoms/Button'
import Loader from '../atoms/Loader'
import React, { ReactElement } from 'react'
import React, { ReactElement, useState, FormEvent } from 'react'
import styles from './MetadataFeedback.module.css'
import SuccessConfetti from '../atoms/SuccessConfetti'
@ -55,13 +55,24 @@ export default function MetadataFeedback({
successAction: Action
setError: (error: string) => void
}): ReactElement {
const [moreInfo, setMoreInfo] = useState<boolean>(false)
function toggleMoreInfo(e: FormEvent<Element>) {
e.preventDefault()
moreInfo === true ? setMoreInfo(false) : setMoreInfo(true)
}
return (
<div className={styles.feedback}>
<div className={styles.box}>
<h3>{title}</h3>
{error ? (
<>
<Alert text={error} state="error" />
<p>Sorry, something went wrong. Please try again.</p>
{moreInfo && <Alert text={error} state="error" />}
<Button style="text" size="small" onClick={toggleMoreInfo}>
{moreInfo === false ? 'More Info' : 'Hide error'}
</Button>
<ActionError setError={setError} />
</>
) : success ? (

View File

@ -1,4 +1,4 @@
import React, { ReactElement, useEffect } from 'react'
import React, { ReactElement } from 'react'
import { useWeb3 } from '../../providers/Web3'
import Status from '../atoms/Status'
import styles from './Web3Feedback.module.css'
@ -22,7 +22,6 @@ export default function Web3Feedback({
const { isGraphSynced, blockGraph, blockHead } = useGraphSyncStatus()
const showFeedback =
!accountId ||
// !ocean ||
isBalanceSufficient === false ||
isAssetNetwork === false ||
isGraphSynced === false
@ -36,9 +35,7 @@ export default function Web3Feedback({
const title = !accountId
? 'No account connected'
: // : !ocean
// ? 'Error connecting to Ocean'
accountId && isAssetNetwork === false
: accountId && isAssetNetwork === false
? 'Not connected to asset network'
: isGraphSynced === false
? `Data out of sync`

View File

@ -1,5 +1,5 @@
.transactions {
composes: container from './index.module.css';
.actions {
composes: container from './AssetActions/Pool/index.module.css';
border-top: 1px solid var(--border-color);
margin-top: calc(var(--spacer) / 1.5);
padding: calc(var(--spacer) / 1.5);
@ -7,12 +7,12 @@
margin-bottom: -2rem;
}
.transactions [class*='rdt_Pagination'] {
.actions [class*='rdt_Pagination'] {
margin-bottom: -1rem;
}
.title {
composes: title from './index.module.css';
composes: title from './AssetActions/Pool/index.module.css';
margin-bottom: 0;
display: flex;
align-items: center;
@ -44,7 +44,7 @@
transform: rotate(180deg);
}
.transactions [class*='Table-module--table'] {
.actions [class*='Table-module--table'] {
/*
react-data-table-component sets a default width: 100%
which often leads to unneccessary overflows. Following lines make
@ -52,6 +52,9 @@
when enough space is available. But it also destroys overflow table on narrow
viewports.
*/
width: fit-content !important;
min-width: 100%;
width: 100%;
}
.actions [class*='TableCell'] {
width: 140px;
}

View File

@ -0,0 +1,36 @@
import React, { ReactElement, useState } from 'react'
import Button from '../atoms/Button'
import styles from './AssetActionHistoryTable.module.css'
import { ReactComponent as Caret } from '../../images/caret.svg'
import { ReactNode } from 'react-markdown'
export default function AssetActionHistoryTable({
title,
children
}: {
title: string
children: ReactNode
}): ReactElement {
const [open, setOpen] = useState(false)
function handleClick() {
setOpen(!open)
}
return (
<div className={`${styles.actions} ${open === true ? styles.open : ''}`}>
{/* TODO: onClick on h3 is nasty but we're in a hurry */}
<h3 className={styles.title} onClick={handleClick}>
{`${title} `}
<Button
style="text"
size="small"
onClick={handleClick}
className={styles.toggle}
>
{open ? 'Hide' : 'Show'} <Caret />
</Button>
</h3>
{open === true && children}
</div>
)
}

View File

@ -38,7 +38,8 @@ import { secondsToString } from '../../../../utils/metadata'
import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelection'
import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute'
import { getPreviousOrders, getPrice } from '../../../../utils/subgraph'
import { chainIds } from '../../../../../app.config'
import AssetActionHistoryTable from '../../AssetActionHistoryTable'
import ComputeJobs from '../../../pages/History/ComputeJobs'
const SuccessAction = () => (
<Button style="text" to="/account?defaultTab=ComputeJobs" size="small">
@ -473,6 +474,15 @@ export default function Compute({
/>
)}
</footer>
{accountId && (
<AssetActionHistoryTable title="Your Compute Jobs">
<ComputeJobs
minimal
assetDTAddress={ddo.dataTokenInfo.address}
chainId={ddo.chainId}
/>
</AssetActionHistoryTable>
)}
</>
)
}

View File

@ -105,7 +105,8 @@ export default function Edit({
const ddoEditedMetdata = await ocean.assets.editMetadata(ddo, {
title: values.name,
description: values.description,
links: typeof values.links !== 'string' ? values.links : []
links: typeof values.links !== 'string' ? values.links : [],
author: values.author === '' ? ' ' : values.author
})
price.type === 'exchange' &&

View File

@ -1,36 +0,0 @@
import React, { ReactElement, useState } from 'react'
import Button from '../../../atoms/Button'
import PoolTransactions from '../../../molecules/PoolTransactions'
import styles from './Transactions.module.css'
import { ReactComponent as Caret } from '../../../../images/caret.svg'
import { useAsset } from '../../../../providers/Asset'
export default function Transactions(): ReactElement {
const [open, setOpen] = useState(false)
const { price } = useAsset()
function handleClick() {
setOpen(!open)
}
return (
<div
className={`${styles.transactions} ${open === true ? styles.open : ''}`}
>
{/* TODO: onClick on h3 is nasty but we're in a hurry */}
<h3 className={styles.title} onClick={handleClick}>
Your Pool Transactions{' '}
<Button
style="text"
size="small"
onClick={handleClick}
className={styles.toggle}
>
{open ? 'Hide' : 'Show'} <Caret />
</Button>
</h3>
{open === true && (
<PoolTransactions poolAddress={price?.address} minimal />
)}
</div>
)
}

View File

@ -12,13 +12,14 @@ import Token from './Token'
import TokenList from './TokenList'
import { graphql, useStaticQuery } from 'gatsby'
import { PoolBalance } from '../../../../@types/TokenBalance'
import Transactions from './Transactions'
import AssetActionHistoryTable from '../../AssetActionHistoryTable'
import Graph from './Graph'
import { useAsset } from '../../../../providers/Asset'
import { gql, OperationResult } from 'urql'
import { PoolLiquidity } from '../../../../@types/apollo/PoolLiquidity'
import { useOcean } from '../../../../providers/Ocean'
import { useWeb3 } from '../../../../providers/Web3'
import PoolTransactions from '../../../molecules/PoolTransactions'
import { fetchData, getQueryContext } from '../../../../utils/subgraph'
const REFETCH_INTERVAL = 5000
@ -383,7 +384,11 @@ export default function Pool(): ReactElement {
)}
</div>
{accountId && <Transactions />}
{accountId && (
<AssetActionHistoryTable title="Your Pool Transactions">
<PoolTransactions poolAddress={price?.address} minimal />
</AssetActionHistoryTable>
)}
</>
)}
</>

View File

@ -112,7 +112,7 @@ export default function Dynamic({
/>
</div>
<Fees tooltips={content.tooltips} />
<Fees tooltips={content.tooltips} pricingType="dynamic" />
<footer className={styles.summary}>
You will get: <br />

View File

@ -5,14 +5,18 @@
margin-left: -2rem;
margin-right: -2rem;
border-bottom: 1px solid var(--border-color);
padding: var(--spacer) var(--spacer) calc(var(--spacer) / 2) var(--spacer);
padding: var(--spacer);
justify-content: center;
text-align: center;
border-bottom: 1px solid var(--border-color);
background: var(--background-highlight);
}
.fees > div {
margin-bottom: 0;
justify-self: center;
}
.fees label {
white-space: nowrap;
}

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react'
import Tooltip from '../../../../atoms/Tooltip'
import styles from './Fees.module.css'
import { useField, useFormikContext } from 'formik'
import { useField } from 'formik'
import Input from '../../../../atoms/Input'
import Error from './Error'
@ -30,31 +30,35 @@ const Default = ({
)
export default function Fees({
tooltips
tooltips,
pricingType
}: {
tooltips: { [key: string]: string }
pricingType: 'dynamic' | 'fixed'
}): ReactElement {
const [field, meta] = useField('swapFee')
return (
<>
<div className={styles.fees}>
<Input
label={
<>
Swap Fee
<Tooltip content={tooltips.swapFee} />
</>
}
type="number"
postfix="%"
min="0.1"
max="10"
step="0.1"
size="small"
{...field}
additionalComponent={<Error meta={meta} />}
/>
{pricingType === 'dynamic' && (
<Input
label={
<>
Swap Fee
<Tooltip content={tooltips.swapFee} />
</>
}
type="number"
postfix="%"
min="0.1"
max="10"
step="0.1"
size="small"
{...field}
additionalComponent={<Error meta={meta} />}
/>
)}
<Default
title="Community Fee"

View File

@ -4,6 +4,7 @@ import styles from './Fixed.module.css'
import FormHelp from '../../../../atoms/Input/Help'
import { DDO } from '@oceanprotocol/lib'
import Price from './Price'
import Fees from './Fees'
export default function Fixed({
ddo,
@ -16,6 +17,7 @@ export default function Fixed({
<div className={styles.fixed}>
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
<Price ddo={ddo} />
<Fees tooltips={content.tooltips} pricingType="fixed" />
</div>
)
}

View File

@ -2,17 +2,13 @@
position: relative;
}
@media (min-width: 55rem) {
.form {
max-width: 12rem;
margin-left: auto;
}
.form * {
margin-bottom: 0;
}
.price {
margin-left: -2rem;
margin-right: -2rem;
padding-top: var(--spacer);
background: var(--background-highlight);
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
@ -20,9 +16,13 @@
.grid {
display: grid;
gap: var(--spacer);
gap: calc(var(--spacer) / 2);
grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
justify-content: center;
padding: var(--spacer);
max-width: 30rem;
margin-left: auto;
margin-right: auto;
align-items: center;
}
.fixed label {
@ -30,7 +30,6 @@
}
.datatoken {
margin-top: calc(var(--spacer) / 2);
color: var(--color-secondary);
font-size: var(--font-size-small);
font-weight: var(--font-weight-bold);
@ -50,7 +49,6 @@
font-size: var(--font-size-small);
color: var(--color-secondary);
text-align: center;
margin-top: -1rem;
padding-top: calc(var(--spacer) / 3);
padding-bottom: calc(var(--spacer) / 3);
border-top: 1px solid var(--border-color);
@ -59,3 +57,7 @@
.firstPrice div {
display: inline-block;
}
.conversion strong {
color: var(--color-secondary);
}

View File

@ -2,11 +2,11 @@ import Conversion from '../../../../atoms/Price/Conversion'
import { useField } from 'formik'
import React, { ReactElement, useState, useEffect } from 'react'
import Input from '../../../../atoms/Input'
import styles from './Price.module.css'
import Error from './Error'
import { DDO } from '@oceanprotocol/lib'
import PriceUnit from '../../../../atoms/Price/PriceUnit'
import usePricing from '../../../../../hooks/usePricing'
import styles from './Price.module.css'
export default function Price({
ddo,
@ -56,16 +56,14 @@ export default function Price({
prefix="OCEAN"
min="1"
{...field}
additionalComponent={
<Conversion price={field.value} className={styles.conversion} />
}
/>
)}
<Error meta={meta} />
</div>
<div className={styles.datatoken}>
<h4>
= <strong>1</strong> {dtName} {dtSymbol}
= <strong>1</strong> {dtSymbol}{' '}
<Conversion price={field.value} className={styles.conversion} />
</h4>
</div>
</div>

View File

@ -4,12 +4,12 @@ import { initialValues, validationSchema } from '../../../../models/FormPricing'
import { DDO, Logger } from '@oceanprotocol/lib'
import { PriceOptionsMarket } from '../../../../@types/MetaData'
import Alert from '../../../atoms/Alert'
import styles from './index.module.css'
import FormPricing from './FormPricing'
import { toast } from 'react-toastify'
import Feedback from './Feedback'
import { graphql, useStaticQuery } from 'gatsby'
import { usePricing } from '../../../../hooks/usePricing'
import styles from './index.module.css'
const query = graphql`
query PricingQuery {
@ -29,6 +29,10 @@ const query = graphql`
fixed {
title
info
tooltips {
communityFee
marketplaceFee
}
}
dynamic {
title

View File

@ -46,6 +46,27 @@ const getComputeOrders = gql`
}
`
const getComputeOrdersByDatatokenAddress = gql`
query ComputeOrdersByDatatokenAddress(
$user: String!
$datatokenAddress: String!
) {
tokenOrders(
orderBy: timestamp
orderDirection: desc
where: { payer: $user, datatokenId: $datatokenAddress }
) {
id
serviceId
datatokenId {
address
}
tx
timestamp
}
}
`
interface TokenOrder {
id: string
serviceId: number
@ -127,13 +148,23 @@ async function getAssetMetadata(
return result.results
}
export default function ComputeJobs(): ReactElement {
export default function ComputeJobs({
minimal,
assetDTAddress,
chainId
}: {
minimal?: boolean
assetDTAddress?: string
chainId?: number
}): ReactElement {
const { ocean, account, config, connect } = useOcean()
const { accountId, networkId } = useWeb3()
const { chainIds } = useUserPreferences()
const [isLoading, setIsLoading] = useState(true)
const { chainIds } = useUserPreferences()
const [jobs, setJobs] = useState<ComputeJobMetaData[]>([])
const columnsMinimal = [columns[4], columns[5], columns[3]]
useEffect(() => {
async function initOcean() {
const oceanInitialConfig = getOceanConfig(networkId)
@ -147,11 +178,18 @@ export default function ComputeJobs(): ReactElement {
async function getJobs() {
if (!accountId) return
setIsLoading(true)
const variables = { user: accountId?.toLowerCase() }
const variables = assetDTAddress
? {
user: accountId?.toLowerCase(),
datatokenAddress: assetDTAddress.toLowerCase()
}
: {
user: accountId?.toLowerCase()
}
const result = await fetchDataForMultipleChains(
getComputeOrders,
assetDTAddress ? getComputeOrdersByDatatokenAddress : getComputeOrders,
variables,
chainIds
assetDTAddress ? [chainId] : chainIds
)
let data: TokenOrder[] = []
for (let i = 0; i < result.length; i++) {
@ -293,20 +331,21 @@ export default function ComputeJobs(): ReactElement {
return accountId ? (
<>
<Button
style="text"
size="small"
title="Refresh compute jobs"
onClick={() => getJobs()}
disabled={isLoading}
className={styles.refresh}
>
<Refresh />
Refresh
</Button>
{jobs.length <= 0 || minimal || (
<Button
style="text"
size="small"
title="Refresh compute jobs"
onClick={() => getJobs()}
disabled={isLoading}
className={styles.refresh}
>
<Refresh />
Refresh
</Button>
)}
<Table
columns={columns}
columns={minimal ? columnsMinimal : columns}
data={jobs}
isLoading={isLoading}
defaultSortField="row.dateCreated"

View File

@ -43,7 +43,6 @@ export default function FormPublish(): ReactElement {
const data = useStaticQuery(query)
const content: FormContent = data.content.edges[0].node.childPublishJson
const { ocean, account } = useOcean()
const {
status,
setStatus,

View File

@ -33,15 +33,6 @@ export const FilterByTypeOptions = {
type FilterByTypeOptions =
typeof FilterByTypeOptions[keyof typeof FilterByTypeOptions]
function addTypeFilterToQuery(sortTerm: string, typeFilter: string): string {
sortTerm = typeFilter
? sortTerm === ''
? `service.attributes.main.type:${typeFilter}`
: `${sortTerm} AND service.attributes.main.type:${typeFilter}`
: sortTerm
return sortTerm
}
function getSortType(sortParam: string): string {
const sortTerm =
sortParam === SortTermOptions.Created
@ -65,7 +56,6 @@ export function getSearchQuery(
const sortTerm = getSortType(sort)
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
const emptySearchTerm = text === undefined || text === ''
let searchTerm = owner
? `(publicKey.owner:${owner})`
: tags
@ -77,16 +67,26 @@ export function getSearchQuery(
: text || ''
searchTerm = searchTerm.trim()
let modifiedSearchTerm = searchTerm.split(' ').join(' OR ').trim()
modifiedSearchTerm = addTypeFilterToQuery(modifiedSearchTerm, serviceType)
searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
const modifiedSearchTerm = searchTerm.split(' ').join(' OR ').trim()
const noSpaceSearchTerm = searchTerm.split(' ').join('').trim()
const prefixedSearchTerm =
emptySearchTerm && searchTerm
? searchTerm
: !emptySearchTerm && searchTerm
? '*' + searchTerm + '*'
: '**'
const searchFields = [
'id',
'publicKey.owner',
'dataToken',
'dataTokenInfo.name',
'dataTokenInfo.symbol',
'service.attributes.main.name^10',
'service.attributes.main.author',
'service.attributes.additionalInformation.description',
'service.attributes.additionalInformation.tags'
]
return {
page: Number(page) || 1,
offset: Number(offset) || 21,
@ -99,22 +99,20 @@ export function getSearchQuery(
{
query_string: {
query: `${modifiedSearchTerm}`,
fields: [
'id',
'publicKey.owner',
'dataToken',
'dataTokenInfo.name',
'dataTokenInfo.symbol',
'service.attributes.main.name^10',
'service.attributes.main.author',
'service.attributes.additionalInformation.description',
'service.attributes.additionalInformation.tags'
],
fields: searchFields,
minimum_should_match: '2<75%',
phrase_slop: 2,
boost: 5
}
},
{
query_string: {
query: `${noSpaceSearchTerm}*`,
fields: searchFields,
boost: 5,
lenient: true
}
},
{
match_phrase: {
content: {
@ -126,23 +124,21 @@ export function getSearchQuery(
{
query_string: {
query: `${prefixedSearchTerm}`,
fields: [
'id',
'publicKey.owner',
'dataToken',
'dataTokenInfo.name',
'dataTokenInfo.symbol',
'service.attributes.main.name',
'service.attributes.main.author',
'service.attributes.additionalInformation.description',
'service.attributes.additionalInformation.tags'
],
fields: searchFields,
default_operator: 'AND'
}
}
]
}
},
{
match: {
'service.attributes.main.type':
serviceType === undefined
? 'dataset OR algorithm'
: `${serviceType}`
}
},
{
query_string: {
query: `${transformChainIdsListToQuery(chainIds)}`

View File

@ -4,10 +4,12 @@ import {
ServiceComputePrivacy,
ServiceType
} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { sleep } from '../utils'
import { publishFeedback } from '../utils/feedback'
import { useOcean } from '../providers/Ocean'
import { useWeb3 } from '../providers/Web3'
import { getOceanConfig } from '../utils/ocean'
interface DataTokenOptions {
cap?: string
@ -30,7 +32,8 @@ interface UsePublish {
}
function usePublish(): UsePublish {
const { ocean, account } = useOcean()
const { networkId, web3Loading } = useWeb3()
const { connect, ocean, account } = useOcean()
const [isLoading, setIsLoading] = useState(false)
const [publishStep, setPublishStep] = useState<number | undefined>()
const [publishStepText, setPublishStepText] = useState<string | undefined>()
@ -40,6 +43,20 @@ function usePublish(): UsePublish {
setPublishStep(index)
index && setPublishStepText(publishFeedback[index])
}
//
// Initiate OceanProvider based on user wallet
//
useEffect(() => {
if (web3Loading || !connect) return
async function initOcean() {
const config = getOceanConfig(networkId)
await connect(config)
}
initOcean()
}, [web3Loading, networkId, connect])
/**
* Publish an asset. It also creates the datatoken, mints tokens and gives the market allowance
* @param {Metadata} asset The metadata of the asset.

View File

@ -10,7 +10,8 @@ export const validationSchema = Yup.object().shape({
description: Yup.string().required('Required').min(10),
price: Yup.number().required('Required'),
links: Yup.array<EditableMetadataLinks[]>().nullable(),
timeout: Yup.string().required('Required')
timeout: Yup.string().required('Required'),
author: Yup.string().nullable()
})
export function getInitialValues(
@ -23,6 +24,7 @@ export function getInitialValues(
description: metadata.additionalInformation.description,
price,
links: metadata.additionalInformation.links,
timeout: secondsToString(timeout)
timeout: secondsToString(timeout),
author: metadata.main.author
}
}

View File

@ -2,15 +2,18 @@ import React, { ReactElement } from 'react'
import PagePublish from '../components/pages/Publish'
import Page from '../components/templates/Page'
import { graphql, PageProps } from 'gatsby'
import OceanProvider from '../providers/Ocean'
export default function PageGatsbyPublish(props: PageProps): ReactElement {
const content = (props.data as any).content.edges[0].node.childPublishJson
const { title, description } = content
return (
<Page title={title} description={description} uri={props.uri}>
<PagePublish content={content} />
</Page>
<OceanProvider>
<Page title={title} description={description} uri={props.uri}>
<PagePublish content={content} />
</Page>
</OceanProvider>
)
}

View File

@ -8,7 +8,6 @@ import React, {
useEffect
} from 'react'
import { Ocean, Logger, Account, ConfigHelperConfig } from '@oceanprotocol/lib'
import { useWeb3 } from './Web3'
import { getDevelopmentConfig, getOceanConfig } from '../utils/ocean'
import { useAsset } from './Asset'
@ -56,7 +55,7 @@ function OceanProvider({ children }: { children: ReactNode }): ReactElement {
)
// -----------------------------------
// Initial connection
// Initial asset details connection
// -----------------------------------
useEffect(() => {
if (!ddo?.chainId) return