From 55326352fa7fd7633fda59f237ded949f8dc9c88 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Thu, 8 Oct 2020 12:56:40 +0200 Subject: [PATCH 1/2] BestPrice updates --- package-lock.json | 6 ++-- package.json | 2 +- src/hooks/useMetadata/BestPrice.ts | 5 --- src/hooks/useMetadata/Pool.ts | 4 ++- src/hooks/useMetadata/index.ts | 1 - src/hooks/useMetadata/useMetadata.ts | 11 ++---- src/utils/dtUtils.ts | 52 ++++++++++++++-------------- 7 files changed, 36 insertions(+), 45 deletions(-) delete mode 100644 src/hooks/useMetadata/BestPrice.ts diff --git a/package-lock.json b/package-lock.json index 97f7b01..78971d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1521,9 +1521,9 @@ "integrity": "sha512-gJ8qQACJgxOPIrPE0OFQ09iYXBAisOGg56EmelQlsMUgp0yY0DKgBntDP83S/Ho1yBjGygqfxCjQrPH63hh/PA==" }, "@oceanprotocol/lib": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.5.5.tgz", - "integrity": "sha512-TJTehUaQnFfNp0dJmw0t15+mpYbTkeF+RX4oc6D5FN7hmlhdvC8kfGf8yeHiqxI2Nb703foFLSSs38MWu/XEpg==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.5.6.tgz", + "integrity": "sha512-S8OU/FYjDJCKkx098GDT9LfxmTTe/gA8zv5fVMy7lRG1k5WFDsHHMplqZkU9mUGXg1aDDtt7KbctwxNdt7ZGFg==", "requires": { "@ethereum-navigator/navigator": "^0.5.0", "@oceanprotocol/contracts": "^0.5.3", diff --git a/package.json b/package.json index 30b71c9..4eac7dd 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "dist/" ], "dependencies": { - "@oceanprotocol/lib": "^0.5.5", + "@oceanprotocol/lib": "^0.5.6", "axios": "^0.20.0", "decimal.js": "^10.2.1", "web3": "^1.3.0", diff --git a/src/hooks/useMetadata/BestPrice.ts b/src/hooks/useMetadata/BestPrice.ts deleted file mode 100644 index 888752f..0000000 --- a/src/hooks/useMetadata/BestPrice.ts +++ /dev/null @@ -1,5 +0,0 @@ -export default interface BestPrice { - type: 'pool' | 'exchange' - address: string - value: string -} diff --git a/src/hooks/useMetadata/Pool.ts b/src/hooks/useMetadata/Pool.ts index e17afe0..8a2650e 100644 --- a/src/hooks/useMetadata/Pool.ts +++ b/src/hooks/useMetadata/Pool.ts @@ -1,4 +1,6 @@ export default interface Pool { address: string - price: string + price: number + ocean?: number + datatoken?: number } diff --git a/src/hooks/useMetadata/index.ts b/src/hooks/useMetadata/index.ts index b39bece..d513773 100644 --- a/src/hooks/useMetadata/index.ts +++ b/src/hooks/useMetadata/index.ts @@ -1,3 +1,2 @@ export * from './useMetadata' export * from './Pool' -export * from './BestPrice' diff --git a/src/hooks/useMetadata/useMetadata.ts b/src/hooks/useMetadata/useMetadata.ts index a68550a..22515a0 100644 --- a/src/hooks/useMetadata/useMetadata.ts +++ b/src/hooks/useMetadata/useMetadata.ts @@ -1,10 +1,9 @@ import { useState, useEffect, useCallback } from 'react' -import { DID, DDO, Metadata, Logger } from '@oceanprotocol/lib' +import { DID, DDO, Metadata, Logger, BestPrice } from '@oceanprotocol/lib' import { useOcean } from 'providers' import ProviderStatus from 'providers/OceanProvider/ProviderStatus' import { getBestDataTokenPrice } from 'utils/dtUtils' import { isDDO } from 'utils' -import BestPrice from './BestPrice' interface UseMetadata { ddo: DDO | undefined @@ -35,14 +34,10 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata { const getPrice = useCallback( async (dataTokenAddress: string): Promise => { - const price = await getBestDataTokenPrice( - ocean, - dataTokenAddress, - accountId - ) + const price = await getBestDataTokenPrice(ocean, dataTokenAddress) return price }, - [ocean, accountId] + [ocean] ) const getMetadata = useCallback(async (ddo: DDO): Promise => { diff --git a/src/utils/dtUtils.ts b/src/utils/dtUtils.ts index d1c813e..c875f9b 100644 --- a/src/utils/dtUtils.ts +++ b/src/utils/dtUtils.ts @@ -1,7 +1,7 @@ -import { Logger, Ocean, Account, Config } from '@oceanprotocol/lib' +import { Logger, Ocean, Account, Config, BestPrice } from '@oceanprotocol/lib' +import { TransactionReceipt } from 'web3-core' import { Decimal } from 'decimal.js' import Pool from 'hooks/useMetadata/Pool' -import BestPrice from 'hooks/useMetadata/BestPrice' import Web3 from 'web3' export async function getCheapestPool( @@ -15,7 +15,7 @@ export async function getCheapestPool( if (tokenPools === undefined || tokenPools.length === 0) { return { address: '', - price: '' + price: 0 } } let cheapestPoolAddress = tokenPools[0] @@ -33,16 +33,21 @@ export async function getCheapestPool( } } + const oceanReserve = await ocean.pool.getOceanReserve(cheapestPoolAddress) + const dtReserve = await ocean.pool.getDTReserve(cheapestPoolAddress) + return { address: cheapestPoolAddress, - price: cheapestPoolPrice.toString() + price: Number(cheapestPoolPrice), + ocean: Number(oceanReserve), + datatoken: Number(dtReserve) } } export async function getCheapestExchange( ocean: Ocean, dataTokenAddress: string -): Promise<{ address?: string; price: string }> { +): Promise { try { const tokenExchanges = await ocean.fixedRateExchange.searchforDT( dataTokenAddress, @@ -51,7 +56,7 @@ export async function getCheapestExchange( if (tokenExchanges === undefined || tokenExchanges.length === 0) { return { address: '', - price: '' + price: 0 } } let cheapestExchangeAddress = tokenExchanges[0].exchangeID @@ -69,34 +74,31 @@ export async function getCheapestExchange( } return { - address: cheapestExchangeAddress, - price: cheapestExchangePrice.toString() + address: cheapestExchangeAddress || '', + price: Number(cheapestExchangePrice) } } catch (err) { Logger.log(err) return { address: '', - price: '' + price: 0 } } } export async function getBestDataTokenPrice( ocean: Ocean, - dataTokenAddress: string, - accountId: string + dataTokenAddress: string ): Promise { const cheapestPool = await getCheapestPool(ocean, dataTokenAddress) const cheapestExchange = await getCheapestExchange(ocean, dataTokenAddress) Decimal.set({ precision: 5 }) const cheapestPoolPrice = new Decimal( - cheapestPool && cheapestPool.price !== '' - ? cheapestPool.price - : 999999999999 + cheapestPool && cheapestPool.price !== 0 ? cheapestPool.price : 999999999999 ) const cheapestExchangePrice = new Decimal( - cheapestExchange && cheapestExchange?.price !== '' + cheapestExchange && cheapestExchange?.price !== 0 ? cheapestExchange.price : 999999999999 ) @@ -105,13 +107,15 @@ export async function getBestDataTokenPrice( return { type: 'pool', address: cheapestPool?.address, - value: cheapestPool?.price + value: cheapestPool?.price, + ocean: cheapestPool?.ocean, + datatoken: cheapestPool?.datatoken } as BestPrice } else { return { type: 'exchange', address: cheapestExchange?.address, - value: cheapestExchange?.price + value: Number(cheapestExchange?.price) } as BestPrice } } @@ -121,18 +125,14 @@ export async function checkAndBuyDT( dataTokenAddress: string, account: Account, config: Config -) { +): Promise { const userOwnedTokens = await ocean.accounts.getTokenBalance( dataTokenAddress, account ) Logger.log(`User has ${userOwnedTokens} tokens`) if (userOwnedTokens === '0') { - const bestPrice = await getBestDataTokenPrice( - ocean, - dataTokenAddress, - account.getId() - ) + const bestPrice = await getBestDataTokenPrice(ocean, dataTokenAddress) switch (bestPrice?.type) { case 'pool': { @@ -152,19 +152,19 @@ export async function checkAndBuyDT( case 'exchange': { if (!config.oceanTokenAddress) { Logger.error(`'oceanTokenAddress' not set in config`) - return null + return } if (!config.fixedRateExchangeAddress) { Logger.error(`'fixedRateExchangeAddress' not set in config`) - return null + return } Logger.log('Buying token from exchange', bestPrice, account.getId()) await ocean.datatokens.approve( config.oceanTokenAddress, config.fixedRateExchangeAddress, - bestPrice.value, + bestPrice.value.toString(), account.getId() ) const exchange = await ocean.fixedRateExchange.buyDT( From efb4b12d71efa12a09d1ce11f1f7471cb4f95509 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Thu, 8 Oct 2020 13:38:00 +0200 Subject: [PATCH 2/2] set price from DDO first, then from chain --- src/hooks/useMetadata/useMetadata.ts | 47 +++++++++++++++++----------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/hooks/useMetadata/useMetadata.ts b/src/hooks/useMetadata/useMetadata.ts index 22515a0..838f948 100644 --- a/src/hooks/useMetadata/useMetadata.ts +++ b/src/hooks/useMetadata/useMetadata.ts @@ -1,7 +1,13 @@ import { useState, useEffect, useCallback } from 'react' -import { DID, DDO, Metadata, Logger, BestPrice } from '@oceanprotocol/lib' +import { + DID, + DDO, + Metadata, + Logger, + BestPrice, + MetadataStore +} from '@oceanprotocol/lib' import { useOcean } from 'providers' -import ProviderStatus from 'providers/OceanProvider/ProviderStatus' import { getBestDataTokenPrice } from 'utils/dtUtils' import { isDDO } from 'utils' @@ -16,7 +22,7 @@ interface UseMetadata { } function useMetadata(asset?: DID | string | DDO): UseMetadata { - const { ocean, status, accountId, networkId } = useOcean() + const { ocean, accountId, networkId, config } = useOcean() const [internalDdo, setDDO] = useState() const [internalDid, setDID] = useState() const [metadata, setMetadata] = useState() @@ -25,11 +31,14 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata { const [price, setPrice] = useState() const getDDO = useCallback( - async (did: DID | string): Promise => { - const ddo = await ocean.metadatastore.retrieveDDO(did) + async (did: DID | string): Promise => { + if (!config.metadataStoreUri) return + + const metadataStore = new MetadataStore(config.metadataStoreUri, Logger) + const ddo = await metadataStore.retrieveDDO(did) return ddo }, - [ocean?.metadatastore] + [config.metadataStoreUri] ) const getPrice = useCallback( @@ -49,11 +58,9 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata { // Get and set DDO based on passed DDO or DID // useEffect(() => { - if (!asset || !ocean || status !== ProviderStatus.CONNECTED) return + if (!asset) return async function init(): Promise { - if (!asset) return - if (isDDO(asset as string | DDO | DID)) { setDDO(asset as DDO) setDID((asset as DDO).id) @@ -66,30 +73,34 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata { } } init() - }, [ocean, status, asset, getDDO]) + }, [asset, getDDO]) // - // Get metadata for stored DDO + // Get metadata & price for stored DDO // useEffect(() => { - if (!accountId) return - async function init(): Promise { if (!internalDdo) return + // Set price from DDO first + setPrice(internalDdo.price) + const metadata = await getMetadata(internalDdo) setMetadata(metadata) setTitle(metadata.main.name) - const price = await getPrice(internalDdo.dataToken) - price && setPrice(price) setIsLoaded(true) + + if (!accountId) return + // Set price again, but from chain + const priceLive = await getPrice(internalDdo.dataToken) + priceLive && internalDdo.price !== priceLive && setPrice(priceLive) } init() const interval = setInterval(async () => { - if (!internalDdo) return - const price = await getPrice(internalDdo.dataToken) - price && setPrice(price) + if (!internalDdo || !accountId) return + const priceLive = await getPrice(internalDdo.dataToken) + priceLive && setPrice(priceLive) }, 10000) return () => {