diff --git a/package-lock.json b/package-lock.json index eefb853..4e18377 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1521,9 +1521,9 @@ "integrity": "sha512-p0oOHXr60hXZuLNsQ/PsOQtCfia79thm7MjPxTrnnBvD+csJoHzARYMB0IFj/KTw6U5vLXODgjJAn8x6QksLwg==" }, "@oceanprotocol/lib": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.9.9.tgz", - "integrity": "sha512-U7lqkSFYhg0W/45ucK1/BA1Z0XH6wtGw15u5LxCzRhXWghPVzyRCkdx/xhs9LZAMl6vabWcIlnp07tMVRcNzJw==", + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.9.12.tgz", + "integrity": "sha512-R52kWSwwpKNzNHfnNbF6seFPvXEtExK3bWIi4V4eIkgmAf272sa6PVza4mJrtEpTAS1WcJv5ihF7cczIDecxbg==", "requires": { "@ethereum-navigator/navigator": "^0.5.0", "@oceanprotocol/contracts": "^0.5.7", @@ -1537,6 +1537,11 @@ "web3-eth-contract": "^1.3.0" } }, + "@oceanprotocol/list-purgatory": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@oceanprotocol/list-purgatory/-/list-purgatory-1.0.5.tgz", + "integrity": "sha512-mp/Ru7nB/ATawlyefSQ2AJHyEoLxntmtWjx3kvuXRaIxF3NDVcdjcVVB0VgBAOLawccEXZ6p4AsIPEVyjqx8zw==" + }, "@octokit/auth-token": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.3.tgz", @@ -5858,9 +5863,9 @@ "integrity": "sha1-o9fZb+HD/wZex84nwsIea6ksGDI=" }, "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" }, "is-callable": { "version": "1.2.0", diff --git a/package.json b/package.json index 1f902e6..16ff0a1 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "dist/" ], "dependencies": { - "@oceanprotocol/lib": "^0.9.9", + "@oceanprotocol/lib": "^0.9.12", "axios": "^0.21.0", "decimal.js": "^10.2.1", "web3": "^1.3.0", diff --git a/src/providers/AssetProvider/AssetProvider.tsx b/src/providers/AssetProvider/AssetProvider.tsx new file mode 100644 index 0000000..9b3d6a2 --- /dev/null +++ b/src/providers/AssetProvider/AssetProvider.tsx @@ -0,0 +1,172 @@ +import React, { + useContext, + useState, + useEffect, + createContext, + ReactElement, + useCallback, + ReactNode +} from 'react' +import { + Logger, + DDO, + Metadata, + BestPrice, + MetadataCache +} from '@oceanprotocol/lib' +import { PurgatoryData } from '@oceanprotocol/lib/dist/node/ddo/interfaces/PurgatoryData' +import { useOcean } from '../index' +import { isDDO, getDataTokenPrice } from 'utils' +import { getAssetPurgatoryData } from '../../utils/getPurgatoryData' +import ProviderStatus from '../OceanProvider/ProviderStatus' +import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' + +interface AssetProviderValue { + isInPurgatory: boolean + purgatoryData: PurgatoryData + ddo: DDO | undefined + did: string | undefined + metadata: Metadata | undefined + title: string | undefined + owner: string | undefined + price: BestPrice | undefined + refreshPrice: () => void +} + +const AssetContext = createContext({} as AssetProviderValue) + +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() + const [internalDdo, setDDO] = useState() + const [internalDid, setDID] = useState() + const [metadata, setMetadata] = useState() + const [title, setTitle] = useState() + const [price, setPrice] = useState() + const [owner, setOwner] = useState() + + const init = useCallback(async () => { + Logger.log('Asset Provider init') + if (!config.metadataCacheUri) return + if (isDDO(asset as string | DDO)) { + setDDO(asset as DDO) + setDID((asset as DDO).id) + } else { + // asset is a DID + + const metadataCache = new MetadataCache(config.metadataCacheUri, Logger) + const ddo = await metadataCache.retrieveDDO(asset as string) + Logger.debug('DDO asset', ddo) + setDDO(ddo) + setDID(asset as string) + } + }, [asset, config.metadataCacheUri]) + + const getPrice = useCallback(async (): Promise => { + if (!internalDdo) + return { + type: '', + address: '', + value: 0, + ocean: 0, + datatoken: 0 + } as BestPrice + + const price = await getDataTokenPrice( + ocean, + internalDdo.dataToken, + internalDdo?.price?.type, + internalDdo.price.pools[0] + ) + return price + }, [ocean, internalDdo]) + + useEffect(() => { + // removed until we can properly test and refactor market + // init() + }, [init, asset, ocean, status]) + + const setPurgatory = useCallback(async (did: string): Promise => { + if (!did) return + try { + const result = await getAssetPurgatoryData(did) + + if (result.did !== undefined) { + setIsInPurgatory(true) + setPurgatoryData(result) + } else { + setIsInPurgatory(false) + } + setPurgatoryData(result) + } catch (error) { + Logger.error(error) + } + }, []) + const initMetadata = useCallback(async (): Promise => { + // remove until we can properly implement this + // if (!internalDdo) return + // setPrice(internalDdo.price) + + // const metadata = internalDdo.findServiceByType('metadata').attributes + // setMetadata(metadata) + // setTitle(metadata.main.name) + // setOwner(internalDdo.publicKey[0].owner) + + // setIsInPurgatory(internalDdo.isInPurgatory) + // setPurgatoryData(internalDdo.purgatoryData) + setMetadata(undefined) + setTitle('not_implemented') + setOwner('not_implemented') + if (!asset) return + await setPurgatory(asset as string) + // Stop here and do not start fetching from chain, when not connected properly. + if (status !== 1 || networkId !== (config as ConfigHelperConfig).networkId) + return + + // Set price again, but from chain + const priceLive = await getPrice() + setPrice(priceLive) + }, [internalDdo, getPrice]) + + useEffect(() => { + if (!internalDdo || !ocean || status !== ProviderStatus.CONNECTED) return + initMetadata() + }, [status, internalDdo, initMetadata]) + + async function refreshPrice(): Promise { + const livePrice = await getPrice() + setPrice(livePrice) + } + return ( + + {children} + + ) +} + +// Helper hook to access the provider values +const useAsset = (): AssetProviderValue => useContext(AssetContext) + +export { AssetProvider, useAsset, AssetProviderValue, AssetContext } +export default AssetProvider diff --git a/src/providers/AssetProvider/index.ts b/src/providers/AssetProvider/index.ts new file mode 100644 index 0000000..29eda98 --- /dev/null +++ b/src/providers/AssetProvider/index.ts @@ -0,0 +1 @@ +export * from './AssetProvider' diff --git a/src/providers/OceanProvider/OceanProvider.tsx b/src/providers/OceanProvider/OceanProvider.tsx index 54c9099..5daa0d7 100644 --- a/src/providers/OceanProvider/OceanProvider.tsx +++ b/src/providers/OceanProvider/OceanProvider.tsx @@ -9,11 +9,21 @@ import React, { } from 'react' import Web3 from 'web3' import ProviderStatus from './ProviderStatus' -import { Ocean, Logger, Account, Config } from '@oceanprotocol/lib' +import { + Ocean, + Logger, + Account, + Config, + PurgatoryData +} from '@oceanprotocol/lib' import Web3Modal, { ICoreOptions } from 'web3modal' import { getDefaultProviders } from './getDefaultProviders' import { getAccountId, getBalance } from 'utils' import { ConfigHelperConfig } from '@oceanprotocol/lib/dist/node/utils/ConfigHelper' +import { + AccountPurgatoryData, + getAccountPurgatoryData +} from 'utils/getPurgatoryData' interface Balance { eth: string | undefined @@ -27,6 +37,8 @@ interface OceanProviderValue { ocean: Ocean config: Config | ConfigHelperConfig account: Account + isInPurgatory: boolean + purgatoryData: AccountPurgatoryData accountId: string balance: Balance networkId: number | undefined @@ -54,6 +66,8 @@ function OceanProvider({ const [networkId, setNetworkId] = useState() const [account, setAccount] = useState() const [accountId, setAccountId] = useState() + const [isInPurgatory, setIsInPurgatory] = useState(false) + const [purgatoryData, setPurgatoryData] = useState() const [config, setConfig] = useState( initialConfig ) @@ -65,6 +79,23 @@ function OceanProvider({ ProviderStatus.NOT_AVAILABLE ) + const setPurgatory = useCallback(async (accountId: string): Promise => { + if (!accountId) return + try { + const result = await getAccountPurgatoryData(accountId) + + if (result.address !== undefined) { + setIsInPurgatory(true) + setPurgatoryData(result) + } else { + setIsInPurgatory(false) + } + setPurgatoryData(result) + } catch (error) { + Logger.error(error) + } + }, []) + const init = useCallback(async () => { Logger.log('Ocean Provider init') window && @@ -116,6 +147,8 @@ function OceanProvider({ const balance = await getBalance(account) setBalance(balance) Logger.log('balance', JSON.stringify(balance)) + + await setPurgatory(accountId) } catch (error) { Logger.error(error) } @@ -173,6 +206,8 @@ function OceanProvider({ ocean, account, accountId, + isInPurgatory, + purgatoryData, balance, networkId, status, diff --git a/src/providers/index.ts b/src/providers/index.ts index 0cc537c..407164a 100644 --- a/src/providers/index.ts +++ b/src/providers/index.ts @@ -1 +1,2 @@ export * from './OceanProvider' +export * from './AssetProvider' diff --git a/src/utils/dtUtils.ts b/src/utils/dtUtils.ts index 702b08e..e6b23ee 100644 --- a/src/utils/dtUtils.ts +++ b/src/utils/dtUtils.ts @@ -86,7 +86,6 @@ export async function getFirstExchange(ocean: Ocean, dataTokenAddress: string) { dataTokenAddress, '1' ) - Logger.log('Found exchanges', tokenExchanges) if (tokenExchanges === undefined || tokenExchanges.length === 0) { return { address: '', diff --git a/src/utils/getPurgatoryData.ts b/src/utils/getPurgatoryData.ts new file mode 100644 index 0000000..0b746c2 --- /dev/null +++ b/src/utils/getPurgatoryData.ts @@ -0,0 +1,24 @@ +import { PurgatoryData } from '@oceanprotocol/lib' +import axios from 'axios' +const purgatoryUrl = 'https://market-purgatory.oceanprotocol.com/api/' + +export interface AccountPurgatoryData { + address: string + reason: string +} + +export async function getAssetPurgatoryData( + did: string +): Promise { + const response = await axios(`${purgatoryUrl}asset?did=${did}`) + const responseJson = await response.data[0] + return { did: responseJson.did, reason: responseJson.reason } +} + +export async function getAccountPurgatoryData( + address: string +): Promise { + const response = await axios(`${purgatoryUrl}account?address=${address}`) + const responseJson = await response.data[0] + return { address: responseJson.address, reason: responseJson.reason } +}