mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
* WIP * UI changes * get and display datasets on both compute and consume * new component for datasets that algorithm can run compute job on * AssetSelection className refactor * added internal link to AssetSelection * show loading page when changing asset * Component and asset title UI update * created new component for dataset list * removed unnecessary changes * updated link margin * prettier fix * merge fix * another fix Co-authored-by: Norbi <katunanorbert@gmai.com> Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
181 lines
5.2 KiB
TypeScript
181 lines
5.2 KiB
TypeScript
import React, { ReactElement, useEffect, useState } from 'react'
|
|
import { toast } from 'react-toastify'
|
|
import { File as FileMetadata, DDO } from '@oceanprotocol/lib'
|
|
import File from '../../atoms/File'
|
|
import Price from '../../atoms/Price'
|
|
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
|
import styles from './Consume.module.css'
|
|
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
|
import { useAsset } from '../../../providers/Asset'
|
|
import { secondsToString } from '../../../utils/metadata'
|
|
import { gql, useQuery } from '@apollo/client'
|
|
import { OrdersData } from '../../../@types/apollo/OrdersData'
|
|
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'
|
|
import ButtonBuy from '../../atoms/ButtonBuy'
|
|
import AlgorithmDatasetsListForCompute from '../AssetContent/AlgorithmDatasetsListForCompute'
|
|
|
|
const previousOrderQuery = gql`
|
|
query PreviousOrder($id: String!, $account: String!) {
|
|
tokenOrders(
|
|
first: 1
|
|
where: { datatokenId: $id, payer: $account }
|
|
orderBy: timestamp
|
|
orderDirection: desc
|
|
) {
|
|
timestamp
|
|
tx
|
|
}
|
|
}
|
|
`
|
|
|
|
export default function Consume({
|
|
ddo,
|
|
file,
|
|
isBalanceSufficient,
|
|
dtBalance,
|
|
fileIsLoading
|
|
}: {
|
|
ddo: DDO
|
|
file: FileMetadata
|
|
isBalanceSufficient: boolean
|
|
dtBalance: string
|
|
fileIsLoading?: boolean
|
|
}): ReactElement {
|
|
const { accountId } = useWeb3()
|
|
const { ocean } = useOcean()
|
|
const { appConfig } = useSiteMetadata()
|
|
const [hasPreviousOrder, setHasPreviousOrder] = useState(false)
|
|
const [previousOrderId, setPreviousOrderId] = useState<string>()
|
|
const { isInPurgatory, price, type } = useAsset()
|
|
const { buyDT, pricingStepText, pricingError, pricingIsLoading } =
|
|
usePricing()
|
|
const { consumeStepText, consume, consumeError } = useConsume()
|
|
const [isDisabled, setIsDisabled] = useState(true)
|
|
const [hasDatatoken, setHasDatatoken] = useState(false)
|
|
const [isConsumable, setIsConsumable] = useState(true)
|
|
const [assetTimeout, setAssetTimeout] = useState('')
|
|
|
|
const { data } = useQuery<OrdersData>(previousOrderQuery, {
|
|
variables: {
|
|
id: ddo.dataToken?.toLowerCase(),
|
|
account: accountId?.toLowerCase()
|
|
},
|
|
pollInterval: 5000
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (!data || !assetTimeout || data.tokenOrders.length === 0) return
|
|
|
|
const lastOrder = data.tokenOrders[0]
|
|
|
|
if (assetTimeout === 'Forever') {
|
|
setPreviousOrderId(lastOrder.tx)
|
|
setHasPreviousOrder(true)
|
|
} else {
|
|
const expiry = new BigNumber(lastOrder.timestamp).plus(assetTimeout)
|
|
const unixTime = new BigNumber(Math.floor(Date.now() / 1000))
|
|
if (unixTime.isLessThan(expiry)) {
|
|
setPreviousOrderId(lastOrder.tx)
|
|
setHasPreviousOrder(true)
|
|
} else {
|
|
setHasPreviousOrder(false)
|
|
}
|
|
}
|
|
}, [data, assetTimeout])
|
|
|
|
useEffect(() => {
|
|
const { timeout } = ddo.findServiceByType('access').attributes.main
|
|
setAssetTimeout(secondsToString(timeout))
|
|
}, [ddo])
|
|
|
|
useEffect(() => {
|
|
if (!price) return
|
|
|
|
setIsConsumable(
|
|
price.isConsumable !== undefined ? price.isConsumable === 'true' : true
|
|
)
|
|
}, [price])
|
|
|
|
useEffect(() => {
|
|
setHasDatatoken(Number(dtBalance) >= 1)
|
|
}, [dtBalance])
|
|
|
|
useEffect(() => {
|
|
setIsDisabled(
|
|
(!ocean ||
|
|
!isBalanceSufficient ||
|
|
typeof consumeStepText !== 'undefined' ||
|
|
pricingIsLoading ||
|
|
!isConsumable) &&
|
|
!hasPreviousOrder &&
|
|
!hasDatatoken
|
|
)
|
|
}, [
|
|
ocean,
|
|
hasPreviousOrder,
|
|
isBalanceSufficient,
|
|
consumeStepText,
|
|
pricingIsLoading,
|
|
isConsumable,
|
|
hasDatatoken
|
|
])
|
|
|
|
async function handleConsume() {
|
|
!hasPreviousOrder && !hasDatatoken && (await buyDT('1', price, ddo))
|
|
await consume(
|
|
ddo.id,
|
|
ddo.dataToken,
|
|
'access',
|
|
appConfig.marketFeeAddress,
|
|
previousOrderId
|
|
)
|
|
setHasPreviousOrder(true)
|
|
}
|
|
|
|
// Output errors in UI
|
|
useEffect(() => {
|
|
consumeError && toast.error(consumeError)
|
|
pricingError && toast.error(pricingError)
|
|
}, [consumeError, pricingError])
|
|
|
|
const PurchaseButton = () => (
|
|
<ButtonBuy
|
|
action="download"
|
|
disabled={isDisabled}
|
|
hasPreviousOrder={hasPreviousOrder}
|
|
hasDatatoken={hasDatatoken}
|
|
dtSymbol={ddo.dataTokenInfo?.symbol}
|
|
dtBalance={dtBalance}
|
|
onClick={handleConsume}
|
|
assetTimeout={assetTimeout}
|
|
assetType={type}
|
|
stepText={consumeStepText || pricingStepText}
|
|
isLoading={pricingIsLoading}
|
|
/>
|
|
)
|
|
|
|
return (
|
|
<aside className={styles.consume}>
|
|
<div className={styles.info}>
|
|
<div className={styles.filewrapper}>
|
|
<File file={file} isLoading={fileIsLoading} />
|
|
</div>
|
|
<div className={styles.pricewrapper}>
|
|
<Price price={price} conversion />
|
|
{!isInPurgatory && <PurchaseButton />}
|
|
</div>
|
|
</div>
|
|
{type === 'algorithm' && (
|
|
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} />
|
|
)}
|
|
<footer className={styles.feedback}>
|
|
<Web3Feedback isBalanceSufficient={isBalanceSufficient} />
|
|
</footer>
|
|
</aside>
|
|
)
|
|
}
|