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 '@shared/ButtonBuy' import { secondsToString } from '@utils/ddo' import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute' import styles from './Download.module.css' import { FileMetadata, LoggerInstance, ZERO_ADDRESS } from '@oceanprotocol/lib' import { order } from '@utils/order' import { AssetExtended } from 'src/@types/AssetExtended' import { buyDtFromPool } from '@utils/pool' import { downloadFile } from '@utils/provider' import { getOrderFeedback } from '@utils/feedback' import { getOrderPriceAndFees } from '@utils/accessDetailsAndPricing' import { OrderPriceAndFees } from 'src/@types/Price' import { toast } from 'react-toastify' import { useIsMounted } from '@hooks/useIsMounted' import { usePool } from '@context/Pool' import { useMarketMetadata } from '@context/MarketMetadata' export default function Download({ asset, file, isBalanceSufficient, dtBalance, fileIsLoading, consumableFeedback }: { asset: AssetExtended file: FileMetadata isBalanceSufficient: boolean dtBalance: string fileIsLoading?: boolean consumableFeedback?: string }): ReactElement { const { accountId, web3 } = useWeb3() const { getOpcFeeForToken } = useMarketMetadata() const { isInPurgatory, isAssetNetwork } = useAsset() const { poolData } = usePool() const isMounted = useIsMounted() const [isDisabled, setIsDisabled] = useState(true) const [hasDatatoken, setHasDatatoken] = useState(false) const [statusText, setStatusText] = useState('') const [isLoading, setIsLoading] = useState(false) const [isOwned, setIsOwned] = useState(false) const [validOrderTx, setValidOrderTx] = useState('') const [orderPriceAndFees, setOrderPriceAndFees] = useState() useEffect(() => { if (!asset?.accessDetails) return setIsOwned(asset?.accessDetails?.isOwned) setValidOrderTx(asset?.accessDetails?.validOrderTx) // get full price and fees async function init() { if ( asset?.accessDetails?.addressOrId === ZERO_ADDRESS || asset?.accessDetails?.type === 'free' || (!poolData && asset?.accessDetails?.type === 'dynamic') ) return const params: CalcInGivenOutParams = { tokenInLiquidity: poolData?.baseTokenLiquidity, tokenOutLiquidity: poolData?.datatokenLiquidity, tokenOutAmount: '1', opcFee: getOpcFeeForToken( poolData?.baseToken?.address || asset?.accessDetails?.addressOrId, asset?.chainId ), lpSwapFee: poolData?.liquidityProviderSwapFee, publishMarketSwapFee: poolData?.publishMarketSwapFee, consumeMarketSwapFee: '0' } const orderPriceAndFees = await getOrderPriceAndFees( asset, ZERO_ADDRESS, params ) setOrderPriceAndFees(orderPriceAndFees) } init() /** * we listen to the assets' changes to get the most updated price * based on the asset and the poolData's information */ }, [asset, accountId, poolData, getOpcFeeForToken]) useEffect(() => { setHasDatatoken(Number(dtBalance) >= 1) }, [dtBalance]) useEffect(() => { if (!isMounted || !accountId || !asset?.accessDetails) 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, isOwned ]) async function handleOrderOrDownload() { setIsLoading(true) try { if (isOwned) { setStatusText( getOrderFeedback( asset.accessDetails?.baseToken?.symbol, asset.accessDetails?.datatoken?.symbol )[3] ) await downloadFile(web3, asset, accountId, validOrderTx) } else { if (!hasDatatoken && asset.accessDetails.type === 'dynamic') { setStatusText( getOrderFeedback( asset.accessDetails.baseToken?.symbol, asset.accessDetails.datatoken?.symbol )[0] ) const tx = await buyDtFromPool(asset.accessDetails, accountId, web3) if (!tx) { throw new Error() } } setStatusText( getOrderFeedback( asset.accessDetails.baseToken?.symbol, asset.accessDetails.datatoken?.symbol )[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) const message = isOwned ? 'Failed to download file!' : 'An error occurred. Check console for more information.' toast.error(message) } setIsLoading(false) } const PurchaseButton = () => ( ) return ( ) }