Merge pull request #1487 from oceanprotocol/fix/issue-1069-c2d-unsupported-networks

allow price calculation when users are on unsupported network / not connected
This commit is contained in:
EnzoVezzaro 2022-11-15 05:58:40 -04:00 committed by GitHub
commit 8225775828
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 117 additions and 59 deletions

View File

@ -2,23 +2,9 @@ import { gql, OperationResult, TypedDocumentNode, OperationContext } from 'urql'
import { LoggerInstance } from '@oceanprotocol/lib'
import { getUrqlClientInstance } from '@context/UrqlProvider'
import { getOceanConfig } from './ocean'
import { AssetPreviousOrder } from '../@types/subgraph/AssetPreviousOrder'
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
import { OpcFeesQuery as OpcFeesData } from '../@types/subgraph/OpcFeesQuery'
const PreviousOrderQuery = gql`
query AssetPreviousOrder($id: String!, $account: String!) {
orders(
first: 1
where: { datatoken: $id, payer: $account }
orderBy: createdTimestamp
orderDirection: desc
) {
createdTimestamp
tx
}
}
`
import appConfig from '../../app.config'
const UserTokenOrders = gql`
query OrdersData($user: String!) {
@ -76,6 +62,11 @@ export function getSubgraphUri(chainId: number): string {
export function getQueryContext(chainId: number): OperationContext {
try {
if (!appConfig.chainIdsSupported.includes(chainId))
throw Object.assign(
new Error('network not supported, query context cancelled')
)
const queryContext: OperationContext = {
url: `${getSubgraphUri(
Number(chainId)

View File

@ -2,6 +2,8 @@ import React, { FormEvent, ReactElement } from 'react'
import Button from '../../../@shared/atoms/Button'
import styles from './index.module.css'
import Loader from '../../../@shared/atoms/Loader'
import { useWeb3 } from '@context/Web3'
import Web3 from 'web3'
export interface ButtonBuyProps {
action: 'download' | 'compute'
@ -28,12 +30,11 @@ export interface ButtonBuyProps {
priceType?: string
algorithmPriceType?: string
isAlgorithmConsumable?: boolean
isSupportedOceanNetwork?: boolean
hasProviderFee?: boolean
retry?: boolean
}
// TODO: we need to take a look at these messages
function getConsumeHelpText(
btSymbol: string,
dtBalance: string,
@ -43,12 +44,14 @@ function getConsumeHelpText(
assetType: string,
isConsumable: boolean,
isBalanceSufficient: boolean,
consumableFeedback: string
consumableFeedback: string,
isSupportedOceanNetwork: boolean,
web3: Web3
) {
const text =
isConsumable === false
? consumableFeedback
: hasPreviousOrder
: hasPreviousOrder && web3 && isSupportedOceanNetwork
? `You bought this ${assetType} already allowing you to use it without paying again.`
: hasDatatoken
? `You own ${dtBalance} ${dtSymbol} allowing you to use this dataset by spending 1 ${dtSymbol}, but without paying ${btSymbol} again.`
@ -58,6 +61,35 @@ function getConsumeHelpText(
return text
}
function getAlgoHelpText(
dtSymbolSelectedComputeAsset: string,
dtBalanceSelectedComputeAsset: string,
isConsumable: boolean,
isAlgorithmConsumable: boolean,
hasPreviousOrderSelectedComputeAsset: boolean,
selectedComputeAssetType: string,
hasDatatokenSelectedComputeAsset: boolean,
isBalanceSufficient: boolean,
isSupportedOceanNetwork: boolean,
web3: Web3
) {
const text =
(!dtSymbolSelectedComputeAsset && !dtBalanceSelectedComputeAsset) ||
isConsumable === false ||
isAlgorithmConsumable === false
? ''
: hasPreviousOrderSelectedComputeAsset && web3 && isSupportedOceanNetwork
? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.`
: hasDatatokenSelectedComputeAsset
? `You own ${dtBalanceSelectedComputeAsset} ${dtSymbolSelectedComputeAsset} allowing you to use the selected ${selectedComputeAssetType} by spending 1 ${dtSymbolSelectedComputeAsset}, but without paying OCEAN again.`
: web3 && !isSupportedOceanNetwork
? `Connect to the correct network to interact with this asset.`
: isBalanceSufficient === false
? ''
: `Additionally, you will buy 1 ${dtSymbolSelectedComputeAsset} for the ${selectedComputeAssetType} and spend it back to its publisher and pool.`
return text
}
function getComputeAssetHelpText(
hasPreviousOrder: boolean,
hasDatatoken: boolean,
@ -74,6 +106,8 @@ function getComputeAssetHelpText(
dtBalanceSelectedComputeAsset?: string,
selectedComputeAssetType?: string,
isAlgorithmConsumable?: boolean,
isSupportedOceanNetwork?: boolean,
web3?: Web3,
hasProviderFee?: boolean
) {
const computeAssetHelpText = getConsumeHelpText(
@ -85,21 +119,24 @@ function getComputeAssetHelpText(
assetType,
isConsumable,
isBalanceSufficient,
consumableFeedback
consumableFeedback,
isSupportedOceanNetwork,
web3
)
const computeAlgoHelpText = getAlgoHelpText(
dtSymbolSelectedComputeAsset,
dtBalanceSelectedComputeAsset,
isConsumable,
isAlgorithmConsumable,
hasPreviousOrderSelectedComputeAsset,
selectedComputeAssetType,
hasDatatokenSelectedComputeAsset,
isBalanceSufficient,
isSupportedOceanNetwork,
web3
)
const computeAlgoHelpText =
(!dtSymbolSelectedComputeAsset && !dtBalanceSelectedComputeAsset) ||
isConsumable === false ||
isAlgorithmConsumable === false
? ''
: hasPreviousOrderSelectedComputeAsset
? `You already bought the selected ${selectedComputeAssetType}, allowing you to use it without paying again.`
: hasDatatokenSelectedComputeAsset
? `You own ${dtBalanceSelectedComputeAsset} ${dtSymbolSelectedComputeAsset} allowing you to use the selected ${selectedComputeAssetType} by spending 1 ${dtSymbolSelectedComputeAsset}, but without paying ${btSymbol} again.`
: isBalanceSufficient === false
? ''
: `Additionally, you will buy 1 ${dtSymbolSelectedComputeAsset} for the ${selectedComputeAssetType} and spend it back to its publisher.`
const providerFeeHelpText = hasProviderFee
? 'In order to start the job you also need to pay the fees for renting the c2d resources.'
: 'C2D resources required to start the job are available, no payment required for those fees.'
@ -133,8 +170,10 @@ export default function ButtonBuy({
algorithmPriceType,
isAlgorithmConsumable,
hasProviderFee,
retry
retry,
isSupportedOceanNetwork
}: ButtonBuyProps): ReactElement {
const { web3 } = useWeb3()
const buttonText = retry
? 'Retry'
: action === 'download'
@ -177,7 +216,9 @@ export default function ButtonBuy({
assetType,
isConsumable,
isBalanceSufficient,
consumableFeedback
consumableFeedback,
isSupportedOceanNetwork,
web3
)
: getComputeAssetHelpText(
hasPreviousOrder,
@ -195,6 +236,8 @@ export default function ButtonBuy({
dtBalanceSelectedComputeAsset,
selectedComputeAssetType,
isAlgorithmConsumable,
isSupportedOceanNetwork,
web3,
hasProviderFee
)}
</div>

View File

@ -9,7 +9,7 @@ import PriceOutput from './PriceOutput'
import { useAsset } from '@context/Asset'
import { useWeb3 } from '@context/Web3'
import content from '../../../../../content/pages/startComputeDataset.json'
import { Asset } from '@oceanprotocol/lib'
import { Asset, ZERO_ADDRESS } from '@oceanprotocol/lib'
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
import { useMarketMetadata } from '@context/MarketMetadata'
import Alert from '@shared/atoms/Alert'
@ -75,7 +75,7 @@ export default function FormStartCompute({
retry: boolean
}): ReactElement {
const { siteContent } = useMarketMetadata()
const { accountId, balance } = useWeb3()
const { accountId, balance, isSupportedOceanNetwork } = useWeb3()
const { isValid, values }: FormikContextType<{ algorithm: string }> =
useFormikContext()
const { asset, isAssetNetwork } = useAsset()
@ -98,7 +98,7 @@ export default function FormStartCompute({
}
useEffect(() => {
if (!values.algorithm || !accountId || !isConsumable) return
if (!values.algorithm || !isConsumable) return
async function fetchAlgorithmAssetExtended() {
const algorithmAsset = getAlgorithmAsset(values.algorithm)
@ -106,7 +106,7 @@ export default function FormStartCompute({
algorithmAsset.chainId,
algorithmAsset.services[0].datatokenAddress,
algorithmAsset.services[0].timeout,
accountId
accountId || ZERO_ADDRESS // if user is not connected, use ZERO_ADDRESS as accountId
)
const extendedAlgoAsset: AssetExtended = {
...algorithmAsset,
@ -198,15 +198,20 @@ export default function FormStartCompute({
}
setTotalPrices(totalPrices)
}, [
asset?.accessDetails,
selectedAlgorithmAsset?.accessDetails,
asset,
hasPreviousOrder,
hasDatatoken,
hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset,
datasetOrderPriceAndFees,
algoOrderPriceAndFees,
providerFeeAmount
providerFeeAmount,
isAssetNetwork,
selectedAlgorithmAsset?.accessDetails,
datasetOrderPrice,
algoOrderPrice,
algorithmSymbol,
datasetSymbol
])
useEffect(() => {
@ -216,12 +221,13 @@ export default function FormStartCompute({
setIsBalanceSufficient(false)
return
}
// if one comparison of baseTokenBalance and token price comparison is false then the state will be false
setIsBalanceSufficient(
isBalanceSufficient && compareAsBN(baseTokenBalance, `${price.value}`)
baseTokenBalance && compareAsBN(baseTokenBalance, `${price.value}`)
)
})
}, [balance, dtBalance, datasetSymbol, algorithmSymbol])
}, [balance, dtBalance, datasetSymbol, algorithmSymbol, totalPrices])
return (
<Form className={styles.form}>
@ -295,6 +301,7 @@ export default function FormStartCompute({
isAlgorithmConsumable={
selectedAlgorithmAsset?.accessDetails?.isPurchasable
}
isSupportedOceanNetwork={isSupportedOceanNetwork}
hasProviderFee={providerFeeAmount && providerFeeAmount !== '0'}
retry={retry}
/>

View File

@ -5,6 +5,7 @@ import Tooltip from '@shared/atoms/Tooltip'
import styles from './PriceOutput.module.css'
import { MAX_DECIMALS } from '@utils/constants'
import Decimal from 'decimal.js'
import { useWeb3 } from '@context/Web3'
interface PriceOutputProps {
hasPreviousOrder: boolean
@ -40,13 +41,21 @@ function Row({
sign?: string
type?: string
}) {
const { isSupportedOceanNetwork } = useWeb3()
return (
<div className={styles.priceRow}>
<div className={styles.sign}>{sign}</div>
<div className={styles.type}>{type}</div>
<div>
<PriceUnit
price={hasPreviousOrder || hasDatatoken ? 0 : Number(price)}
price={
!isSupportedOceanNetwork
? hasPreviousOrder || hasDatatoken
? 0
: Number(price)
: Number(price)
}
symbol={symbol}
size="small"
className={styles.price}

View File

@ -45,6 +45,7 @@ import { getComputeFeedback } from '@utils/feedback'
import { getDummyWeb3 } from '@utils/web3'
import { initializeProviderForCompute } from '@utils/provider'
import { useUserPreferences } from '@context/UserPreferences'
import { useAsset } from '@context/Asset'
const refreshInterval = 10000 // 10 sec.
export default function Compute({
@ -60,8 +61,10 @@ export default function Compute({
fileIsLoading?: boolean
consumableFeedback?: string
}): ReactElement {
const { accountId, web3 } = useWeb3()
const { accountId, web3, isSupportedOceanNetwork } = useWeb3()
const { chainIds } = useUserPreferences()
const { isAssetNetwork } = useAsset()
const newAbortController = useAbortController()
const newCancelToken = useCancelToken()
@ -116,7 +119,7 @@ export default function Compute({
const datatokenInstance = new Datatoken(web3)
const dtBalance = await datatokenInstance.balance(
asset?.services[0].datatokenAddress,
accountId
accountId || ZERO_ADDRESS // if the user is not connected, we use ZERO_ADDRESS as accountId
)
setAlgorithmDTBalance(new Decimal(dtBalance).toString())
const hasAlgoDt = Number(dtBalance) >= 1
@ -134,9 +137,10 @@ export default function Compute({
const initializedProvider = await initializeProviderForCompute(
asset,
selectedAlgorithmAsset,
accountId,
accountId || ZERO_ADDRESS, // if the user is not connected, we use ZERO_ADDRESS as accountId
computeEnv
)
if (
!initializedProvider ||
!initializedProvider?.datasets ||
@ -145,13 +149,17 @@ export default function Compute({
throw new Error(`Error initializing provider for the compute job!`)
setInitializedProviderResponse(initializedProvider)
setProviderFeeAmount(
await unitsToAmount(
web3,
initializedProvider?.datasets?.[0]?.providerFee?.providerFeeToken,
initializedProvider?.datasets?.[0]?.providerFee?.providerFeeAmount
)
const feeAmount = await unitsToAmount(
!isSupportedOceanNetwork || !isAssetNetwork
? await getDummyWeb3(asset?.chainId)
: web3,
initializedProvider?.datasets?.[0]?.providerFee?.providerFeeToken,
initializedProvider?.datasets?.[0]?.providerFee?.providerFeeAmount
)
setProviderFeeAmount(feeAmount)
const computeDuration = (
parseInt(initializedProvider?.datasets?.[0]?.providerFee?.validUntil) -
Math.floor(Date.now() / 1000)
@ -217,7 +225,7 @@ export default function Compute({
}, [asset?.accessDetails, accountId, isUnsupportedPricing])
useEffect(() => {
if (!selectedAlgorithmAsset?.accessDetails || !accountId) return
if (!selectedAlgorithmAsset?.accessDetails) return
setIsRequestingAlgoOrderPrice(true)
setIsConsumableAlgorithmPrice(
@ -306,6 +314,7 @@ export default function Compute({
documentId: selectedAlgorithmAsset.id,
serviceId: selectedAlgorithmAsset.services[0].id
}
const allowed = await isOrderable(
asset,
computeService.id,
@ -450,14 +459,12 @@ export default function Compute({
setSelectedAlgorithm={setSelectedAlgorithmAsset}
isLoading={isOrdering || isRequestingAlgoOrderPrice}
isComputeButtonDisabled={isComputeButtonDisabled}
hasPreviousOrder={validOrderTx !== undefined}
hasPreviousOrder={!!validOrderTx}
hasDatatoken={hasDatatoken}
dtBalance={dtBalance}
assetType={asset?.metadata.type}
assetTimeout={secondsToString(asset?.services[0].timeout)}
hasPreviousOrderSelectedComputeAsset={
validAlgorithmOrderTx !== undefined
}
hasPreviousOrderSelectedComputeAsset={!!validAlgorithmOrderTx}
hasDatatokenSelectedComputeAsset={hasAlgoAssetDatatoken}
datasetSymbol={asset?.accessDetails?.baseToken?.symbol || 'OCEAN'}
algorithmSymbol={

View File

@ -33,7 +33,7 @@ export default function Download({
fileIsLoading?: boolean
consumableFeedback?: string
}): ReactElement {
const { accountId, web3 } = useWeb3()
const { accountId, web3, isSupportedOceanNetwork } = useWeb3()
const { getOpcFeeForToken } = useMarketMetadata()
const { isInPurgatory, isAssetNetwork } = useAsset()
const isMounted = useIsMounted()
@ -184,6 +184,7 @@ export default function Download({
isBalanceSufficient={isBalanceSufficient}
consumableFeedback={consumableFeedback}
retry={retry}
isSupportedOceanNetwork={isSupportedOceanNetwork}
/>
)