market/src/components/Asset/AssetActions/Download.tsx

248 lines
7.5 KiB
TypeScript
Raw Normal View History

import React, { ReactElement, useEffect, useState } from 'react'
import FileIcon from '@shared/FileIcon'
import Price from '@shared/Price'
import { useAsset } from '@context/Asset'
import { useWeb3 } from '@context/Web3'
import ButtonBuy from './ButtonBuy'
import { secondsToString } from '@utils/ddo'
import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute'
import styles from './Download.module.css'
import { FileInfo, LoggerInstance, ZERO_ADDRESS } from '@oceanprotocol/lib'
import { order } from '@utils/order'
import { downloadFile } from '@utils/provider'
import { getOrderFeedback } from '@utils/feedback'
import { getOrderPriceAndFees } from '@utils/accessDetailsAndPricing'
import { toast } from 'react-toastify'
import { useIsMounted } from '@hooks/useIsMounted'
Various fixes in the pool component (#1327) * remove legacy check to prevent rug pull Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * add expected output to remove Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove console.logs Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix max calculations Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactors Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * temp fixes for build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * local calc for pice and liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove var Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix profile liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * global context, opc fee Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * comment Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactor global context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove nesting from market context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix undefined appConfig Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * direct import of appConfig & siteContent * this never changes on run time, so we should never have to wait for it and have it in js bundle at all times * in utility methods, import directly * for components, import directly in MarketMetadata context and pass through * remove screen CSS fixes * put back auto-fetching indicator, move manual refresh action behind debug Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
2022-04-22 02:38:35 +02:00
import { useMarketMetadata } from '@context/MarketMetadata'
2022-08-02 11:53:22 +02:00
import Alert from '@shared/atoms/Alert'
import Loader from '@shared/atoms/Loader'
export default function Download({
asset,
file,
isBalanceSufficient,
dtBalance,
fileIsLoading,
consumableFeedback
}: {
asset: AssetExtended
file: FileInfo
isBalanceSufficient: boolean
dtBalance: string
fileIsLoading?: boolean
consumableFeedback?: string
}): ReactElement {
const { accountId, web3, isSupportedOceanNetwork } = useWeb3()
Various fixes in the pool component (#1327) * remove legacy check to prevent rug pull Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * add expected output to remove Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove console.logs Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix max calculations Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactors Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * temp fixes for build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * local calc for pice and liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove var Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix profile liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * global context, opc fee Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * comment Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactor global context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove nesting from market context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix undefined appConfig Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * direct import of appConfig & siteContent * this never changes on run time, so we should never have to wait for it and have it in js bundle at all times * in utility methods, import directly * for components, import directly in MarketMetadata context and pass through * remove screen CSS fixes * put back auto-fetching indicator, move manual refresh action behind debug Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
2022-04-22 02:38:35 +02:00
const { getOpcFeeForToken } = useMarketMetadata()
const { isInPurgatory, isAssetNetwork } = useAsset()
const isMounted = useIsMounted()
const [isDisabled, setIsDisabled] = useState(true)
const [hasDatatoken, setHasDatatoken] = useState(false)
const [statusText, setStatusText] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [isPriceLoading, setIsPriceLoading] = useState(false)
const [isOwned, setIsOwned] = useState(false)
const [validOrderTx, setValidOrderTx] = useState('')
const [isOrderDisabled, setIsOrderDisabled] = useState(false)
const [orderPriceAndFees, setOrderPriceAndFees] =
useState<OrderPriceAndFees>()
const [retry, setRetry] = useState<boolean>(false)
2022-08-02 11:53:22 +02:00
const isUnsupportedPricing = asset?.accessDetails?.type === 'NOT_SUPPORTED'
useEffect(() => {
Number(asset?.nft.state) === 4 && setIsOrderDisabled(true)
}, [asset?.nft.state])
useEffect(() => {
2022-08-02 11:53:22 +02:00
if (!asset?.accessDetails || isUnsupportedPricing) return
2022-08-02 11:53:22 +02:00
asset.accessDetails.isOwned && setIsOwned(asset?.accessDetails?.isOwned)
asset.accessDetails.validOrderTx &&
2022-05-19 18:48:13 +02:00
setValidOrderTx(asset?.accessDetails?.validOrderTx)
// get full price and fees
async function init() {
if (
2022-08-02 11:53:22 +02:00
asset.accessDetails.addressOrId === ZERO_ADDRESS ||
asset.accessDetails.type === 'free' ||
isLoading
)
return
Various fixes in the pool component (#1327) * remove legacy check to prevent rug pull Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * add expected output to remove Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove console.logs Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix max calculations Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactors Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * temp fixes for build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * local calc for pice and liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove var Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix profile liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * global context, opc fee Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * comment Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactor global context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove nesting from market context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix undefined appConfig Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * direct import of appConfig & siteContent * this never changes on run time, so we should never have to wait for it and have it in js bundle at all times * in utility methods, import directly * for components, import directly in MarketMetadata context and pass through * remove screen CSS fixes * put back auto-fetching indicator, move manual refresh action behind debug Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
2022-04-22 02:38:35 +02:00
!orderPriceAndFees && setIsPriceLoading(true)
Various fixes in the pool component (#1327) * remove legacy check to prevent rug pull Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove old prop Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * add expected output to remove Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove console.logs Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix max calculations Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactors Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * temp fixes for build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * local calc for pice and liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove var Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix profile liquidity Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * global context, opc fee Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * comment Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * various fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * refactor global context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * remove nesting from market context Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix build Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix undefined appConfig Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * direct import of appConfig & siteContent * this never changes on run time, so we should never have to wait for it and have it in js bundle at all times * in utility methods, import directly * for components, import directly in MarketMetadata context and pass through * remove screen CSS fixes * put back auto-fetching indicator, move manual refresh action behind debug Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
2022-04-22 02:38:35 +02:00
2022-08-02 11:53:22 +02:00
const _orderPriceAndFees = await getOrderPriceAndFees(asset, ZERO_ADDRESS)
setOrderPriceAndFees(_orderPriceAndFees)
!orderPriceAndFees && setIsPriceLoading(false)
}
init()
2022-08-02 11:53:22 +02:00
/**
* we listen to the assets' changes to get the most updated price
* based on the asset and the poolData's information.
* Not adding isLoading and getOpcFeeForToken because we set these here. It is a compromise
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
2022-08-02 11:53:22 +02:00
}, [asset, accountId, getOpcFeeForToken, isUnsupportedPricing])
useEffect(() => {
setHasDatatoken(Number(dtBalance) >= 1)
}, [dtBalance])
useEffect(() => {
2022-08-02 11:53:22 +02:00
if (
(asset?.accessDetails?.type === 'fixed' && !orderPriceAndFees) ||
2022-08-02 11:53:22 +02:00
!isMounted ||
!accountId ||
!asset?.accessDetails ||
isUnsupportedPricing
)
return
/**
* disabled in these cases:
* - if the asset is not purchasable
* - if the user is on the wrong network
* - if user balance is not sufficient
* - if user has no datatokens
*/
const isDisabled =
!asset?.accessDetails.isPurchasable ||
!isAssetNetwork ||
((!isBalanceSufficient || !isAssetNetwork) && !isOwned && !hasDatatoken)
setIsDisabled(isDisabled)
}, [
isMounted,
asset?.accessDetails,
isBalanceSufficient,
isAssetNetwork,
hasDatatoken,
accountId,
2022-08-02 11:53:22 +02:00
isOwned,
isUnsupportedPricing,
orderPriceAndFees
])
async function handleOrderOrDownload() {
setIsLoading(true)
try {
if (isOwned) {
setStatusText(
getOrderFeedback(
2022-08-02 11:53:22 +02:00
asset.accessDetails.baseToken?.symbol,
asset.accessDetails.datatoken?.symbol
)[3]
)
await downloadFile(web3, asset, accountId, validOrderTx)
} else {
setStatusText(
getOrderFeedback(
asset.accessDetails.baseToken?.symbol,
asset.accessDetails.datatoken?.symbol
2022-08-02 11:53:22 +02:00
)[asset.accessDetails.type === 'fixed' ? 2 : 1]
)
const orderTx = await order(web3, asset, orderPriceAndFees, accountId)
if (!orderTx) {
throw new Error()
}
setIsOwned(true)
setValidOrderTx(orderTx.transactionHash)
}
} catch (error) {
LoggerInstance.error(error)
setRetry(true)
const message = isOwned
? 'Failed to download file!'
: 'An error occurred, please retry. Check console for more information.'
toast.error(message)
}
setIsLoading(false)
}
const PurchaseButton = () => (
<ButtonBuy
action="download"
disabled={isDisabled}
hasPreviousOrder={isOwned}
hasDatatoken={hasDatatoken}
Dynamic token list support for publishing (#1516) * feat: add approved tokens list query to subgraph * feat: add base token selector * feat: add placeholder tooltip message for base token * feat: use user selected base token for publish * fix: publish constants * feat: update base token query to include digits and symbol * feat: display correct token name and symbol in publish pricing tab * fix: publish preview token name * fix: query type * feat: add balance fetch for all approved tokens * fix: balance check for dynamic price with alternative base tokens * feat: update balance to show baseToken instead of ocean * fix: default baseToken in publish form * feat: update text content for pricing publish step * chore: update ocean.js * add decimals to token Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix dt decimals Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * update ocean.js Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * fix: show correct basetoken symbol under button buy * refactor: move baseToken selector to input label [WIP] * refactor: preserve baseToken value value when switching tabs * remove basetoken tooltip from content json * fix: price props * refactor: remove BaseToken component * fix: baseToken name on first load * fix: baseToken display name in dynamic price * fix: conversion tooltip text * fix: error box overlapping in Coin component * feat: add token logo component * feat: add basetoken logo to asset actions pool * fix: token images size * fix: add default appproved token list when disconnected or chainId not supported * fix: datatoken logo on asset details meta * refactor: balance fetch + move approved base tokens list in web3 provider * feat: update all datatokens to display ocean logo in violet * fix: show correct logos on polygon * fix wallet, remove dynamic * fix build * fix: reset baseToken on chainId change during publish * fix: price tabs selection indicator * feat: set the ocean token as default in pricing * add baseToken * fix price * remove firstPrice * cleanup, more affordance for token dropdown Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> Co-authored-by: Matthias Kretschmann <m@kretschmann.io>
2022-08-03 14:48:57 +02:00
btSymbol={asset?.accessDetails?.baseToken?.symbol}
dtSymbol={asset?.datatokens[0]?.symbol}
dtBalance={dtBalance}
onClick={handleOrderOrDownload}
assetTimeout={secondsToString(asset?.services?.[0]?.timeout)}
assetType={asset?.metadata?.type}
stepText={statusText}
isLoading={isLoading}
priceType={asset.accessDetails?.type}
isConsumable={asset.accessDetails?.isPurchasable}
isBalanceSufficient={isBalanceSufficient}
consumableFeedback={consumableFeedback}
retry={retry}
isSupportedOceanNetwork={isSupportedOceanNetwork}
/>
)
2022-08-02 11:53:22 +02:00
const AssetAction = ({ asset }: { asset: AssetExtended }) => {
return (
<div>
{isOrderDisabled ? (
2022-08-02 11:53:22 +02:00
<Alert
className={styles.fieldWarning}
state="info"
text={`The publisher temporarily disabled ordering for this asset`}
2022-08-02 11:53:22 +02:00
/>
) : (
<>
{isUnsupportedPricing || !asset.services.length ? (
<Alert
className={styles.fieldWarning}
state="info"
text={`No pricing schema available for this asset.`}
/>
) : (
<>
{isPriceLoading ? (
<Loader message="Calculating full price (including fees)" />
) : (
<Price
accessDetails={asset.accessDetails}
orderPriceAndFees={orderPriceAndFees}
conversion
size="large"
/>
)}
{!isInPurgatory && <PurchaseButton />}
</>
)}
2022-08-02 11:53:22 +02:00
</>
)}
</div>
)
}
return (
<aside className={styles.consume}>
<div className={styles.info}>
<div className={styles.filewrapper}>
2022-08-02 11:53:22 +02:00
<FileIcon file={file} isLoading={fileIsLoading} small />
</div>
2022-08-02 11:53:22 +02:00
<AssetAction asset={asset} />
</div>
{asset?.metadata?.type === 'algorithm' && (
<AlgorithmDatasetsListForCompute
algorithmDid={asset.id}
asset={asset}
/>
)}
</aside>
)
}