mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
210 lines
5.4 KiB
TypeScript
210 lines
5.4 KiB
TypeScript
import React, {
|
|
useContext,
|
|
useState,
|
|
useEffect,
|
|
createContext,
|
|
ReactElement,
|
|
useCallback,
|
|
ReactNode
|
|
} from 'react'
|
|
import { Logger, DDO, BestPrice, MetadataMain } from '@oceanprotocol/lib'
|
|
import { PurgatoryData } from '@oceanprotocol/lib/dist/node/ddo/interfaces/PurgatoryData'
|
|
import { getDataTokenPrice, useOcean } from '@oceanprotocol/react'
|
|
import getAssetPurgatoryData from '../utils/purgatory'
|
|
import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper'
|
|
import axios, { CancelToken } from 'axios'
|
|
import { retrieveDDO } from '../utils/aquarius'
|
|
import { MetadataMarket } from '../@types/MetaData'
|
|
|
|
interface AssetProviderValue {
|
|
isInPurgatory: boolean
|
|
purgatoryData: PurgatoryData
|
|
ddo: DDO | undefined
|
|
did: string | undefined
|
|
metadata: MetadataMarket | undefined
|
|
title: string | undefined
|
|
owner: string | undefined
|
|
price: BestPrice | undefined
|
|
type: MetadataMain['type'] | undefined
|
|
error?: string
|
|
refreshInterval: number
|
|
refreshDdo: (token?: CancelToken) => Promise<void>
|
|
refreshPrice: () => Promise<void>
|
|
}
|
|
|
|
const AssetContext = createContext({} as AssetProviderValue)
|
|
|
|
const refreshInterval = 10000 // 10 sec.
|
|
|
|
function AssetProvider({
|
|
asset,
|
|
children
|
|
}: {
|
|
asset: string | DDO
|
|
children: ReactNode
|
|
}): ReactElement {
|
|
const { ocean, status, config, networkId } = useOcean()
|
|
const [isInPurgatory, setIsInPurgatory] = useState(false)
|
|
const [purgatoryData, setPurgatoryData] = useState<PurgatoryData>()
|
|
const [ddo, setDDO] = useState<DDO>()
|
|
const [did, setDID] = useState<string>()
|
|
const [metadata, setMetadata] = useState<MetadataMarket>()
|
|
const [title, setTitle] = useState<string>()
|
|
const [price, setPrice] = useState<BestPrice>()
|
|
const [owner, setOwner] = useState<string>()
|
|
const [error, setError] = useState<string>()
|
|
const [type, setType] = useState<MetadataMain['type']>()
|
|
|
|
const refreshPrice = useCallback(async () => {
|
|
if (
|
|
!ddo ||
|
|
status !== 1 ||
|
|
networkId !== (config as ConfigHelperConfig).networkId
|
|
)
|
|
return
|
|
|
|
const newPrice = await getDataTokenPrice(
|
|
ocean,
|
|
ddo.dataToken,
|
|
ddo?.price?.type,
|
|
ddo.price.address
|
|
)
|
|
setPrice(newPrice)
|
|
Logger.log(`Refreshed asset price: ${newPrice?.value}`, newPrice)
|
|
}, [ocean, config, ddo, networkId, status])
|
|
|
|
const fetchDdo = async (token?: CancelToken) => {
|
|
Logger.log('Init asset, get ddo')
|
|
const ddo = await retrieveDDO(
|
|
asset as string,
|
|
config.metadataCacheUri,
|
|
token
|
|
)
|
|
|
|
if (!ddo) {
|
|
setError(
|
|
`The DDO for ${asset} was not found in MetadataCache. If you just published a new data set, wait some seconds and refresh this page.`
|
|
)
|
|
} else {
|
|
setError(undefined)
|
|
}
|
|
return ddo
|
|
}
|
|
|
|
const refreshDdo = async (token?: CancelToken) => {
|
|
const ddo = await fetchDdo(token)
|
|
Logger.debug('DDO', ddo)
|
|
setDDO(ddo)
|
|
}
|
|
//
|
|
// Get and set DDO based on passed DDO or DID
|
|
//
|
|
useEffect(() => {
|
|
if (!asset || !config?.metadataCacheUri) return
|
|
|
|
const source = axios.CancelToken.source()
|
|
let isMounted = true
|
|
Logger.log('Init asset, get ddo')
|
|
|
|
async function init() {
|
|
const ddo = await fetchDdo(source.token)
|
|
if (!isMounted) return
|
|
Logger.debug('DDO', ddo)
|
|
setDDO(ddo)
|
|
setDID(asset as string)
|
|
}
|
|
init()
|
|
return () => {
|
|
isMounted = false
|
|
source.cancel()
|
|
}
|
|
}, [asset, config?.metadataCacheUri])
|
|
|
|
useEffect(() => {
|
|
// Re-fetch price periodically, triggering re-calculation of everything
|
|
let isMounted = true
|
|
|
|
const interval = setInterval(() => {
|
|
if (!isMounted) return
|
|
refreshPrice()
|
|
}, refreshInterval)
|
|
|
|
return () => {
|
|
clearInterval(interval)
|
|
isMounted = false
|
|
}
|
|
}, [ddo, networkId, refreshPrice])
|
|
|
|
const setPurgatory = useCallback(async (did: string): Promise<void> => {
|
|
if (!did) return
|
|
try {
|
|
const result = await getAssetPurgatoryData(did)
|
|
|
|
if (result?.did !== undefined) {
|
|
setIsInPurgatory(true)
|
|
setPurgatoryData(result)
|
|
return
|
|
}
|
|
|
|
setIsInPurgatory(false)
|
|
} catch (error) {
|
|
Logger.error(error)
|
|
}
|
|
}, [])
|
|
|
|
const initMetadata = useCallback(
|
|
async (ddo: DDO): Promise<void> => {
|
|
if (!ddo) return
|
|
|
|
Logger.log('Init metadata')
|
|
// Set price & metadata from DDO first
|
|
setPrice(ddo.price)
|
|
const { attributes } = ddo.findServiceByType('metadata')
|
|
setMetadata((attributes as unknown) as MetadataMarket)
|
|
setTitle(attributes?.main.name)
|
|
setType(attributes.main.type)
|
|
setOwner(ddo.publicKey[0].owner)
|
|
setIsInPurgatory(ddo.isInPurgatory === 'true')
|
|
|
|
await setPurgatory(ddo.id)
|
|
await refreshPrice()
|
|
},
|
|
[refreshPrice, setPurgatory]
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (!ddo) return
|
|
initMetadata(ddo)
|
|
}, [ddo, initMetadata])
|
|
|
|
return (
|
|
<AssetContext.Provider
|
|
value={
|
|
{
|
|
ddo,
|
|
did,
|
|
metadata,
|
|
title,
|
|
owner,
|
|
price,
|
|
type,
|
|
error,
|
|
isInPurgatory,
|
|
purgatoryData,
|
|
refreshInterval,
|
|
refreshDdo,
|
|
refreshPrice
|
|
} as AssetProviderValue
|
|
}
|
|
>
|
|
{children}
|
|
</AssetContext.Provider>
|
|
)
|
|
}
|
|
|
|
// Helper hook to access the provider values
|
|
const useAsset = (): AssetProviderValue => useContext(AssetContext)
|
|
|
|
export { AssetProvider, useAsset, AssetProviderValue, AssetContext }
|
|
export default AssetProvider
|