mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
279 lines
7.6 KiB
TypeScript
279 lines
7.6 KiB
TypeScript
import React, { ReactElement, useEffect, useState } from 'react'
|
|
import web3 from 'web3'
|
|
import Time from '../../../atoms/Time'
|
|
import { Link } from 'gatsby'
|
|
import { DDO, Logger, Service, Provider } from '@oceanprotocol/lib'
|
|
import { ComputeJobMetaData } from '../../../../@types/ComputeJobMetaData'
|
|
import Dotdotdot from 'react-dotdotdot'
|
|
import Table from '../../../atoms/Table'
|
|
import Button from '../../../atoms/Button'
|
|
import { useOcean } from '../../../../providers/Ocean'
|
|
import { gql, useQuery } from 'urql'
|
|
import { ComputeOrders } from '../../../../@types/apollo/ComputeOrders'
|
|
import { useWeb3 } from '../../../../providers/Web3'
|
|
import {
|
|
queryMetadata,
|
|
transformChainIdsListToQuery
|
|
} from '../../../../utils/aquarius'
|
|
import axios, { CancelToken } from 'axios'
|
|
import Details from './Details'
|
|
import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/Compute'
|
|
import { ReactComponent as Refresh } from '../../../../images/refresh.svg'
|
|
import styles from './index.module.css'
|
|
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
|
|
import { useUserPreferences } from '../../../../providers/UserPreferences'
|
|
|
|
const getComputeOrders = gql`
|
|
query ComputeOrders($user: String!) {
|
|
tokenOrders(
|
|
orderBy: timestamp
|
|
orderDirection: desc
|
|
where: { payer: $user }
|
|
) {
|
|
id
|
|
serviceId
|
|
datatokenId {
|
|
address
|
|
}
|
|
tx
|
|
timestamp
|
|
}
|
|
}
|
|
`
|
|
|
|
export function Status({ children }: { children: string }): ReactElement {
|
|
return <div className={styles.status}>{children}</div>
|
|
}
|
|
|
|
const columns = [
|
|
{
|
|
name: 'Data Set',
|
|
selector: function getAssetRow(row: ComputeJobMetaData) {
|
|
return (
|
|
<Dotdotdot clamp={2}>
|
|
<Link to={`/asset/${row.inputDID[0]}`}>{row.assetName}</Link>
|
|
</Dotdotdot>
|
|
)
|
|
}
|
|
},
|
|
{
|
|
name: 'Created',
|
|
selector: function getTimeRow(row: ComputeJobMetaData) {
|
|
return <Time date={row.dateCreated} isUnix relative />
|
|
}
|
|
},
|
|
{
|
|
name: 'Finished',
|
|
selector: function getTimeRow(row: ComputeJobMetaData) {
|
|
return row.dateFinished ? (
|
|
<Time date={row.dateFinished} isUnix relative />
|
|
) : (
|
|
''
|
|
)
|
|
}
|
|
},
|
|
{
|
|
name: 'Status',
|
|
selector: function getStatus(row: ComputeJobMetaData) {
|
|
return <Status>{row.statusText}</Status>
|
|
}
|
|
},
|
|
{
|
|
name: 'Actions',
|
|
selector: function getActions(row: ComputeJobMetaData) {
|
|
return <Details job={row} />
|
|
}
|
|
}
|
|
]
|
|
|
|
async function getAssetMetadata(
|
|
queryDtList: string,
|
|
cancelToken: CancelToken,
|
|
chainIds: number[]
|
|
): Promise<DDO[]> {
|
|
const queryDid = {
|
|
page: 1,
|
|
offset: 100,
|
|
query: {
|
|
query_string: {
|
|
query: `(${queryDtList}) (${transformChainIdsListToQuery(
|
|
chainIds
|
|
)}) AND (${transformChainIdsListToQuery(
|
|
chainIds
|
|
)}) AND service.attributes.main.type:dataset AND service.type:compute`,
|
|
fields: ['dataToken']
|
|
}
|
|
}
|
|
}
|
|
|
|
const result = await queryMetadata(queryDid, cancelToken)
|
|
|
|
return result.results
|
|
}
|
|
|
|
export default function ComputeJobs(): ReactElement {
|
|
const { ocean, account, config } = useOcean()
|
|
const { accountId } = useWeb3()
|
|
const [isLoading, setIsLoading] = useState(true)
|
|
const [jobs, setJobs] = useState<ComputeJobMetaData[]>([])
|
|
const { chainIds } = useUserPreferences()
|
|
const [result] = useQuery<ComputeOrders>({
|
|
query: getComputeOrders,
|
|
variables: {
|
|
user: accountId?.toLowerCase()
|
|
}
|
|
})
|
|
const { data } = result
|
|
|
|
async function getJobs() {
|
|
if (!accountId) return
|
|
setIsLoading(true)
|
|
|
|
// await refetch()
|
|
const dtList = []
|
|
const computeJobs: ComputeJobMetaData[] = []
|
|
for (let i = 0; i < data.tokenOrders.length; i++) {
|
|
dtList.push(data.tokenOrders[i].datatokenId.address)
|
|
}
|
|
const queryDtList = JSON.stringify(dtList)
|
|
.replace(/,/g, ' ')
|
|
.replace(/"/g, '')
|
|
.replace(/(\[|\])/g, '')
|
|
|
|
try {
|
|
const source = axios.CancelToken.source()
|
|
const assets = await getAssetMetadata(queryDtList, source.token, chainIds)
|
|
const providers: Provider[] = []
|
|
const serviceEndpoints: string[] = []
|
|
for (let i = 0; i < data.tokenOrders.length; i++) {
|
|
try {
|
|
const did = web3.utils
|
|
.toChecksumAddress(data.tokenOrders[i].datatokenId.address)
|
|
.replace('0x', 'did:op:')
|
|
|
|
const ddo = assets.filter((x) => x.id === did)[0]
|
|
|
|
if (!ddo) continue
|
|
|
|
const service = ddo.service.filter(
|
|
(x: Service) => x.index === data.tokenOrders[i].serviceId
|
|
)[0]
|
|
|
|
if (!service || service.type !== 'compute') continue
|
|
const { serviceEndpoint } = service
|
|
|
|
const wasProviderQueried =
|
|
serviceEndpoints.filter((x) => x === serviceEndpoint).length > 0
|
|
|
|
if (wasProviderQueried) continue
|
|
serviceEndpoints.push(serviceEndpoint)
|
|
} catch (err) {
|
|
Logger.error(err)
|
|
}
|
|
}
|
|
|
|
try {
|
|
for (let i = 0; i < serviceEndpoints.length; i++) {
|
|
const instanceConfig = {
|
|
config,
|
|
web3: config.web3Provider,
|
|
logger: Logger,
|
|
ocean: ocean
|
|
}
|
|
const provider = await Provider.getInstance(instanceConfig)
|
|
await provider.setBaseUrl(serviceEndpoints[i])
|
|
const hasSameCompute =
|
|
providers.filter(
|
|
(x) => x.computeAddress === provider.computeAddress
|
|
).length > 0
|
|
if (!hasSameCompute) providers.push(provider)
|
|
}
|
|
} catch (err) {
|
|
Logger.error(err)
|
|
}
|
|
for (let i = 0; i < providers.length; i++) {
|
|
try {
|
|
const providerComputeJobs = (await providers[i].computeStatus(
|
|
'',
|
|
account,
|
|
undefined,
|
|
undefined,
|
|
false
|
|
)) as ComputeJob[]
|
|
|
|
// means the provider uri is not good, so we ignore it and move on
|
|
if (!providerComputeJobs) continue
|
|
providerComputeJobs.sort((a, b) => {
|
|
if (a.dateCreated > b.dateCreated) {
|
|
return -1
|
|
}
|
|
if (a.dateCreated < b.dateCreated) {
|
|
return 1
|
|
}
|
|
return 0
|
|
})
|
|
|
|
for (let j = 0; j < providerComputeJobs.length; j++) {
|
|
const job = providerComputeJobs[j]
|
|
const did = job.inputDID[0]
|
|
const ddo = assets.filter((x) => x.id === did)[0]
|
|
|
|
if (!ddo) continue
|
|
const serviceMetadata = ddo.service.filter(
|
|
(x: Service) => x.type === 'metadata'
|
|
)[0]
|
|
|
|
const compJob: ComputeJobMetaData = {
|
|
...job,
|
|
assetName: serviceMetadata.attributes.main.name,
|
|
assetDtSymbol: ddo.dataTokenInfo.symbol
|
|
}
|
|
computeJobs.push(compJob)
|
|
}
|
|
} catch (err) {
|
|
Logger.error(err)
|
|
}
|
|
}
|
|
setJobs(computeJobs)
|
|
} catch (error) {
|
|
Logger.log(error.message)
|
|
} finally {
|
|
setIsLoading(false)
|
|
}
|
|
return true
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (data === undefined || !chainIds) {
|
|
setIsLoading(false)
|
|
return
|
|
}
|
|
getJobs()
|
|
}, [ocean, account, data, chainIds])
|
|
|
|
return (
|
|
<>
|
|
{jobs.length > 0 && (
|
|
<Button
|
|
style="text"
|
|
size="small"
|
|
title="Refresh compute jobs"
|
|
onClick={() => getJobs()}
|
|
disabled={isLoading}
|
|
className={styles.refresh}
|
|
>
|
|
<Refresh />
|
|
Refresh
|
|
</Button>
|
|
)}
|
|
<Table
|
|
columns={columns}
|
|
data={jobs}
|
|
isLoading={isLoading}
|
|
defaultSortField="row.dateCreated"
|
|
defaultSortAsc={false}
|
|
/>
|
|
</>
|
|
)
|
|
}
|