1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

move asset selection to compute helper

This commit is contained in:
Bogdan Fazakas 2022-02-10 16:33:16 +02:00
parent 24ad553765
commit cd2a4da8c5
5 changed files with 189 additions and 111 deletions

View File

@ -45,7 +45,7 @@ export function generateBaseQuery(
filter: [
...(baseQueryParams.filters || []),
getFilterTerm('chainId', baseQueryParams.chainIds),
getFilterTerm('_index', 'aquarius'),
// getFilterTerm('_index', 'aquarius'),
...(baseQueryParams.ignorePurgatory
? []
: [getFilterTerm('purgatory.state', false)])

View File

@ -15,14 +15,22 @@ import {
ComputeAlgorithm,
Service,
LoggerInstance,
ProviderInstance
ProviderInstance,
PublisherTrustedAlgorithm
} from '@oceanprotocol/lib'
import { CancelToken } from 'axios'
import { gql } from 'urql'
import { queryMetadata, getFilterTerm, generateBaseQuery } from './aquarius'
import {
queryMetadata,
getFilterTerm,
generateBaseQuery,
transformDDOToAssetSelection
} from './aquarius'
import { fetchDataForMultipleChains } from './subgraph'
import { getServiceById } from './ddo'
import { getServiceById, getServiceByName } from './ddo'
import { getOceanConfig } from './ocean'
import { SortTermOptions } from 'src/@types/aquarius/SearchQuery'
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
const getComputeOrders = gql`
query ComputeOrders($user: String!) {
@ -115,6 +123,74 @@ export async function isOrderable(
}
}
function getQuerryString(
trustedAlgorithmList: PublisherTrustedAlgorithm[],
chainId?: number
): SearchQuery {
const algorithmDidList = trustedAlgorithmList.map((x) => x.did)
const baseParams = {
chainIds: [chainId],
sort: { sortBy: SortTermOptions.Created },
filters: [
getFilterTerm('metadata.type', 'algorithm'),
getFilterTerm('id', algorithmDidList)
]
} as BaseQueryParams
const query = generateBaseQuery(baseParams)
return query
}
export async function getAlgorithmsForAsset(
asset: Asset,
token: CancelToken
): Promise<Asset[]> {
const computeService: Service = getServiceByName(asset, 'compute')
let algorithms: Asset[]
if (
!computeService.compute ||
!computeService.compute.publisherTrustedAlgorithms ||
computeService.compute.publisherTrustedAlgorithms.length === 0
) {
algorithms = []
} else {
const gueryResults = await queryMetadata(
getQuerryString(
computeService.compute.publisherTrustedAlgorithms,
asset.chainId
),
token
)
algorithms = gueryResults?.results
}
return algorithms
}
export async function getAlgorithmAssetSelectionList(
asset: Asset,
algorithms: Asset[],
token: CancelToken
): Promise<AssetSelectionAsset[]> {
const computeService: Service = getServiceByName(asset, 'compute')
let algorithmSelectionList: AssetSelectionAsset[]
if (
!computeService.compute ||
!computeService.compute.publisherTrustedAlgorithms ||
computeService.compute.publisherTrustedAlgorithms.length === 0
) {
algorithmSelectionList = []
} else {
algorithmSelectionList = await transformDDOToAssetSelection(
computeService?.serviceEndpoint,
algorithms,
[],
token
)
}
return algorithmSelectionList
}
function getServiceEndpoints(data: TokenOrder[], assets: Asset[]): string[] {
// const serviceEndpoints: string[] = []

View File

@ -17,7 +17,8 @@ import {
approve,
TokenInOutMarket,
AmountsInMaxFee,
AmountsOutMaxFee
AmountsOutMaxFee,
Service
} from '@oceanprotocol/lib'
import { toast } from 'react-toastify'
import Price from '@shared/Price'
@ -39,8 +40,14 @@ import FormStartComputeDataset from './FormComputeDataset'
import styles from './index.module.css'
import SuccessConfetti from '@shared/SuccessConfetti'
import { getServiceByName, secondsToString } from '@utils/ddo'
import { isOrderable } from '@utils/compute'
import { AssetSelectionAsset } from '@shared/FormFields/AssetSelection'
import {
isOrderable,
getAlgorithmAssetSelectionList,
getAlgorithmsForAsset
} from '@utils/compute'
import AssetSelection, {
AssetSelectionAsset
} from '@shared/FormFields/AssetSelection'
import AlgorithmDatasetsListForCompute from './AlgorithmDatasetsListForCompute'
import { getPreviousOrders } from '@utils/subgraph'
import AssetActionHistoryTable from '../AssetActionHistoryTable'
@ -52,10 +59,9 @@ import { Decimal } from 'decimal.js'
import { TransactionReceipt } from 'web3-core'
import { useAbortController } from '@hooks/useAbortController'
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
import AssetDetails from '../..'
export default function Compute({
ddo,
asset,
accessDetails,
dtBalance,
file,
@ -63,7 +69,7 @@ export default function Compute({
isConsumable,
consumableFeedback
}: {
ddo: Asset
asset: Asset
accessDetails: AccessDetails
dtBalance: string
file: FileMetadata
@ -94,9 +100,9 @@ export default function Compute({
useState<string>()
const [datasetTimeout, setDatasetTimeout] = useState<string>()
const [algorithmTimeout, setAlgorithmTimeout] = useState<string>()
const newCancelToken = useCancelToken()
const hasDatatoken = Number(dtBalance) >= 1
const isMounted = useIsMounted()
const newCancelToken = useCancelToken()
const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [isAlgoConsumablePrice, setIsAlgoConsumablePrice] = useState(true)
const isComputeButtonDisabled =
@ -107,13 +113,13 @@ export default function Compute({
!hasAlgoAssetDatatoken &&
!isAlgoConsumablePrice)
const { timeout } = ddo?.services[0]
const { timeout } = asset?.services[0]
async function checkPreviousOrders(ddo: DDO) {
const { type } = ddo.metadata
async function checkPreviousOrders(asset: DDO) {
const { type } = asset.metadata
const orderId = await getPreviousOrders(
ddo.services[0].datatokenAddress?.toLowerCase(),
asset.services[0].datatokenAddress?.toLowerCase(),
accountId?.toLowerCase(),
timeout.toString()
)
@ -138,60 +144,11 @@ export default function Compute({
setHasAlgoAssetDatatoken(Number(AssetDtBalance) >= 1)
}
function getQuerryString(
trustedAlgorithmList: PublisherTrustedAlgorithm[],
chainId?: number
): SearchQuery {
const algorithmDidList = trustedAlgorithmList.map((x) => x.did)
const baseParams = {
chainIds: [chainId],
sort: { sortBy: SortTermOptions.Created },
filters: [
getFilterTerm('service.attributes.main.type', 'algorithm'),
getFilterTerm('id', algorithmDidList)
]
} as BaseQueryParams
const query = generateBaseQuery(baseParams)
return query
}
async function getAlgorithmList(): Promise<AssetSelectionAsset[]> {
const source = axios.CancelToken.source()
const computeService = ddo.services[0]
let algorithmSelectionList: AssetSelectionAsset[]
if (
!computeService.compute ||
!computeService.compute.publisherTrustedAlgorithms ||
computeService.compute.publisherTrustedAlgorithms.length === 0
) {
algorithmSelectionList = []
} else {
const gueryResults = await queryMetadata(
getQuerryString(
computeService.compute.publisherTrustedAlgorithms,
ddo.chainId
),
source.token
)
setDdoAlgorithmList(gueryResults.results)
algorithmSelectionList = await transformDDOToAssetSelection(
computeService?.serviceEndpoint,
gueryResults.results,
[],
newCancelToken()
)
}
return algorithmSelectionList
}
const initMetadata = useCallback(async (ddo: Asset): Promise<void> => {
if (!ddo) return
const initMetadata = useCallback(async (asset: Asset): Promise<void> => {
if (!asset) return
const accessDetails = await getAccessDetails(
ddo.chainId,
ddo.services[0].datatokenAddress
asset.chainId,
asset.services[0].datatokenAddress
)
setAlgorithmConsumeDetails(accessDetails)
}, [])
@ -213,23 +170,31 @@ export default function Compute({
// }, [ddo])
useEffect(() => {
if (!ddo) return
getAlgorithmList().then((algorithms) => {
setAlgorithmList(algorithms)
if (!asset) return
getAlgorithmsForAsset(asset, newCancelToken()).then((algorithmsAssets) => {
setDdoAlgorithmList(algorithmsAssets)
getAlgorithmAssetSelectionList(
asset,
algorithmsAssets,
newCancelToken()
).then((algorithmSelectionList) => {
setAlgorithmList(algorithmSelectionList)
})
}, [ddo])
})
}, [asset])
useEffect(() => {
if (!accountId) return
checkPreviousOrders(ddo)
}, [ddo, accountId])
checkPreviousOrders(asset)
}, [asset, accountId])
useEffect(() => {
if (!selectedAlgorithmAsset) return
initMetadata(selectedAlgorithmAsset)
const { timeout } = ddo.services[0]
const { timeout } = asset.services[0]
// setAlgorithmTimeout(secondsToString(timeout))
@ -248,7 +213,7 @@ export default function Compute({
}
}
checkAssetDTBalance(selectedAlgorithmAsset)
}, [ddo, selectedAlgorithmAsset, accountId, hasPreviousAlgorithmOrder])
}, [asset, selectedAlgorithmAsset, accountId, hasPreviousAlgorithmOrder])
// Output errors in toast UI
useEffect(() => {
@ -257,13 +222,13 @@ export default function Compute({
toast.error(newError)
}, [error, pricingError])
async function startJob(algorithmId: string) {
async function startJob(algorithmId: string): Promise<string> {
try {
setIsJobStarting(true)
setIsPublished(false) // would be nice to rename this
setError(undefined)
const computeService = getServiceByName(ddo, 'compute')
const computeService = getServiceByName(asset, 'compute')
const serviceAlgo = getServiceByName(selectedAlgorithmAsset, 'access')
? getServiceByName(selectedAlgorithmAsset, 'access')
: getServiceByName(selectedAlgorithmAsset, 'compute')
@ -274,7 +239,7 @@ export default function Compute({
}
const allowed = await isOrderable(
ddo,
asset,
computeService.id,
computeAlgorithm,
selectedAlgorithmAsset
@ -296,11 +261,11 @@ export default function Compute({
if (!hasPreviousDatasetOrder) {
// going to move/replace part of this logic when the use consume hook will be ready
const initializeData = await ProviderInstance.initialize(
ddo.id,
ddo.services[0].id,
asset.id,
asset.services[0].id,
0,
accountId,
ddo.services[0].serviceEndpoint //to check
asset.services[0].serviceEndpoint // to check
)
const providerFees: ProviderFees = {
providerFeeAddress: initializeData.providerFee.providerFeeAddress,
@ -375,6 +340,8 @@ export default function Compute({
tokenInOutMarket,
amountsInOutMaxFee
)
break
}
case 'fixed': {
const datatokenInstance = new Datatoken(web3)
@ -392,12 +359,14 @@ export default function Compute({
marketFeeAddress: appConfig.marketFeeAddress
}
tx = await datatokenInstance.buyFromFreAndOrder(
ddo.datatokens[0].address,
asset.datatokens[0].address,
accountId,
order,
fre
)
assetOrderId = tx.transactionHash
break
}
case 'free': {
const datatokenInstance = new Datatoken(web3)
@ -415,26 +384,27 @@ export default function Compute({
marketFeeAddress: appConfig.marketFeeAddress
}
tx = await datatokenInstance.buyFromDispenserAndOrder(
ddo.datatokens[0].address,
asset.datatokens[0].address,
accountId,
order,
accessDetails.addressOrId
)
assetOrderId = tx.transactionHash
}
}
if (!tx) {
setError('Error buying datatoken.')
LoggerInstance.error(
'[compute] Error buying datatoken for data set ',
ddo.id
asset.id
)
return
}
break
}
}
} else {
const datatokenInstance = new Datatoken(web3)
const tx = await datatokenInstance.startOrder(
ddo.datatokens[0].address,
asset.datatokens[0].address,
accountId,
initializeData.computeAddress,
0,
@ -531,6 +501,7 @@ export default function Compute({
tokenInOutMarket,
amountsInOutMaxFee
)
break
}
case 'fixed': {
const datatokenInstance = new Datatoken(web3)
@ -554,6 +525,7 @@ export default function Compute({
fre
)
algorithmAssetOrderId = tx.transactionHash
break
}
case 'free': {
const datatokenInstance = new Datatoken(web3)
@ -577,6 +549,7 @@ export default function Compute({
algorithmConsumeDetails.addressOrId
)
algorithmAssetOrderId = tx.transactionHash
break
}
}
} else {
@ -615,8 +588,8 @@ export default function Compute({
LoggerInstance.log('[compute] Starting compute job.')
const computeAsset: ComputeAsset = {
documentId: ddo.id,
serviceId: ddo.services[0].id,
documentId: asset.id,
serviceId: asset.services[0].id,
transferTxId: assetOrderId
}
computeAlgorithm.transferTxId = algorithmAssetOrderId
@ -627,7 +600,7 @@ export default function Compute({
}
const response = await ProviderInstance.computeStart(
ddo.services[0].serviceEndpoint,
asset.services[0].serviceEndpoint,
web3,
accountId,
'env1',
@ -646,17 +619,18 @@ export default function Compute({
LoggerInstance.log('[compute] Starting compute job response: ', response)
await checkPreviousOrders(selectedAlgorithmAsset)
await checkPreviousOrders(ddo)
await checkPreviousOrders(asset)
setIsPublished(true)
} catch (error) {
await checkPreviousOrders(selectedAlgorithmAsset)
await checkPreviousOrders(ddo)
await checkPreviousOrders(asset)
setError('Failed to start job!')
LoggerInstance.error('[compute] Failed to start job: ', error.message)
} finally {
setIsJobStarting(false)
}
}
return (
<>
<div className={styles.info}>
@ -664,13 +638,16 @@ export default function Compute({
<Price accessDetails={accessDetails} conversion />
</div>
{ddo.metadata.type === 'algorithm' ? (
{asset.metadata.type === 'algorithm' ? (
<>
<Alert
text="This algorithm has been set to private by the publisher and can't be downloaded. You can run it against any allowed data sets though!"
state="info"
/>
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} ddo={ddo} />
<AlgorithmDatasetsListForCompute
algorithmDid={asset.id}
ddo={asset}
/>
</>
) : (
<Formik
@ -691,7 +668,7 @@ export default function Compute({
hasDatatoken={hasDatatoken}
dtBalance={dtBalance}
datasetLowPoolLiquidity={!isConsumablePrice}
assetType={ddo?.metadata.type}
assetType={asset?.metadata.type}
assetTimeout={datasetTimeout}
hasPreviousOrderSelectedComputeAsset={hasPreviousAlgorithmOrder}
hasDatatokenSelectedComputeAsset={hasAlgoAssetDatatoken}

View File

@ -131,7 +131,7 @@ export default function AssetActions({
const UseContent = isCompute ? (
<Compute
ddo={asset}
asset={asset}
accessDetails={asset?.accessDetails}
dtBalance={dtBalance}
file={fileMetadata}

View File

@ -1,4 +1,5 @@
import React, { ReactElement } from 'react'
import React, { ReactElement, useEffect, useState } from 'react'
import { useWeb3 } from '@context/Web3'
import Markdown from '@shared/Markdown'
import MetaFull from './MetaFull'
import MetaSecondary from './MetaSecondary'
@ -14,15 +15,39 @@ import styles from './index.module.css'
import NetworkName from '@shared/NetworkName'
import content from '../../../../content/purgatory.json'
import { AssetExtended } from 'src/@types/AssetExtended'
import Button from '@shared/atoms/Button'
import { getServiceById, getServiceByName } from '@utils/ddo'
import EditComputeDataset from '../Edit/EditComputeDataset'
export default function AssetContent({
asset
}: {
asset: AssetExtended
}): ReactElement {
const { accountId } = useWeb3()
const { debug } = useUserPreferences()
const { isInPurgatory, purgatoryData } = useAsset()
const { owner, isInPurgatory, purgatoryData, isAssetNetwork } = useAsset()
const [isOwner, setIsOwner] = useState(false)
const [isComputeType, setIsComputeType] = useState<boolean>(false)
const [showEditCompute, setShowEditCompute] = useState<boolean>()
useEffect(() => {
if (!accountId || !owner) return
const isOwner = accountId.toLowerCase() === owner.toLowerCase()
setIsOwner(isOwner)
// setShowPricing(isOwner && price.type === '')
setIsComputeType(Boolean(getServiceByName(asset, 'compute')))
}, [accountId, asset?.accessDetails, owner, asset])
function handleEditComputeButton() {
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
setShowEditCompute(true)
}
// return showEditCompute ? (
// <EditComputeDataset setShowEdit={setShowEditCompute} />
// ) : (
return (
<>
<div className={styles.networkWrap}>
@ -68,16 +93,16 @@ export default function AssetContent({
with own URL instead of switching out AssetContent in place.
Simple way would be modal usage
*/}
{/* {isOwner && isAssetNetwork && (
{isOwner && isAssetNetwork && (
<div className={styles.ownerActions}>
<Button
{/* <Button
style="text"
size="small"
onClick={handleEditButton}
onClick={handleEditComputeButton}
>
Edit Metadata
</Button>
{serviceCompute && ddo?.metadata.type === 'dataset' && (
</Button> */}
{isComputeType && asset.metadata.type === 'dataset' && (
<>
<span className={styles.separator}>|</span>
<Button
@ -90,7 +115,7 @@ export default function AssetContent({
</>
)}
</div>
)} */}
)}
</div>
</article>
</>