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, FixedRateExchange } 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 { getCollectTokensFeedback, getOrderFeedback } from '@utils/feedback' import { getOrderPriceAndFees } from '@utils/accessDetailsAndPricing' import { OrderPriceAndFees } from 'src/@types/Price' import { toast } from 'react-toastify' import { gql, OperationResult } from 'urql' import { fetchData, getQueryContext } from '@utils/subgraph' import { getOceanConfig } from '@utils/ocean' import { FixedRateExchanges } from 'src/@types/subgraph/FixedRateExchanges' const FixedRateExchangesQuery = gql` query FixedRateExchanges($user: String, $exchangeId: String) { fixedRateExchanges(where: { owner: $user, exchangeId: $exchangeId }) { id owner { id } exchangeId baseTokenBalance } } ` 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 { isInPurgatory, isAssetNetwork } = useAsset() 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 [isCollectLoading, setIsCollectLoading] = useState(false) const [baseTokenBalance, setBaseTokenBalance] = useState(0) const [collectStatusText, setCollectStatusText] = 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) return setIsLoading(true) setStatusText('Calculating price including fees.') const orderPriceAndFees = await getOrderPriceAndFees(asset, ZERO_ADDRESS) setOrderPriceAndFees(orderPriceAndFees) setIsLoading(false) } init() }, [asset, accountId]) useEffect(() => { setHasDatatoken(Number(dtBalance) >= 1) }, [dtBalance]) useEffect(() => { if (!accountId || !asset?.accessDetails) return setIsDisabled( !asset?.accessDetails.isPurchasable || ((!isBalanceSufficient || !isAssetNetwork) && !isOwned && !hasDatatoken) ) }, [ asset?.accessDetails, isBalanceSufficient, isAssetNetwork, hasDatatoken, accountId, isOwned ]) useEffect(() => { if (!accountId || asset.nft.owner !== accountId) return const queryContext = getQueryContext(Number(asset.chainId)) async function getBaseTokenBalance() { const variables = { user: accountId.toLowerCase(), exchangeId: asset?.accessDetails?.addressOrId } const result: OperationResult = await fetchData( FixedRateExchangesQuery, variables, queryContext ) result?.data?.fixedRateExchanges[0]?.baseTokenBalance ? setBaseTokenBalance( parseInt(result?.data?.fixedRateExchanges[0]?.baseTokenBalance) ) : setBaseTokenBalance(0) } getBaseTokenBalance() }, [accountId, asset?.accessDetails?.addressOrId, asset.chainId, asset.nft]) async function handleOrderOrDownload() { setIsLoading(true) if (isOwned) { setStatusText( getOrderFeedback( asset.accessDetails?.baseToken?.symbol, asset.accessDetails?.datatoken?.symbol )[3] ) await downloadFile(web3, asset, accountId, validOrderTx) } else { try { 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) { toast.error('Failed to buy datatoken from pool!') setIsLoading(false) return } } 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) { toast.error('Failed to buy datatoken from pool!') setIsLoading(false) return } setIsOwned(true) setValidOrderTx(orderTx.transactionHash) } catch (ex) { LoggerInstance.log(ex.message) setIsLoading(false) } } setIsLoading(false) } async function handleCollectTokens() { setIsCollectLoading(true) const config = getOceanConfig(asset?.chainId) const fixed = new FixedRateExchange(web3, config.fixedRateExchangeAddress) try { setCollectStatusText( getCollectTokensFeedback( asset.accessDetails.baseToken?.symbol, baseTokenBalance.toString() ) ) const tx = await fixed.collectBT( accountId, asset?.accessDetails?.addressOrId ) if (!tx) { setIsCollectLoading(false) return } setBaseTokenBalance(0) return tx } catch (error) { LoggerInstance.log(error.message) setIsCollectLoading(false) } finally { setIsCollectLoading(false) } } const PurchaseButton = () => ( ) const CollectTokensButton = () => ( ) return ( ) }