1
0
mirror of https://github.com/oceanprotocol/react.git synced 2025-02-14 21:10:38 +01:00

Merge pull request #138 from oceanprotocol/feature/price-updates

BestPrice updates
This commit is contained in:
Matthias Kretschmann 2020-10-08 14:22:45 +02:00 committed by GitHub
commit 0a45eb2a6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 64 additions and 62 deletions

6
package-lock.json generated
View File

@ -1521,9 +1521,9 @@
"integrity": "sha512-gJ8qQACJgxOPIrPE0OFQ09iYXBAisOGg56EmelQlsMUgp0yY0DKgBntDP83S/Ho1yBjGygqfxCjQrPH63hh/PA==" "integrity": "sha512-gJ8qQACJgxOPIrPE0OFQ09iYXBAisOGg56EmelQlsMUgp0yY0DKgBntDP83S/Ho1yBjGygqfxCjQrPH63hh/PA=="
}, },
"@oceanprotocol/lib": { "@oceanprotocol/lib": {
"version": "0.5.5", "version": "0.5.6",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.5.5.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.5.6.tgz",
"integrity": "sha512-TJTehUaQnFfNp0dJmw0t15+mpYbTkeF+RX4oc6D5FN7hmlhdvC8kfGf8yeHiqxI2Nb703foFLSSs38MWu/XEpg==", "integrity": "sha512-S8OU/FYjDJCKkx098GDT9LfxmTTe/gA8zv5fVMy7lRG1k5WFDsHHMplqZkU9mUGXg1aDDtt7KbctwxNdt7ZGFg==",
"requires": { "requires": {
"@ethereum-navigator/navigator": "^0.5.0", "@ethereum-navigator/navigator": "^0.5.0",
"@oceanprotocol/contracts": "^0.5.3", "@oceanprotocol/contracts": "^0.5.3",

View File

@ -25,7 +25,7 @@
"dist/" "dist/"
], ],
"dependencies": { "dependencies": {
"@oceanprotocol/lib": "^0.5.5", "@oceanprotocol/lib": "^0.5.6",
"axios": "^0.20.0", "axios": "^0.20.0",
"decimal.js": "^10.2.1", "decimal.js": "^10.2.1",
"web3": "^1.3.0", "web3": "^1.3.0",

View File

@ -1,5 +0,0 @@
export default interface BestPrice {
type: 'pool' | 'exchange'
address: string
value: string
}

View File

@ -1,4 +1,6 @@
export default interface Pool { export default interface Pool {
address: string address: string
price: string price: number
ocean?: number
datatoken?: number
} }

View File

@ -1,3 +1,2 @@
export * from './useMetadata' export * from './useMetadata'
export * from './Pool' export * from './Pool'
export * from './BestPrice'

View File

@ -1,10 +1,15 @@
import { useState, useEffect, useCallback } from 'react' import { useState, useEffect, useCallback } from 'react'
import { DID, DDO, Metadata, Logger } from '@oceanprotocol/lib' import {
DID,
DDO,
Metadata,
Logger,
BestPrice,
MetadataStore
} from '@oceanprotocol/lib'
import { useOcean } from 'providers' import { useOcean } from 'providers'
import ProviderStatus from 'providers/OceanProvider/ProviderStatus'
import { getBestDataTokenPrice } from 'utils/dtUtils' import { getBestDataTokenPrice } from 'utils/dtUtils'
import { isDDO } from 'utils' import { isDDO } from 'utils'
import BestPrice from './BestPrice'
interface UseMetadata { interface UseMetadata {
ddo: DDO | undefined ddo: DDO | undefined
@ -17,7 +22,7 @@ interface UseMetadata {
} }
function useMetadata(asset?: DID | string | DDO): UseMetadata { function useMetadata(asset?: DID | string | DDO): UseMetadata {
const { ocean, status, accountId, networkId } = useOcean() const { ocean, accountId, networkId, config } = useOcean()
const [internalDdo, setDDO] = useState<DDO>() const [internalDdo, setDDO] = useState<DDO>()
const [internalDid, setDID] = useState<DID | string>() const [internalDid, setDID] = useState<DID | string>()
const [metadata, setMetadata] = useState<Metadata>() const [metadata, setMetadata] = useState<Metadata>()
@ -26,23 +31,22 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata {
const [price, setPrice] = useState<BestPrice>() const [price, setPrice] = useState<BestPrice>()
const getDDO = useCallback( const getDDO = useCallback(
async (did: DID | string): Promise<DDO> => { async (did: DID | string): Promise<DDO | undefined> => {
const ddo = await ocean.metadatastore.retrieveDDO(did) if (!config.metadataStoreUri) return
const metadataStore = new MetadataStore(config.metadataStoreUri, Logger)
const ddo = await metadataStore.retrieveDDO(did)
return ddo return ddo
}, },
[ocean?.metadatastore] [config.metadataStoreUri]
) )
const getPrice = useCallback( const getPrice = useCallback(
async (dataTokenAddress: string): Promise<BestPrice> => { async (dataTokenAddress: string): Promise<BestPrice> => {
const price = await getBestDataTokenPrice( const price = await getBestDataTokenPrice(ocean, dataTokenAddress)
ocean,
dataTokenAddress,
accountId
)
return price return price
}, },
[ocean, accountId] [ocean]
) )
const getMetadata = useCallback(async (ddo: DDO): Promise<Metadata> => { const getMetadata = useCallback(async (ddo: DDO): Promise<Metadata> => {
@ -54,11 +58,9 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata {
// Get and set DDO based on passed DDO or DID // Get and set DDO based on passed DDO or DID
// //
useEffect(() => { useEffect(() => {
if (!asset || !ocean || status !== ProviderStatus.CONNECTED) return
async function init(): Promise<void> {
if (!asset) return if (!asset) return
async function init(): Promise<void> {
if (isDDO(asset as string | DDO | DID)) { if (isDDO(asset as string | DDO | DID)) {
setDDO(asset as DDO) setDDO(asset as DDO)
setDID((asset as DDO).id) setDID((asset as DDO).id)
@ -71,30 +73,34 @@ function useMetadata(asset?: DID | string | DDO): UseMetadata {
} }
} }
init() init()
}, [ocean, status, asset, getDDO]) }, [asset, getDDO])
// //
// Get metadata for stored DDO // Get metadata & price for stored DDO
// //
useEffect(() => { useEffect(() => {
if (!accountId) return
async function init(): Promise<void> { async function init(): Promise<void> {
if (!internalDdo) return if (!internalDdo) return
// Set price from DDO first
setPrice(internalDdo.price)
const metadata = await getMetadata(internalDdo) const metadata = await getMetadata(internalDdo)
setMetadata(metadata) setMetadata(metadata)
setTitle(metadata.main.name) setTitle(metadata.main.name)
const price = await getPrice(internalDdo.dataToken)
price && setPrice(price)
setIsLoaded(true) setIsLoaded(true)
if (!accountId) return
// Set price again, but from chain
const priceLive = await getPrice(internalDdo.dataToken)
priceLive && internalDdo.price !== priceLive && setPrice(priceLive)
} }
init() init()
const interval = setInterval(async () => { const interval = setInterval(async () => {
if (!internalDdo) return if (!internalDdo || !accountId) return
const price = await getPrice(internalDdo.dataToken) const priceLive = await getPrice(internalDdo.dataToken)
price && setPrice(price) priceLive && setPrice(priceLive)
}, 10000) }, 10000)
return () => { return () => {

View File

@ -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 { Decimal } from 'decimal.js'
import Pool from 'hooks/useMetadata/Pool' import Pool from 'hooks/useMetadata/Pool'
import BestPrice from 'hooks/useMetadata/BestPrice'
import Web3 from 'web3' import Web3 from 'web3'
export async function getCheapestPool( export async function getCheapestPool(
@ -15,7 +15,7 @@ export async function getCheapestPool(
if (tokenPools === undefined || tokenPools.length === 0) { if (tokenPools === undefined || tokenPools.length === 0) {
return { return {
address: '', address: '',
price: '' price: 0
} }
} }
let cheapestPoolAddress = tokenPools[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 { return {
address: cheapestPoolAddress, address: cheapestPoolAddress,
price: cheapestPoolPrice.toString() price: Number(cheapestPoolPrice),
ocean: Number(oceanReserve),
datatoken: Number(dtReserve)
} }
} }
export async function getCheapestExchange( export async function getCheapestExchange(
ocean: Ocean, ocean: Ocean,
dataTokenAddress: string dataTokenAddress: string
): Promise<{ address?: string; price: string }> { ): Promise<Pool | undefined> {
try { try {
const tokenExchanges = await ocean.fixedRateExchange.searchforDT( const tokenExchanges = await ocean.fixedRateExchange.searchforDT(
dataTokenAddress, dataTokenAddress,
@ -51,7 +56,7 @@ export async function getCheapestExchange(
if (tokenExchanges === undefined || tokenExchanges.length === 0) { if (tokenExchanges === undefined || tokenExchanges.length === 0) {
return { return {
address: '', address: '',
price: '' price: 0
} }
} }
let cheapestExchangeAddress = tokenExchanges[0].exchangeID let cheapestExchangeAddress = tokenExchanges[0].exchangeID
@ -69,34 +74,31 @@ export async function getCheapestExchange(
} }
return { return {
address: cheapestExchangeAddress, address: cheapestExchangeAddress || '',
price: cheapestExchangePrice.toString() price: Number(cheapestExchangePrice)
} }
} catch (err) { } catch (err) {
Logger.log(err) Logger.log(err)
return { return {
address: '', address: '',
price: '' price: 0
} }
} }
} }
export async function getBestDataTokenPrice( export async function getBestDataTokenPrice(
ocean: Ocean, ocean: Ocean,
dataTokenAddress: string, dataTokenAddress: string
accountId: string
): Promise<BestPrice> { ): Promise<BestPrice> {
const cheapestPool = await getCheapestPool(ocean, dataTokenAddress) const cheapestPool = await getCheapestPool(ocean, dataTokenAddress)
const cheapestExchange = await getCheapestExchange(ocean, dataTokenAddress) const cheapestExchange = await getCheapestExchange(ocean, dataTokenAddress)
Decimal.set({ precision: 5 }) Decimal.set({ precision: 5 })
const cheapestPoolPrice = new Decimal( const cheapestPoolPrice = new Decimal(
cheapestPool && cheapestPool.price !== '' cheapestPool && cheapestPool.price !== 0 ? cheapestPool.price : 999999999999
? cheapestPool.price
: 999999999999
) )
const cheapestExchangePrice = new Decimal( const cheapestExchangePrice = new Decimal(
cheapestExchange && cheapestExchange?.price !== '' cheapestExchange && cheapestExchange?.price !== 0
? cheapestExchange.price ? cheapestExchange.price
: 999999999999 : 999999999999
) )
@ -105,13 +107,15 @@ export async function getBestDataTokenPrice(
return { return {
type: 'pool', type: 'pool',
address: cheapestPool?.address, address: cheapestPool?.address,
value: cheapestPool?.price value: cheapestPool?.price,
ocean: cheapestPool?.ocean,
datatoken: cheapestPool?.datatoken
} as BestPrice } as BestPrice
} else { } else {
return { return {
type: 'exchange', type: 'exchange',
address: cheapestExchange?.address, address: cheapestExchange?.address,
value: cheapestExchange?.price value: Number(cheapestExchange?.price)
} as BestPrice } as BestPrice
} }
} }
@ -121,18 +125,14 @@ export async function checkAndBuyDT(
dataTokenAddress: string, dataTokenAddress: string,
account: Account, account: Account,
config: Config config: Config
) { ): Promise<TransactionReceipt | undefined> {
const userOwnedTokens = await ocean.accounts.getTokenBalance( const userOwnedTokens = await ocean.accounts.getTokenBalance(
dataTokenAddress, dataTokenAddress,
account account
) )
Logger.log(`User has ${userOwnedTokens} tokens`) Logger.log(`User has ${userOwnedTokens} tokens`)
if (userOwnedTokens === '0') { if (userOwnedTokens === '0') {
const bestPrice = await getBestDataTokenPrice( const bestPrice = await getBestDataTokenPrice(ocean, dataTokenAddress)
ocean,
dataTokenAddress,
account.getId()
)
switch (bestPrice?.type) { switch (bestPrice?.type) {
case 'pool': { case 'pool': {
@ -152,19 +152,19 @@ export async function checkAndBuyDT(
case 'exchange': { case 'exchange': {
if (!config.oceanTokenAddress) { if (!config.oceanTokenAddress) {
Logger.error(`'oceanTokenAddress' not set in config`) Logger.error(`'oceanTokenAddress' not set in config`)
return null return
} }
if (!config.fixedRateExchangeAddress) { if (!config.fixedRateExchangeAddress) {
Logger.error(`'fixedRateExchangeAddress' not set in config`) Logger.error(`'fixedRateExchangeAddress' not set in config`)
return null return
} }
Logger.log('Buying token from exchange', bestPrice, account.getId()) Logger.log('Buying token from exchange', bestPrice, account.getId())
await ocean.datatokens.approve( await ocean.datatokens.approve(
config.oceanTokenAddress, config.oceanTokenAddress,
config.fixedRateExchangeAddress, config.fixedRateExchangeAddress,
bestPrice.value, bestPrice.value.toString(),
account.getId() account.getId()
) )
const exchange = await ocean.fixedRateExchange.buyDT( const exchange = await ocean.fixedRateExchange.buyDT(