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

Merge pull request #105 from oceanprotocol/feature/fixedPrice

Feature/fixed price
This commit is contained in:
mihaisc 2020-09-07 15:58:13 +03:00 committed by GitHub
commit ef3963c9b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 134 additions and 72 deletions

View File

@ -13,7 +13,7 @@ export function AllDdos() {
useEffect(() => { useEffect(() => {
async function init() { async function init() {
if (ocean === undefined || account === undefined) return if (!ocean || !account) return
const assets = await ocean.assets.query({ const assets = await ocean.assets.query({
page: 1, page: 1,

View File

@ -3,20 +3,11 @@ import './App.css'
import { OceanProvider } from '@oceanprotocol/react' import { OceanProvider } from '@oceanprotocol/react'
import { Wallet } from './Wallet' import { Wallet } from './Wallet'
import { Publish } from './Publish' import { Publish } from './Publish'
// import { Config } from '@oceanprotocol/lib'
import { ConfigHelper } from '@oceanprotocol/lib' import { ConfigHelper } from '@oceanprotocol/lib'
import { AllDdos } from './AllDdos' import { AllDdos } from './AllDdos'
import { ConsumeDdo } from './ConsumeDdo' import { ConsumeDdo } from './ConsumeDdo'
import { NetworkMonitor } from './NetworkMonitor' import { NetworkMonitor } from './NetworkMonitor'
// factory Address needs to be updated each time you deploy the contract on local network
// const config: Config = {
// metadataStoreUri: 'http://aquarius:5000',
// providerUri: 'http://localhost:8030',
// nodeUri: `http://localhost:8545`,
// factoryAddress: '0x2fC1fd21cb222Dc180Ef817dE4c426fd9230b5A5'
// }
const configRinkeby = new ConfigHelper().getConfig('rinkeby') const configRinkeby = new ConfigHelper().getConfig('rinkeby')
const providerOptions = {} const providerOptions = {}
@ -43,11 +34,9 @@ function App() {
<div> <div>
<AllDdos /> <AllDdos />
</div> </div>
<div> <div>
<Publish /> <Publish />
</div> </div>
<div> <div>
<ConsumeDdo /> <ConsumeDdo />
</div> </div>

View File

@ -19,14 +19,14 @@ export function ConsumeDdo() {
}, [ocean]) }, [ocean])
const consumeDid = async () => { const consumeDid = async () => {
if (did === undefined) return if (!did) return
const ddo = await ocean.assets.resolve(did) const ddo = await ocean.assets.resolve(did)
await consume(did, ddo.dataToken, 'access') await consume(did, ddo.dataToken, 'access')
} }
const computeDid = async () => { const computeDid = async () => {
if (did === undefined) return if (!did) return
const ddo = await ocean.assets.resolve(did) const ddo = await ocean.assets.resolve(did)
console.log(ddo) console.log(ddo)
console.log('ocean dt', ocean.datatokens) console.log('ocean dt', ocean.datatokens)

View File

@ -8,20 +8,7 @@ export const NetworkMonitor = () => {
const handleNetworkChanged = useCallback( const handleNetworkChanged = useCallback(
(chainId: number) => { (chainId: number) => {
// const config = getOceanConfig(chainId) const config = new ConfigHelper().getConfigById(chainId)
// temp hack
let network = ''
switch (chainId) {
case 1: {
network = 'mainnet'
break
}
case 4: {
network = 'rinkeby'
break
}
}
const config = new ConfigHelper().getConfig(network)
connect(config) connect(config)
}, },
[connect] [connect]

View File

@ -6,7 +6,6 @@ import { useState } from 'react'
import { Metadata } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Metadata' import { Metadata } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Metadata'
export function Publish() { export function Publish() {
// const { accountId, ocean } = useOcean()
const { publish, publishStepText, isLoading } = usePublish() const { publish, publishStepText, isLoading } = usePublish()
const [ddo, setDdo] = useState<DDO | undefined>() const [ddo, setDdo] = useState<DDO | undefined>()
@ -32,14 +31,16 @@ export function Publish() {
} }
const publishAsset = async () => { const publishAsset = async () => {
const ddo = await publish(asset as Metadata, '90', 'access', '', '') const priceOptions = {
// const pool = ocean.pool.createDTPool( price: 10,
// accountId, tokensToMint: 10,
// ddo.dataToken, type: 'fixed',
// '90', weightOnDataToken: '',
// '9', liquidityProviderFee: ''
// '0.03' }
// )
const ddo = await publish(asset as Metadata, priceOptions, 'access', '', '')
console.log(ddo)
setDdo(ddo) setDdo(ddo)
} }
return ( return (
@ -51,7 +52,6 @@ export function Publish() {
<div> <div>
IsLoading: {isLoading.toString()} || Status: {publishStepText} IsLoading: {isLoading.toString()} || Status: {publishStepText}
</div> </div>
<div>DID: {ddo && ddo.id} </div> <div>DID: {ddo && ddo.id} </div>
</> </>
) )

View File

@ -29,11 +29,9 @@ export function Wallet() {
<div> <div>
<button onClick={conn}>Connect</button> <button onClick={conn}>Connect</button>
</div> </div>
<div> <div>
<button onClick={disc}>Disconnect</button> <button onClick={disc}>Disconnect</button>
</div> </div>
<div>{accountId}</div> <div>{accountId}</div>
</> </>
) )

View File

@ -85,5 +85,8 @@
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
},
"directories": {
"example": "example"
} }
} }

View File

@ -0,0 +1,7 @@
export interface PriceOptions {
price?: number
tokensToMint: number
type: 'fixed' | 'dynamic' | string
weightOnDataToken: string
liquidityProviderFee: string
}

View File

@ -1,5 +0,0 @@
import { ServiceType } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service'
export interface ServiceConfig {
serviceType: ServiceType
cost: string
}

View File

@ -1,2 +1,2 @@
export * from './usePublish' export * from './usePublish'
export * from './ServiceConfig' export * from './PriceOptions'

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from 'react' import { useState } from 'react'
import { DDO, Metadata, DataTokens, Logger } from '@oceanprotocol/lib' import { DDO, Metadata, Logger } from '@oceanprotocol/lib'
import { useOcean } from '../../providers' import { useOcean } from '../../providers'
import ProviderStatus from '../../providers/OceanProvider/ProviderStatus' import ProviderStatus from '../../providers/OceanProvider/ProviderStatus'
import { import {
@ -7,13 +7,13 @@ import {
ServiceComputePrivacy, ServiceComputePrivacy,
ServiceType ServiceType
} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service'
import { ServiceConfig } from './ServiceConfig' import { PriceOptions } from './PriceOptions'
import { publishFeedback } from '../../utils' import { publishFeedback } from '../../utils'
interface UsePublish { interface UsePublish {
publish: ( publish: (
asset: Metadata, asset: Metadata,
tokensToMint: string, priceOptions: PriceOptions,
serviceConfigs: ServiceType, serviceConfigs: ServiceType,
mpAddress: string, mpAddress: string,
mpFee: string mpFee: string
@ -26,7 +26,7 @@ interface UsePublish {
} }
function usePublish(): UsePublish { function usePublish(): UsePublish {
const { ocean, status, account, accountId, config } = useOcean() const { ocean, status, account, accountId } = useOcean()
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [publishStep, setPublishStep] = useState<number | undefined>() const [publishStep, setPublishStep] = useState<number | undefined>()
const [publishStepText, setPublishStepText] = useState<string | undefined>() const [publishStepText, setPublishStepText] = useState<string | undefined>()
@ -40,23 +40,23 @@ function usePublish(): UsePublish {
/** /**
* Publish an asset.It also creates the datatoken, mints tokens and gives the market allowance * Publish an asset.It also creates the datatoken, mints tokens and gives the market allowance
* @param {Metadata} asset The metadata of the asset. * @param {Metadata} asset The metadata of the asset.
* @param {string} tokensToMint Numer of tokens to mint and give allowance to market * @param {PriceOptions} priceOptions : number of tokens to mint, datatoken weight , liquidity fee, type : fixed, dynamic
* @param {ServiceConfig[]} serviceConfigs Desired services of the asset, ex: [{serviceType: 'access', cost:'1'}] * @param {ServiceType} serviceType Desired service type of the asset access or compute
* @param {string} mpAddress The address of the market * @param {string} mpAddress The address of the market
* @param {string} mpFee The fee of the market * @param {string} mpFee The fee of the market
* @return {Promise<DDO>} Returns the newly published ddo * @return {Promise<DDO>} Returns the newly published ddo
*/ */
async function publish( async function publish(
asset: Metadata, asset: Metadata,
tokensToMint: string, priceOptions: PriceOptions,
serviceType: ServiceType, serviceType: ServiceType
mpAddress: string,
mpFee: string
): Promise<DDO> { ): Promise<DDO> {
if (status !== ProviderStatus.CONNECTED || !ocean || !account) return if (status !== ProviderStatus.CONNECTED || !ocean || !account) return
setIsLoading(true) setIsLoading(true)
setPublishError(undefined) setPublishError(undefined)
try { try {
const tokensToMint = priceOptions.tokensToMint.toString()
const publishedDate = const publishedDate =
new Date(Date.now()).toISOString().split('.')[0] + 'Z' new Date(Date.now()).toISOString().split('.')[0] + 'Z'
const timeout = 0 const timeout = 0
@ -132,8 +132,9 @@ function usePublish(): UsePublish {
setStep(7) setStep(7)
await mint(ddo.dataToken, tokensToMint) await mint(ddo.dataToken, tokensToMint)
Logger.log(`minted ${tokensToMint} tokens`) Logger.log(`minted ${tokensToMint} tokens`)
setStep(8)
await createPricing(priceOptions, ddo.dataToken)
setStep(8)
return ddo return ddo
} catch (error) { } catch (error) {
setPublishError(error.message) setPublishError(error.message)
@ -144,6 +145,34 @@ function usePublish(): UsePublish {
} }
} }
async function createPricing(
priceOptions: PriceOptions,
dataTokenAddress: string
) {
switch (priceOptions.type) {
case 'dynamic': {
// weight is hardcoded at 9 (90%) and publisher fee at 0.03(this was a random value set by me)
const pool = await ocean.pool.createDTPool(
accountId,
dataTokenAddress,
priceOptions.tokensToMint.toString(),
priceOptions.weightOnDataToken,
priceOptions.liquidityProviderFee
)
break
}
case 'fixed': {
const fixedPriceExchange = await ocean.fixedRateExchange.create(
dataTokenAddress,
priceOptions.price.toString(),
accountId
)
await ocean.fixedRateExchange.activate(fixedPriceExchange, accountId)
break
}
}
}
async function mint(tokenAddress: string, tokensToMint: string) { async function mint(tokenAddress: string, tokensToMint: string) {
Logger.log('mint function', tokenAddress, accountId) Logger.log('mint function', tokenAddress, accountId)
await ocean.datatokens.mint(tokenAddress, accountId, tokensToMint) await ocean.datatokens.mint(tokenAddress, accountId, tokensToMint)

View File

@ -54,6 +54,48 @@ export async function getBestDataTokenPrice(
return bestPool.price return bestPool.price
} }
export async function getCheapestExchange(
ocean: Ocean,
dataTokenAddress: string
) {
if (!ocean || !dataTokenAddress) return
const tokenExchanges = await ocean.fixedRateExchange.searchforDT(
dataTokenAddress,
'1'
)
Logger.log('Exchanges found', tokenExchanges)
if (tokenExchanges === undefined || tokenExchanges.length === 0) {
return {
address: '',
price: ''
}
}
let cheapestExchangeAddress
let cheapestExchangePrice = new Decimal(999999999999)
if (tokenExchanges) {
for (let i = 0; i < tokenExchanges.length; i++) {
const exchangePrice = tokenExchanges[i].fixedRate
const decimalExchangePrice = new Decimal(exchangePrice)
Logger.log(
'Pool price ',
tokenExchanges[i],
decimalExchangePrice.toString()
)
if (decimalExchangePrice < cheapestExchangePrice) {
cheapestExchangePrice = decimalExchangePrice
cheapestExchangeAddress = tokenExchanges[i]
}
}
}
return {
address: cheapestExchangeAddress,
price: cheapestExchangePrice.toString()
}
}
export async function checkAndBuyDT( export async function checkAndBuyDT(
ocean: Ocean, ocean: Ocean,
@ -65,25 +107,37 @@ export async function checkAndBuyDT(
account account
) )
Logger.log(`User has ${userOwnedTokens} tokens`) Logger.log(`User has ${userOwnedTokens} tokens`)
let cheapestPool
if (userOwnedTokens === '0') { if (userOwnedTokens === '0') {
cheapestPool = await getCheapestPool( const cheapestPool = await getCheapestPool(
ocean, ocean,
account.getId(), account.getId(),
dataTokenAddress dataTokenAddress
) )
const cheapestExchange = await getCheapestExchange(ocean, dataTokenAddress)
Decimal.set({ precision: 5 }) Decimal.set({ precision: 5 })
const price = new Decimal(cheapestPool.price).times(1.05).toString() const cheapestPoolPrice = new Decimal(cheapestPool.price)
const maxPrice = new Decimal(cheapestPool.price).times(2).toString() const cheapestExchangePrice = new Decimal(cheapestExchange.price)
Logger.log('Buying token', cheapestPool, account.getId(), price)
const buyResponse = await ocean.pool.buyDT( if (cheapestExchangePrice > cheapestPoolPrice) {
account.getId(), const price = new Decimal(cheapestPool.price).times(1.05).toString()
cheapestPool.address, const maxPrice = new Decimal(cheapestPool.price).times(2).toString()
'1', Logger.log('Buying token', cheapestPool, account.getId(), price)
price, const buyResponse = await ocean.pool.buyDT(
maxPrice account.getId(),
) cheapestPool.address,
Logger.log('DT buy response', buyResponse) '1',
return buyResponse price,
maxPrice
)
Logger.log('DT buy response', buyResponse)
return buyResponse
} else {
const exchange = await ocean.fixedRateExchange.buyDT(
cheapestExchange.address,
'1',
account.getId()
)
return exchange
}
} }
} }