diff --git a/src/@hooks/usePricing.ts b/src/@hooks/usePricing.ts index 452c854f6..e7f7c8609 100644 --- a/src/@hooks/usePricing.ts +++ b/src/@hooks/usePricing.ts @@ -129,7 +129,7 @@ function usePricing(): UsePricing { Decimal.set({ precision: 18 }) switch (price?.type) { - case 'pool': { + case 'dynamic': { const oceanAmmount = new Decimal(price.value).times(1.05).toString() const maxPrice = new Decimal(price.value).times(2).toString() @@ -152,7 +152,7 @@ function usePricing(): UsePricing { Logger.log('DT buy response', tx) break } - case 'exchange': { + case 'fixed': { if (!config.oceanTokenAddress) { Logger.error(`'oceanTokenAddress' not set in config`) return diff --git a/src/@types/DDO/Services.d.ts b/src/@types/DDO/Services.d.ts index 994c6ec83..7ff1588b1 100644 --- a/src/@types/DDO/Services.d.ts +++ b/src/@types/DDO/Services.d.ts @@ -22,7 +22,7 @@ interface Service { files: string datatokenAddress: string serviceEndpoint: string - timeout: string + timeout: number name?: string description?: string compute?: ServiceComputeOptions diff --git a/src/@types/Price.d.ts b/src/@types/Price.d.ts index 37d927c96..9ca072b59 100644 --- a/src/@types/Price.d.ts +++ b/src/@types/Price.d.ts @@ -1,5 +1,5 @@ interface BestPrice { - type: 'pool' | 'exchange' | 'free' | '' + type: 'dynamic' | 'fixed' | 'free' | '' address: string value: number isConsumable?: 'true' | 'false' | '' @@ -15,7 +15,7 @@ interface PriceOptions { price: number amountDataToken: number amountOcean: number - type: 'fixed' | 'dynamic' | 'free' | string + type: 'dynamic' | 'fixed' | 'free' | '' weightOnDataToken: string weightOnOcean: string // easier to keep this as number for Yup input validation diff --git a/src/@utils/provider.ts b/src/@utils/provider.ts index b0f5b040d..fe0bd2808 100644 --- a/src/@utils/provider.ts +++ b/src/@utils/provider.ts @@ -2,6 +2,8 @@ import axios, { CancelToken, AxiosResponse } from 'axios' import { DID, Logger } from '@oceanprotocol/lib' export interface FileMetadata { + index: number + valid: boolean contentType: string contentLength: string } @@ -35,20 +37,13 @@ export async function getFileInfo( ): Promise { let postBody try { - if (url instanceof DID) - postBody = { - did: url.getDid() - } - else - postBody = { - url - } + if (url instanceof DID) postBody = { did: url.getDid() } + else postBody = { url } + const response: AxiosResponse = await axios.post( `${providerUrl}/api/v1/services/fileinfo`, postBody, - { - cancelToken - } + { cancelToken } ) if (!response || response.status !== 200 || !response.data) return diff --git a/src/@utils/subgraph.ts b/src/@utils/subgraph.ts index 38819d064..90f36122d 100644 --- a/src/@utils/subgraph.ts +++ b/src/@utils/subgraph.ts @@ -346,7 +346,7 @@ function transformPriceToBestPrice( ) { if (poolPrice?.length > 0) { const price: BestPrice = { - type: 'pool', + type: 'dynamic', address: poolPrice[0]?.id, value: poolPrice[0]?.consumePrice === '-1' @@ -363,7 +363,7 @@ function transformPriceToBestPrice( // TODO Hacky hack, temporary™: set isConsumable to true for fre assets. // isConsumable: 'true' const price: BestPrice = { - type: 'exchange', + type: 'fixed', value: frePrice[0]?.rate, address: frePrice[0]?.id, exchangeId: frePrice[0]?.id, diff --git a/src/@utils/web3.ts b/src/@utils/web3.ts index db4825e02..bcc766fcd 100644 --- a/src/@utils/web3.ts +++ b/src/@utils/web3.ts @@ -3,7 +3,7 @@ import { Logger } from '@oceanprotocol/lib' import { getOceanConfig } from './ocean' export function accountTruncate(account: string): string { - if (!account) return + if (!account || account === '') return const middle = account.substring(6, 38) const truncated = account.replace(middle, '…') return truncated diff --git a/src/components/@shared/DebugOutput.tsx b/src/components/@shared/DebugOutput.tsx index c0931a3ec..9f42da559 100644 --- a/src/components/@shared/DebugOutput.tsx +++ b/src/components/@shared/DebugOutput.tsx @@ -10,7 +10,7 @@ export default function DebugOutput({ return (
{title}
-
+      
         {JSON.stringify(output, null, 2)}
       
diff --git a/src/components/@shared/FormFields/FilesInput/Info.tsx b/src/components/@shared/FormFields/FilesInput/Info.tsx index 5d54fd961..ca41ba8f4 100644 --- a/src/components/@shared/FormFields/FilesInput/Info.tsx +++ b/src/components/@shared/FormFields/FilesInput/Info.tsx @@ -22,7 +22,7 @@ export default function FileInfo({ return (
- {/*

{file}

*/} +

{(file as any).url}

  • URL confirmed
  • {file.contentLength &&
  • {prettySize(+file.contentLength)}
  • } diff --git a/src/components/@shared/FormFields/FilesInput/index.tsx b/src/components/@shared/FormFields/FilesInput/index.tsx index 89f587f49..1e377b7f8 100644 --- a/src/components/@shared/FormFields/FilesInput/index.tsx +++ b/src/components/@shared/FormFields/FilesInput/index.tsx @@ -27,7 +27,7 @@ export default function FilesInput(props: InputProps): ReactElement { config?.providerUri, newCancelToken() ) - checkedFile && helpers.setValue([checkedFile]) + checkedFile && helpers.setValue([{ url: fileUrl, ...checkedFile[0] }]) } catch (error) { toast.error('Could not fetch file info. Please check URL and try again') console.error(error.message) diff --git a/src/components/@shared/Publisher/index.tsx b/src/components/@shared/Publisher/index.tsx index a65951c48..abc4f39ab 100644 --- a/src/components/@shared/Publisher/index.tsx +++ b/src/components/@shared/Publisher/index.tsx @@ -21,13 +21,13 @@ export default function Publisher({ minimal?: boolean className?: string }): ReactElement { - const { accountId } = useWeb3() + // const { accountId } = useWeb3() const isMounted = useIsMounted() const [profile, setProfile] = useState() const [name, setName] = useState(accountTruncate(account)) const [accountEns, setAccountEns] = useState() - const showAdd = account === accountId && !profile + // const showAdd = account === accountId && !profile useEffect(() => { if (!account) return @@ -70,7 +70,7 @@ export default function Publisher({ {name} - {showAdd && } + {/* {showAdd && } */} )}
diff --git a/src/components/@shared/atoms/Tabs.module.css b/src/components/@shared/atoms/Tabs.module.css index f138f9458..21a160e7b 100644 --- a/src/components/@shared/atoms/Tabs.module.css +++ b/src/components/@shared/atoms/Tabs.module.css @@ -34,6 +34,10 @@ border-color: var(--font-color-heading); } +.tab[aria-disabled='true'] { + cursor: not-allowed; +} + .tabContent { padding: calc(var(--spacer) / 2); } diff --git a/src/components/@shared/atoms/Tabs.tsx b/src/components/@shared/atoms/Tabs.tsx index 2d6e4d6a5..7e7c01606 100644 --- a/src/components/@shared/atoms/Tabs.tsx +++ b/src/components/@shared/atoms/Tabs.tsx @@ -2,9 +2,10 @@ import React, { ReactElement, ReactNode } from 'react' import { Tab, Tabs as ReactTabs, TabList, TabPanel } from 'react-tabs' import styles from './Tabs.module.css' -interface TabsItem { +export interface TabsItem { title: string content: ReactNode + disabled?: boolean } export default function Tabs({ @@ -29,6 +30,7 @@ export default function Tabs({ className={styles.tab} key={item.title} onClick={handleTabChange ? () => handleTabChange(item.title) : null} + disabled={item.disabled} > {item.title} diff --git a/src/components/Asset/AssetActions/Compute/AlgorithmDatasetsListForCompute.tsx b/src/components/Asset/AssetActions/Compute/AlgorithmDatasetsListForCompute.tsx index 666114543..f9735ef96 100644 --- a/src/components/Asset/AssetActions/Compute/AlgorithmDatasetsListForCompute.tsx +++ b/src/components/Asset/AssetActions/Compute/AlgorithmDatasetsListForCompute.tsx @@ -3,38 +3,39 @@ import styles from './AlgorithmDatasetsListForCompute.module.css' import { getAlgorithmDatasetsForCompute } from '@utils/aquarius' import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection' import AssetComputeList from '@shared/AssetList/AssetComputeList' -import { useAsset } from '@context/Asset' import { useCancelToken } from '@hooks/useCancelToken' import { getServiceByName } from '@utils/ddo' export default function AlgorithmDatasetsListForCompute({ - algorithmDid, - dataset + ddo, + algorithmDid }: { + ddo: Asset algorithmDid: string - dataset: Asset }): ReactElement { - const { ddo } = useAsset() const [datasetsForCompute, setDatasetsForCompute] = useState() const newCancelToken = useCancelToken() + useEffect(() => { + if (!ddo) return + async function getDatasetsAllowedForCompute() { - const isCompute = Boolean(getServiceByName(dataset, 'compute')) + const isCompute = Boolean(getServiceByName(ddo, 'compute')) const datasetComputeService = getServiceByName( - dataset, + ddo, isCompute ? 'compute' : 'access' ) const datasets = await getAlgorithmDatasetsForCompute( algorithmDid, datasetComputeService?.serviceEndpoint, - dataset?.chainId, + ddo?.chainId, newCancelToken() ) setDatasetsForCompute(datasets) } ddo.metadata.type === 'algorithm' && getDatasetsAllowedForCompute() - }, [ddo.metadata.type]) + }, [ddo?.metadata?.type]) return (
diff --git a/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx b/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx index 219f18a24..fa03c013d 100644 --- a/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx +++ b/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx @@ -160,7 +160,7 @@ export default function FormStartCompute({ } hasPreviousOrder={hasPreviousOrder} hasDatatoken={hasDatatoken} - dtSymbol={ddo.dataTokenInfo.symbol} + dtSymbol={ddo?.dataTokenInfo?.symbol} dtBalance={dtBalance} datasetLowPoolLiquidity={datasetLowPoolLiquidity} assetTimeout={assetTimeout} diff --git a/src/components/Asset/AssetActions/Compute/index.tsx b/src/components/Asset/AssetActions/Compute/index.tsx index bc4b89b75..8298125cc 100644 --- a/src/components/Asset/AssetActions/Compute/index.tsx +++ b/src/components/Asset/AssetActions/Compute/index.tsx @@ -37,12 +37,16 @@ import { SortTermOptions } from '../../../../@types/aquarius/SearchQuery' import { FileMetadata } from '@utils/provider' export default function Compute({ + ddo, + price, dtBalance, file, fileIsLoading, isConsumable, consumableFeedback }: { + ddo: Asset + price: BestPrice dtBalance: string file: FileMetadata fileIsLoading?: boolean @@ -51,8 +55,7 @@ export default function Compute({ }): ReactElement { const { appConfig } = useSiteMetadata() const { accountId } = useWeb3() - const { ocean, account } = useOcean() - const { price, ddo } = useAsset() + const { ocean } = useOcean() const { buyDT, pricingError, pricingStepText } = usePricing() const [isJobStarting, setIsJobStarting] = useState(false) const [error, setError] = useState() @@ -399,10 +402,7 @@ export default function Compute({ text="This algorithm has been set to private by the publisher and can't be downloaded. You can run it against any allowed data sets though!" state="info" /> - + ) : ( )} - {accountId && ( + {accountId && price?.datatoken && ( diff --git a/src/components/Asset/AssetActions/Consume.tsx b/src/components/Asset/AssetActions/Consume.tsx index d6acf3e80..416db0e87 100644 --- a/src/components/Asset/AssetActions/Consume.tsx +++ b/src/components/Asset/AssetActions/Consume.tsx @@ -8,7 +8,6 @@ import { gql } from 'urql' import { fetchData, getQueryContext } from '@utils/subgraph' import { OrdersData } from '../../../@types/apollo/OrdersData' import BigNumber from 'bignumber.js' -import { useOcean } from '@context/Ocean' import { useWeb3 } from '@context/Web3' import { usePricing } from '@hooks/usePricing' import { useConsume } from '@hooks/useConsume' @@ -35,6 +34,7 @@ const previousOrderQuery = gql` export default function Consume({ ddo, + price, file, isBalanceSufficient, dtBalance, @@ -43,6 +43,7 @@ export default function Consume({ consumableFeedback }: { ddo: Asset + price: BestPrice file: FileMetadata isBalanceSufficient: boolean dtBalance: string @@ -51,11 +52,10 @@ export default function Consume({ consumableFeedback?: string }): ReactElement { const { accountId } = useWeb3() - const { ocean } = useOcean() const { appConfig } = useSiteMetadata() const [hasPreviousOrder, setHasPreviousOrder] = useState(false) const [previousOrderId, setPreviousOrderId] = useState() - const { isInPurgatory, price, isAssetNetwork } = useAsset() + const { isInPurgatory, isAssetNetwork } = useAsset() const { buyDT, pricingStepText, pricingError, pricingIsLoading } = usePricing() const { consumeStepText, consume, consumeError, isLoading } = useConsume() @@ -105,6 +105,8 @@ export default function Consume({ }, [data, assetTimeout, accountId, isAssetNetwork]) useEffect(() => { + if (!ddo) return + const { timeout } = ddo.services[0] setAssetTimeout(`${timeout}`) }, [ddo]) @@ -125,8 +127,7 @@ export default function Consume({ if (!accountId) return setIsDisabled( !isConsumable || - ((!ocean || - !isBalanceSufficient || + ((!isBalanceSufficient || !isAssetNetwork || typeof consumeStepText !== 'undefined' || pricingIsLoading || @@ -135,7 +136,6 @@ export default function Consume({ !hasDatatoken) ) }, [ - ocean, hasPreviousOrder, isBalanceSufficient, isAssetNetwork, @@ -182,7 +182,7 @@ export default function Consume({ datasetLowPoolLiquidity={!isConsumablePrice} onClick={handleConsume} assetTimeout={secondsToString(parseInt(assetTimeout))} - assetType={ddo?.metadata.type} + assetType={ddo?.metadata?.type} stepText={consumeStepText || pricingStepText} isLoading={pricingIsLoading || isLoading} priceType={price?.type} @@ -203,8 +203,8 @@ export default function Consume({ {!isInPurgatory && }
- {ddo.metadata.type === 'algorithm' && ( - + {ddo?.metadata?.type === 'algorithm' && ( + )} ) diff --git a/src/components/Asset/AssetActions/index.tsx b/src/components/Asset/AssetActions/index.tsx index a3ffd237f..86e748798 100644 --- a/src/components/Asset/AssetActions/index.tsx +++ b/src/components/Asset/AssetActions/index.tsx @@ -2,7 +2,7 @@ import React, { ReactElement, useState, useEffect } from 'react' import Compute from './Compute' import Consume from './Consume' import { Logger } from '@oceanprotocol/lib' -import Tabs from '@shared/atoms/Tabs' +import Tabs, { TabsItem } from '@shared/atoms/Tabs' import { compareAsBN } from '@utils/numbers' import Pool from './Pool' import Trade from './Trade' @@ -15,11 +15,20 @@ import { getOceanConfig } from '@utils/ocean' import { useCancelToken } from '@hooks/useCancelToken' import { useIsMounted } from '@hooks/useIsMounted' import styles from './index.module.css' +import { useFormikContext } from 'formik' +import { FormPublishData } from 'src/components/Publish/_types' -export default function AssetActions(): ReactElement { +export default function AssetActions({ + ddo, + price +}: { + ddo: Asset + price: BestPrice +}): ReactElement { const { accountId, balance } = useWeb3() const { ocean, account } = useOcean() - const { price, ddo, isAssetNetwork } = useAsset() + const { isAssetNetwork } = useAsset() + const { values } = useFormikContext() const [isBalanceSufficient, setIsBalanceSufficient] = useState() const [dtBalance, setDtBalance] = useState() @@ -51,25 +60,30 @@ export default function AssetActions(): ReactElement { // }, [accountId, isAssetNetwork, ddo, ocean]) useEffect(() => { - const oceanConfig = getOceanConfig(ddo.chainId) + const oceanConfig = getOceanConfig(ddo?.chainId) if (!oceanConfig) return async function initFileInfo() { setFileIsLoading(true) + + const asset = values?.services?.[0].files?.[0].url || ddo.id + const providerUrl = + values?.services[0].providerUrl || oceanConfig.providerUri + try { const fileInfoResponse = await getFileInfo( - ddo.id, + asset, oceanConfig.providerUri, newCancelToken() ) fileInfoResponse && setFileMetadata(fileInfoResponse[0]) - isMounted() && setFileIsLoading(false) + setFileIsLoading(false) } catch (error) { Logger.error(error.message) } } initFileInfo() - }, [ddo, isMounted, newCancelToken]) + }, [ddo, isMounted, newCancelToken, values?.services]) // Get and set user DT balance useEffect(() => { @@ -104,6 +118,8 @@ export default function AssetActions(): ReactElement { const UseContent = isCompute ? ( ) - const tabs = [ + const tabs: TabsItem[] = [ { title: 'Use', content: UseContent } ] - price?.type === 'pool' && + price?.type === 'dynamic' && tabs.push( { title: 'Pool', - content: + content: , + disabled: !price.datatoken }, { title: 'Trade', - content: + content: , + disabled: !price.datatoken } ) diff --git a/src/components/Asset/AssetContent/EditHistory.tsx b/src/components/Asset/AssetContent/EditHistory.tsx index feebe003a..d857e858e 100644 --- a/src/components/Asset/AssetContent/EditHistory.tsx +++ b/src/components/Asset/AssetContent/EditHistory.tsx @@ -68,14 +68,14 @@ export default function EditHistory(): ReactElement {
    {receipts?.map((receipt) => (
  • - + edited
  • ))}
  • - - published
diff --git a/src/components/Asset/AssetContent/MetaFull.tsx b/src/components/Asset/AssetContent/MetaFull.tsx index 77983e719..359ce2a94 100644 --- a/src/components/Asset/AssetContent/MetaFull.tsx +++ b/src/components/Asset/AssetContent/MetaFull.tsx @@ -4,27 +4,28 @@ import styles from './MetaFull.module.css' import Publisher from '@shared/Publisher' import { useAsset } from '@context/Asset' -export default function MetaFull(): ReactElement { - const { ddo, isInPurgatory } = useAsset() - const { type, author, algorithm } = ddo?.metadata +export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement { + const { isInPurgatory } = useAsset() function DockerImage() { - const { image, tag } = algorithm?.container + const { image, tag } = ddo?.metadata?.algorithm?.container return {`${image}:${tag}`} } - return ( + return ddo ? (
- {!isInPurgatory && } + {!isInPurgatory && ( + + )} } /> - {type === 'algorithm' && algorithm && ( + {ddo?.metadata?.type === 'algorithm' && ddo?.metadata?.algorithm && ( } /> )} {ddo?.id}} />
- ) + ) : null } diff --git a/src/components/Asset/AssetContent/MetaMain.tsx b/src/components/Asset/AssetContent/MetaMain.tsx index 4f2cbab66..f9093790f 100644 --- a/src/components/Asset/AssetContent/MetaMain.tsx +++ b/src/components/Asset/AssetContent/MetaMain.tsx @@ -9,8 +9,8 @@ import AssetType from '@shared/AssetType' import styles from './MetaMain.module.css' import { getServiceByName } from '@utils/ddo' -export default function MetaMain(): ReactElement { - const { ddo, owner, isAssetNetwork } = useAsset() +export default function MetaMain({ ddo }: { ddo: Asset }): ReactElement { + const { isAssetNetwork } = useAsset() const { web3ProviderInfo } = useWeb3() const isCompute = Boolean(getServiceByName(ddo, 'compute')) @@ -18,6 +18,9 @@ export default function MetaMain(): ReactElement { const blockscoutNetworks = [1287, 2021000, 2021001, 44787, 246, 1285] const isBlockscoutExplorer = blockscoutNetworks.includes(ddo?.chainId) + const dataTokenName = ddo?.dataTokenInfo?.name + const dataTokenSymbol = ddo?.dataTokenInfo?.symbol + return (