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

Merge pull request #147 from oceanprotocol/feature/flow_splits

split flows for Publish and Buy
This commit is contained in:
Matthias Kretschmann 2020-10-21 14:26:50 +02:00 committed by GitHub
commit 83c68ab601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 531 additions and 234 deletions

View File

@ -8,6 +8,7 @@ import { AllDdos } from './AllDdos'
import { ConsumeDdo } from './ConsumeDdo' import { ConsumeDdo } from './ConsumeDdo'
import { NetworkMonitor } from './NetworkMonitor' import { NetworkMonitor } from './NetworkMonitor'
import { LogLevel } from '@oceanprotocol/lib/dist/node/utils' import { LogLevel } from '@oceanprotocol/lib/dist/node/utils'
import { Pricing } from './Pricing'
const configRinkeby = new ConfigHelper().getConfig('rinkeby') const configRinkeby = new ConfigHelper().getConfig('rinkeby')
const providerOptions = {} const providerOptions = {}
@ -39,6 +40,9 @@ function App() {
<div> <div>
<Publish /> <Publish />
</div> </div>
<div>
<Pricing />
</div>
<div> <div>
<ConsumeDdo /> <ConsumeDdo />
</div> </div>

57
example/src/Pricing.tsx Normal file
View File

@ -0,0 +1,57 @@
import React from 'react'
import { useOcean, usePricing } from '@oceanprotocol/react'
// import { useOcean, usePublish } from '@oceanprotocol/react'
import { DDO } from '@oceanprotocol/lib'
import { useState } from 'react'
import { Metadata } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Metadata'
export function Trade() {
const { ocean, accountId } = useOcean()
const { createPricing,buyDT,sellDT,mint,pricingStep,pricingStepText,pricingIsLoading, pricingError} = usePricing()
const [datatoken, setDatatoken] = useState<string | undefined>()
const handleBuy = async () => {
const tx = await buyDT(datatoken,'1')
console.log(tx)
}
const handleSell = async () => {
const tx = await buyDT(datatoken,'1')
console.log(tx)
}
const handleChange = (e: any) => {
setDatatoken(e.target.value)
}
const handlePostForSale = async () => {
if(datatoken){
const priceOptions = {
price: 7,
dtAmount: 10,
type: 'fixed',
weightOnDataToken: '',
swapFee: ''
}
const tx = await createPricing(datatoken,priceOptions)
console.log(tx)
}
}
return (
<>
<div>Trade Datatoken</div>
<div>
Datatoken <input onChange={handleChange}></input>
</div>
<div>
<button onClick={handlePostForSale}>Post for sale</button>
</div>
<div>
<button onClick={handleBuy}>Buy 1 DT</button>
</div>
<div>
<button onClick={handleSell}>Sell 1 DT</button>
</div>
<div>
IsLoading: {pricingIsLoading.toString()} || Status: {pricingStepText}
</div>
</>
)
}

View File

@ -1,12 +1,12 @@
import React from 'react' import React from 'react'
import { usePublish } from '@oceanprotocol/react' import { usePublish } from '@oceanprotocol/react'
// import { useOcean, usePublish } from '@oceanprotocol/react'
import { DDO } from '@oceanprotocol/lib' import { DDO } from '@oceanprotocol/lib'
import { useState } from 'react' 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 { publish, publishStepText, isLoading } = usePublish() const { publish, publishStepText, isLoading } = usePublish()
const { createPricing, pricingStep, pricingStepText, pricingIsLoading, pricingError} = usePricing()
const [ddo, setDdo] = useState<DDO | undefined | null>() const [ddo, setDdo] = useState<DDO | undefined | null>()
const asset = { const asset = {
@ -31,18 +31,16 @@ export function Publish() {
} }
const publishAsset = async () => { const publishAsset = async () => {
const priceOptions = {
price: 7, const datatokenOptions = {
tokensToMint: 10,
type: 'fixed',
weightOnDataToken: '',
swapFee: ''
} }
const ddo = await publish(asset as Metadata, 'access', datatokenOptions)
const ddo = await publish(asset as Metadata, priceOptions, 'access')
console.log(ddo) console.log(ddo)
setDdo(ddo) setDdo(ddo)
} }
return ( return (
<> <>
<div>Publish</div> <div>Publish</div>
@ -53,6 +51,7 @@ export function Publish() {
IsLoading: {isLoading.toString()} || Status: {publishStepText} IsLoading: {isLoading.toString()} || Status: {publishStepText}
</div> </div>
<div>DID: {ddo && ddo.id} </div> <div>DID: {ddo && ddo.id} </div>
</> </>
) )
} }

6
package-lock.json generated
View File

@ -1521,9 +1521,9 @@
"integrity": "sha512-LING+GvW37I0L40rZdPCZ1SvcZurDSGGhT0WOVPNO8oyh2C3bXModDBNE4+gCFa8pTbQBOc4ot1/Zoj9PfT/zA==" "integrity": "sha512-LING+GvW37I0L40rZdPCZ1SvcZurDSGGhT0WOVPNO8oyh2C3bXModDBNE4+gCFa8pTbQBOc4ot1/Zoj9PfT/zA=="
}, },
"@oceanprotocol/lib": { "@oceanprotocol/lib": {
"version": "0.6.5", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.6.5.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.7.0.tgz",
"integrity": "sha512-GH7ZujwmV997kZT4GJy7cZF0TBitM/RVm+xBLtqpr5qmrP/4Pq38WODbOol3dGEHsyT62qzDTvCGoBYSRSCU1g==", "integrity": "sha512-XRQ58wWbohtz/buug0498EbpBchxrPwYBh8f/Iln1Vwh6h3IfLWvznmg4gNg/H1AE3qdPsuVcBJwYb0Bos/yGQ==",
"requires": { "requires": {
"@ethereum-navigator/navigator": "^0.5.0", "@ethereum-navigator/navigator": "^0.5.0",
"@oceanprotocol/contracts": "^0.5.6", "@oceanprotocol/contracts": "^0.5.6",

View File

@ -25,7 +25,7 @@
"dist/" "dist/"
], ],
"dependencies": { "dependencies": {
"@oceanprotocol/lib": "^0.6.5", "@oceanprotocol/lib": "^0.7.0",
"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

@ -2,3 +2,4 @@ export * from './useConsume'
export * from './useMetadata' export * from './useMetadata'
export * from './usePublish' export * from './usePublish'
export * from './useCompute' export * from './useCompute'
export * from './usePricing'

View File

@ -4,7 +4,6 @@ import { ComputeValue } from './ComputeOptions'
import { Logger, ServiceCompute } from '@oceanprotocol/lib' import { Logger, ServiceCompute } from '@oceanprotocol/lib'
import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm' import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm'
import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/ComputeJob' import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/ComputeJob'
import { checkAndBuyDT } from 'utils/dtUtils'
interface UseCompute { interface UseCompute {
compute: ( compute: (
@ -13,7 +12,7 @@ interface UseCompute {
dataTokenAddress: string, dataTokenAddress: string,
algorithmRawCode: string, algorithmRawCode: string,
computeContainer: ComputeValue, computeContainer: ComputeValue,
marketFeeAddress: string marketFeeAddress?: string
) => Promise<ComputeJob | void> ) => Promise<ComputeJob | void>
computeStep?: number computeStep?: number
computeStepText?: string computeStepText?: string
@ -62,7 +61,7 @@ function useCompute(): UseCompute {
dataTokenAddress: string, dataTokenAddress: string,
algorithmRawCode: string, algorithmRawCode: string,
computeContainer: ComputeValue, computeContainer: ComputeValue,
marketFeeAddress: string marketFeeAddress?: string
): Promise<ComputeJob | void> { ): Promise<ComputeJob | void> {
if (!ocean || !account) return if (!ocean || !account) return
@ -72,50 +71,47 @@ function useCompute(): UseCompute {
setIsLoading(true) setIsLoading(true)
setStep(0) setStep(0)
await checkAndBuyDT(ocean, dataTokenAddress, account, config) const userOwnedTokens = await ocean.accounts.getTokenBalance(
rawAlgorithmMeta.container = computeContainer
rawAlgorithmMeta.rawcode = algorithmRawCode
const output = {}
Logger.log(
'compute order',
accountId,
did,
computeService,
rawAlgorithmMeta,
marketFeeAddress
)
const tokenTransfer = await ocean.compute.order(
accountId,
did,
computeService.index,
undefined,
rawAlgorithmMeta,
marketFeeAddress
)
setStep(1)
// const computeOrder = JSON.parse(order)
// Logger.log('compute order', computeOrder)
// const tokenTransfer = await ocean.datatokens.transferWei(
// computeOrder.dataToken,
// computeOrder.to,
// String(computeOrder.numTokens),
// computeOrder.from
// )
setStep(2)
const response = await ocean.compute.start(
did,
tokenTransfer,
dataTokenAddress, dataTokenAddress,
account, account
undefined,
rawAlgorithmMeta,
output,
`${computeService.index}`,
computeService.type
) )
return response if (parseFloat(userOwnedTokens) < 1) {
setComputeError('Not enough datatokens')
} else {
rawAlgorithmMeta.container = computeContainer
rawAlgorithmMeta.rawcode = algorithmRawCode
const output = {}
Logger.log(
'compute order',
accountId,
did,
computeService,
rawAlgorithmMeta,
marketFeeAddress
)
const tokenTransfer = await ocean.compute.order(
accountId,
did,
computeService.index,
undefined,
rawAlgorithmMeta,
marketFeeAddress
)
setStep(1)
setStep(2)
const response = await ocean.compute.start(
did,
tokenTransfer,
dataTokenAddress,
account,
undefined,
rawAlgorithmMeta,
output,
`${computeService.index}`,
computeService.type
)
return response
}
} catch (error) { } catch (error) {
Logger.error(error) Logger.error(error)
setComputeError(error.message) setComputeError(error.message)

View File

@ -9,6 +9,7 @@ import React from 'react'
import { useOcean, useConsume } from '@oceanprotocol/react' import { useOcean, useConsume } from '@oceanprotocol/react'
const did = 'did:op:0x000000000' const did = 'did:op:0x000000000'
const dtBalance = 20
export default function MyComponent() { export default function MyComponent() {
const { accountId } = useOcean() const { accountId } = useOcean()
@ -16,10 +17,16 @@ export default function MyComponent() {
// Get metadata for this asset // Get metadata for this asset
const { title, price, ddo } = useMetadata(did) const { title, price, ddo } = useMetadata(did)
// Pricing helpers
const { buyDT } = usePricing(ddo)
// Consume helpers // Consume helpers
const { consume, consumeStep } = useConsume() const { consume, consumeStep } = useConsume()
const hasDatatoken = dtBalance >= 1
async function handleDownload() { async function handleDownload() {
!hasDatatoken && (await buyDT('1'))
await consume(did, ddo.dataToken, 'access') await consume(did, ddo.dataToken, 'access')
} }

View File

@ -2,7 +2,6 @@ import { useState } from 'react'
import { useOcean } from 'providers' import { useOcean } from 'providers'
import { feedback } from 'utils' import { feedback } from 'utils'
import { DID, Logger, ServiceType } from '@oceanprotocol/lib' import { DID, Logger, ServiceType } from '@oceanprotocol/lib'
import { checkAndBuyDT } from 'utils/dtUtils'
interface UseConsume { interface UseConsume {
consume: ( consume: (
@ -26,7 +25,7 @@ export const consumeFeedback: { [key in number]: string } = {
} }
function useConsume(): UseConsume { function useConsume(): UseConsume {
const { ocean, account, accountId, config } = useOcean() const { ocean, account, accountId } = useOcean()
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [consumeStep, setConsumeStep] = useState<number | undefined>() const [consumeStep, setConsumeStep] = useState<number | undefined>()
const [consumeStepText, setConsumeStepText] = useState<string | undefined>() const [consumeStepText, setConsumeStepText] = useState<string | undefined>()
@ -44,43 +43,40 @@ function useConsume(): UseConsume {
marketFeeAddress: string marketFeeAddress: string
): Promise<void> { ): Promise<void> {
if (!ocean || !account || !accountId) return if (!ocean || !account || !accountId) return
setIsLoading(true) setIsLoading(true)
setConsumeError(undefined) setConsumeError(undefined)
try { try {
setStep(0) setStep(0)
await checkAndBuyDT(ocean, dataTokenAddress, account, config) const userOwnedTokens = await ocean.accounts.getTokenBalance(
setStep(1)
const tokenTransfer = await ocean.assets.order(
did as string,
serviceType,
accountId,
undefined,
marketFeeAddress
)
Logger.log('order created', tokenTransfer)
setStep(2)
// const res = JSON.parse(order)
// Logger.log('order parsed', res)
// Logger.log('ocean.datatokens before transfer', ocean.datatokens)
// const tokenTransfer = await ocean.datatokens.transferWei(
// res.dataToken,
// res.to,
// String(res.numTokens),
// res.from
// )
// Logger.log('token transfered', tokenTransfer)
setStep(3)
await ocean.assets.download(
did as string,
tokenTransfer,
dataTokenAddress, dataTokenAddress,
account, account
''
) )
if (parseFloat(userOwnedTokens) < 1) {
setStep(4) setConsumeError('Not enough datatokens')
} else {
setStep(1)
ocean.datatokens.generateDtName()
const tokenTransfer = await ocean.assets.order(
did as string,
serviceType,
accountId,
undefined,
marketFeeAddress
)
Logger.log('order created', tokenTransfer)
setStep(2)
setStep(3)
await ocean.assets.download(
did as string,
tokenTransfer,
dataTokenAddress,
account,
''
)
setStep(4)
}
} catch (error) { } catch (error) {
setConsumeError(error.message) setConsumeError(error.message)
Logger.error(error) Logger.error(error)

View File

@ -1,6 +1,6 @@
export interface PriceOptions { export interface PriceOptions {
price: number price: number
tokensToMint: number dtAmount: number
type: 'fixed' | 'dynamic' | string type: 'fixed' | 'dynamic' | string
weightOnDataToken: string weightOnDataToken: string
swapFee: string swapFee: string

View File

@ -0,0 +1,58 @@
# `usePricing`
Hook with helper utilities to create fixed price exchanges or liquidity pools for your data set, mint datatokens, and buy and sell datatokens.
## Usage
```tsx
import React from 'react'
import { useOcean, useCreatePricing } from '@oceanprotocol/react'
import { Metadata, DDO } from '@oceanprotocol/lib'
export default function MyComponent({ ddo }: { ddo: DDO }) {
const { accountId } = useOcean()
// Pricing helpers
const {
createPricing,
buyDT,
sellDT,
pricingStepText,
pricingError
} = usePricing(ddo)
const priceOptions = {
price: 10,
dtAmount: 10,
type: 'fixed',
weightOnDataToken: '',
swapFee: ''
}
async function handleCreatePricing() {
await createPricing(priceOptions)
}
async function handleMint() {
await mint('1')
}
async function handleBuyDT() {
await buyDT('1')
}
async function handleSellDT() {
await sellDT('1')
}
return (
<div>
<h1>Post for sale</h1>
<p>Your account: {accountId}</p>
<button onClick={handleMint}>Mint DT</button>
<button onClick={handleCreatePricing}>Post for sale</button>
<button onClick={handleBuyDT}>Buy DT</button>
<button onClick={handleSellDT}>Sell DT</button>
</div>
)
}
```

View File

@ -0,0 +1,2 @@
export * from './usePricing'
export * from './PriceOptions'

View File

@ -0,0 +1,257 @@
import { DDO, Logger } from '@oceanprotocol/lib'
import { useEffect, useState } from 'react'
import { useOcean } from 'providers'
import { PriceOptions } from './PriceOptions'
import { TransactionReceipt } from 'web3-core'
import { getBestDataTokenPrice, getFirstPool } from 'utils/dtUtils'
import { Decimal } from 'decimal.js'
import {
getCreatePricingPoolFeedback,
getCreatePricingExchangeFeedback,
getBuyDTFeedback,
getSellDTFeedback
} from './utils'
interface UsePricing {
dtSymbol?: string
dtName?: string
createPricing: (
priceOptions: PriceOptions
) => Promise<TransactionReceipt | string | void>
buyDT: (dtAmount: number | string) => Promise<TransactionReceipt | void>
sellDT: (dtAmount: number | string) => Promise<TransactionReceipt | void>
mint: (tokensToMint: string) => Promise<TransactionReceipt>
pricingStep?: number
pricingStepText?: string
pricingError?: string
pricingIsLoading: boolean
}
function usePricing(ddo: DDO): UsePricing {
const { ocean, accountId, config } = useOcean()
const [pricingIsLoading, setPricingIsLoading] = useState(false)
const [pricingStep, setPricingStep] = useState<number>()
const [pricingStepText, setPricingStepText] = useState<string>()
const [pricingError, setPricingError] = useState<string>()
const [dtSymbol, setDtSymbol] = useState<string>()
const [dtName, setDtName] = useState<string>()
const { dataToken, dataTokenInfo } = ddo
// Get Datatoken info, from DDO first, then from chain
useEffect(() => {
if (!dataToken) return
async function init() {
const dtSymbol = dataTokenInfo
? dataTokenInfo.symbol
: await ocean?.datatokens.getSymbol(dataToken)
setDtSymbol(dtSymbol)
const dtName = dataTokenInfo
? dataTokenInfo.name
: await ocean?.datatokens.getName(dataToken)
setDtName(dtName)
}
init()
}, [ocean, dataToken, dataTokenInfo])
// Helper for setting steps & feedback for all flows
function setStep(index: number, type: 'pool' | 'exchange' | 'buy' | 'sell') {
setPricingStep(index)
if (!dtSymbol) return
let messages
switch (type) {
case 'pool':
messages = getCreatePricingPoolFeedback(dtSymbol)
break
case 'exchange':
messages = getCreatePricingExchangeFeedback(dtSymbol)
break
case 'buy':
messages = getBuyDTFeedback(dtSymbol)
break
case 'sell':
messages = getSellDTFeedback(dtSymbol)
break
}
setPricingStepText(messages[index])
}
async function mint(tokensToMint: string): Promise<TransactionReceipt> {
Logger.log('mint function', dataToken, accountId)
const tx = await ocean.datatokens.mint(dataToken, accountId, tokensToMint)
return tx
}
async function buyDT(
dtAmount: number | string
): Promise<TransactionReceipt | void> {
if (!ocean || !accountId) return
let tx
try {
setPricingIsLoading(true)
setPricingError(undefined)
setStep(1, 'buy')
const bestPrice = await getBestDataTokenPrice(ocean, dataToken)
switch (bestPrice?.type) {
case 'pool': {
const price = new Decimal(bestPrice.value).times(1.05).toString()
const maxPrice = new Decimal(bestPrice.value).times(2).toString()
setStep(2, 'buy')
Logger.log('Buying token from pool', bestPrice, accountId, price)
tx = await ocean.pool.buyDT(
accountId,
bestPrice.address,
String(dtAmount),
price,
maxPrice
)
setStep(3, 'buy')
Logger.log('DT buy response', tx)
break
}
case 'exchange': {
if (!config.oceanTokenAddress) {
Logger.error(`'oceanTokenAddress' not set in config`)
return
}
if (!config.fixedRateExchangeAddress) {
Logger.error(`'fixedRateExchangeAddress' not set in config`)
return
}
Logger.log('Buying token from exchange', bestPrice, accountId)
await ocean.datatokens.approve(
config.oceanTokenAddress,
config.fixedRateExchangeAddress,
`${bestPrice.value}`,
accountId
)
setStep(2, 'buy')
tx = await ocean.fixedRateExchange.buyDT(
bestPrice.address,
`${dtAmount}`,
accountId
)
setStep(3, 'buy')
Logger.log('DT exchange buy response', tx)
break
}
}
} catch (error) {
setPricingError(error.message)
Logger.error(error)
} finally {
setStep(0, 'buy')
setPricingStepText(undefined)
setPricingIsLoading(false)
}
return tx
}
async function sellDT(
dtAmount: number | string
): Promise<TransactionReceipt | void> {
if (!ocean || !accountId) return
if (!config.oceanTokenAddress) {
Logger.error(`'oceanTokenAddress' not set in config`)
return
}
try {
setPricingIsLoading(true)
setPricingError(undefined)
setStep(1, 'sell')
const pool = await getFirstPool(ocean, dataToken)
if (!pool || pool.price === 0) return
const price = new Decimal(pool.price).times(0.95).toString()
setStep(2, 'sell')
Logger.log('Selling token to pool', pool, accountId, price)
const tx = await ocean.pool.sellDT(
accountId,
pool.address,
`${dtAmount}`,
price
)
setStep(3, 'sell')
Logger.log('DT sell response', tx)
return tx
} catch (error) {
setPricingError(error.message)
Logger.error(error)
} finally {
setStep(0, 'sell')
setPricingStepText(undefined)
setPricingIsLoading(false)
}
}
async function createPricing(
priceOptions: PriceOptions
): Promise<TransactionReceipt | void> {
if (!ocean || !accountId || !dtSymbol) return
const { type, dtAmount, price, weightOnDataToken, swapFee } = priceOptions
const isPool = type === 'dynamic'
if (!isPool && !config.fixedRateExchangeAddress) {
Logger.error(`'fixedRateExchangeAddress' not set in ccnfig.`)
return
}
setPricingIsLoading(true)
setPricingError(undefined)
setStep(99, 'pool')
try {
await mint(`${dtAmount}`)
const tx = isPool
? await ocean.pool
.create(
accountId,
dataToken,
`${dtAmount}`,
weightOnDataToken,
swapFee
)
.next((step: number) => setStep(step, 'pool'))
: await ocean.fixedRateExchange
.create(dataToken, `${price}`, accountId)
.next((step: number) => setStep(step, 'exchange'))
return tx
} catch (error) {
setPricingError(error.message)
Logger.error(error)
} finally {
setPricingStep(0)
setPricingStepText(undefined)
setPricingIsLoading(false)
}
}
return {
dtSymbol,
dtName,
createPricing,
buyDT,
sellDT,
mint,
pricingStep,
pricingStepText,
pricingIsLoading,
pricingError
}
}
export { usePricing, UsePricing }
export default usePricing

View File

@ -0,0 +1,39 @@
export function getCreatePricingPoolFeedback(
dtSymbol: string
): { [key: number]: string } {
return {
99: `Minting ${dtSymbol} ...`,
0: 'Creating pool ...',
1: `Approving ${dtSymbol} ...`,
2: 'Approving OCEAN ...',
3: 'Setup pool ...',
4: 'Pool created.'
}
}
export function getCreatePricingExchangeFeedback(
dtSymbol: string
): { [key: number]: string } {
return {
99: `Minting ${dtSymbol} ...`,
0: 'Creating exchange ...',
1: `Approving ${dtSymbol} ...`,
2: 'Fixed exchange created.'
}
}
export function getBuyDTFeedback(dtSymbol: string): { [key: number]: string } {
return {
1: '1/3 Approving OCEAN ...',
2: `2/3 Buying ${dtSymbol} ...`,
3: `3/3 ${dtSymbol} bought.`
}
}
export function getSellDTFeedback(dtSymbol: string): { [key: number]: string } {
return {
1: '1/3 Approving OCEAN ...',
2: `2/3 Selling ${dtSymbol} ...`,
3: `3/3 ${dtSymbol} sold.`
}
}

View File

@ -1,6 +1,6 @@
# `usePublish` # `usePublish`
Publish data sets, and create data tokens and liquidity pools for them. Publish data sets and create datatokens for them.
## Usage ## Usage
@ -10,7 +10,7 @@ import { useOcean, usePublish } from '@oceanprotocol/react'
import { Metadata } from '@oceanprotocol/lib' import { Metadata } from '@oceanprotocol/lib'
export default function MyComponent() { export default function MyComponent() {
const { accountId } = useOcean() const { ocean, accountId } = useOcean()
// Publish helpers // Publish helpers
const { publish, publishStep } = usePublish() const { publish, publishStep } = usePublish()
@ -24,16 +24,10 @@ export default function MyComponent() {
} }
} }
const priceOptions = {
price: 10,
tokensToMint: 10,
type: 'fixed',
weightOnDataToken: '',
swapFee: ''
}
async function handlePublish() { async function handlePublish() {
const ddo = await publish(metadata, priceOptions, 'access') const ddo = await publish(metadata, 'access')
// Heads Up! You should now create pricing for your data set
// with the `usePricing()` hook in another step.
} }
return ( return (

View File

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

View File

@ -5,21 +5,19 @@ import {
ServiceType ServiceType
} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service' } from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service'
import { useState } from 'react' import { useState } from 'react'
import { DataTokenOptions } from '.' import { DataTokenOptions } from './DataTokenOptions'
import { useOcean } from 'providers' import { useOcean } from 'providers'
import ProviderStatus from 'providers/OceanProvider/ProviderStatus' import ProviderStatus from 'providers/OceanProvider/ProviderStatus'
import { publishFeedback } from 'utils' import { publishFeedback } from 'utils'
import { PriceOptions } from './PriceOptions'
interface UsePublish { interface UsePublish {
publish: ( publish: (
asset: Metadata, asset: Metadata,
priceOptions: PriceOptions,
serviceConfigs: ServiceType, serviceConfigs: ServiceType,
dataTokenOptions?: DataTokenOptions, dataTokenOptions?: DataTokenOptions,
timeout?: number,
providerUri?: string providerUri?: string
) => Promise<DDO | undefined | null> ) => Promise<DDO | undefined | null>
mint: (tokenAddress: string, tokensToMint: string) => void
publishStep?: number publishStep?: number
publishStepText?: string publishStepText?: string
publishError?: string publishError?: string
@ -27,7 +25,7 @@ interface UsePublish {
} }
function usePublish(): UsePublish { function usePublish(): UsePublish {
const { ocean, status, account, accountId, config } = useOcean() const { ocean, status, account } = 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>()
@ -37,50 +35,6 @@ function usePublish(): UsePublish {
setPublishStep(index) setPublishStep(index)
index && setPublishStepText(publishFeedback[index]) index && setPublishStepText(publishFeedback[index])
} }
async function mint(tokenAddress: string, tokensToMint: string) {
Logger.log('mint function', tokenAddress, accountId)
await ocean.datatokens.mint(tokenAddress, accountId, tokensToMint)
}
async function createPricing(
priceOptions: PriceOptions,
dataTokenAddress: string,
mintedTokens: string
): Promise<void | null> {
switch (priceOptions.type) {
case 'dynamic': {
await ocean.pool.createDTPool(
accountId,
dataTokenAddress,
priceOptions.tokensToMint.toString(),
priceOptions.weightOnDataToken,
priceOptions.swapFee
)
break
}
case 'fixed': {
if (!config.fixedRateExchangeAddress) {
Logger.error(`'fixedRateExchangeAddress' not set in ccnfig.`)
return null
}
await ocean.fixedRateExchange.create(
dataTokenAddress,
priceOptions.price.toString(),
accountId
)
await ocean.datatokens.approve(
dataTokenAddress,
config.fixedRateExchangeAddress,
mintedTokens,
accountId
)
break
}
}
}
/** /**
* 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.
@ -91,38 +45,37 @@ function usePublish(): UsePublish {
*/ */
async function publish( async function publish(
asset: Metadata, asset: Metadata,
priceOptions: PriceOptions,
serviceType: ServiceType, serviceType: ServiceType,
dataTokenOptions?: DataTokenOptions, dataTokenOptions?: DataTokenOptions,
timeout?: number,
providerUri?: string providerUri?: string
): Promise<DDO | undefined | null> { ): Promise<DDO | undefined | null> {
if (status !== ProviderStatus.CONNECTED || !ocean || !account) return null if (status !== ProviderStatus.CONNECTED || !ocean || !account) return null
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 services: Service[] = [] const services: Service[] = []
const price = '1' const price = '1'
switch (serviceType) { switch (serviceType) {
case 'access': { case 'access': {
if (!timeout) timeout = 0
const accessService = await ocean.assets.createAccessServiceAttributes( const accessService = await ocean.assets.createAccessServiceAttributes(
account, account,
price, price,
publishedDate, publishedDate,
timeout timeout,
providerUri
) )
Logger.log('access service created', accessService) Logger.log('access service created', accessService)
services.push(accessService) services.push(accessService)
break break
} }
case 'compute': { case 'compute': {
if (!timeout) timeout = 3600
const cluster = ocean.compute.createClusterAttributes( const cluster = ocean.compute.createClusterAttributes(
'Kubernetes', 'Kubernetes',
'http://10.0.0.17/xxx' 'http://10.0.0.17/xxx'
@ -163,7 +116,9 @@ function usePublish(): UsePublish {
price, price,
publishedDate, publishedDate,
provider, provider,
origComputePrivacy as ServiceComputePrivacy origComputePrivacy as ServiceComputePrivacy,
timeout,
providerUri
) )
services.push(computeService) services.push(computeService)
break break
@ -186,11 +141,6 @@ function usePublish(): UsePublish {
.next(setStep) .next(setStep)
Logger.log('ddo created', ddo) Logger.log('ddo created', ddo)
setStep(7) setStep(7)
await mint(ddo.dataToken, tokensToMint)
Logger.log(`minted ${tokensToMint} tokens`)
await createPricing(priceOptions, ddo.dataToken, tokensToMint)
setStep(8)
return ddo return ddo
} catch (error) { } catch (error) {
setPublishError(error.message) setPublishError(error.message)
@ -203,7 +153,6 @@ function usePublish(): UsePublish {
return { return {
publish, publish,
mint,
publishStep, publishStep,
publishStepText, publishStepText,
isLoading, isLoading,

View File

@ -1,5 +1,4 @@
import { Logger, Ocean, Account, Config, BestPrice } from '@oceanprotocol/lib' import { Logger, Ocean, 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 Web3 from 'web3' import Web3 from 'web3'
@ -146,62 +145,3 @@ export async function getBestDataTokenPrice(
} as BestPrice } as BestPrice
} }
} }
export async function checkAndBuyDT(
ocean: Ocean,
dataTokenAddress: string,
account: Account,
config: Config
): Promise<TransactionReceipt | undefined> {
const userOwnedTokens = await ocean.accounts.getTokenBalance(
dataTokenAddress,
account
)
Logger.log(`User has ${userOwnedTokens} tokens`)
if (userOwnedTokens === '0') {
const bestPrice = await getBestDataTokenPrice(ocean, dataTokenAddress)
switch (bestPrice?.type) {
case 'pool': {
const price = new Decimal(bestPrice.value).times(1.05).toString()
const maxPrice = new Decimal(bestPrice.value).times(2).toString()
Logger.log('Buying token from pool', bestPrice, account.getId(), price)
const buyResponse = await ocean.pool.buyDT(
account.getId(),
bestPrice.address,
'1',
price,
maxPrice
)
Logger.log('DT buy response', buyResponse)
return buyResponse
}
case 'exchange': {
if (!config.oceanTokenAddress) {
Logger.error(`'oceanTokenAddress' not set in config`)
return
}
if (!config.fixedRateExchangeAddress) {
Logger.error(`'fixedRateExchangeAddress' not set in config`)
return
}
Logger.log('Buying token from exchange', bestPrice, account.getId())
await ocean.datatokens.approve(
config.oceanTokenAddress,
config.fixedRateExchangeAddress,
bestPrice.value.toString(),
account.getId()
)
const exchange = await ocean.fixedRateExchange.buyDT(
bestPrice.address,
'1',
account.getId()
)
Logger.log('DT exchange buy response', exchange)
return exchange
}
}
}
}

View File

@ -31,12 +31,11 @@ export const feedback: { [key in number]: string } = {
} }
export const publishFeedback: { [key in number]: string } = { export const publishFeedback: { [key in number]: string } = {
0: '1/6 Creating datatoken ...', 0: '1/5 Creating datatoken ...',
2: '2/6 Encrypting files ...', 2: '2/5 Encrypting files ...',
4: '3/6 Generating proof ...', 4: '3/5 Storing ddo ...',
6: '4/6 Storing ddo ...', 6: '4/5 Minting tokens ...',
7: '5/6 Minting tokens ...', 8: '5/5 Asset published succesfully'
8: '6/6 Asset published succesfully'
} }
export * from './web3' export * from './web3'

View File

@ -14,5 +14,5 @@
"importHelpers": true, "importHelpers": true,
"strict": true "strict": true
}, },
"include": ["./src/@types", "./src/index.ts"] "include": ["./src/@types", "./src/hooks", "./src/index.ts"]
} }