mirror of
https://github.com/oceanprotocol/react.git
synced 2025-01-05 11:25:18 +01:00
Merge pull request #147 from oceanprotocol/feature/flow_splits
split flows for Publish and Buy
This commit is contained in:
commit
83c68ab601
@ -8,6 +8,7 @@ import { AllDdos } from './AllDdos'
|
||||
import { ConsumeDdo } from './ConsumeDdo'
|
||||
import { NetworkMonitor } from './NetworkMonitor'
|
||||
import { LogLevel } from '@oceanprotocol/lib/dist/node/utils'
|
||||
import { Pricing } from './Pricing'
|
||||
|
||||
const configRinkeby = new ConfigHelper().getConfig('rinkeby')
|
||||
const providerOptions = {}
|
||||
@ -39,6 +40,9 @@ function App() {
|
||||
<div>
|
||||
<Publish />
|
||||
</div>
|
||||
<div>
|
||||
<Pricing />
|
||||
</div>
|
||||
<div>
|
||||
<ConsumeDdo />
|
||||
</div>
|
||||
|
57
example/src/Pricing.tsx
Normal file
57
example/src/Pricing.tsx
Normal 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>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
import React from 'react'
|
||||
import { usePublish } 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 Publish() {
|
||||
const { publish, publishStepText, isLoading } = usePublish()
|
||||
const { createPricing, pricingStep, pricingStepText, pricingIsLoading, pricingError} = usePricing()
|
||||
const [ddo, setDdo] = useState<DDO | undefined | null>()
|
||||
|
||||
const asset = {
|
||||
@ -31,18 +31,16 @@ export function Publish() {
|
||||
}
|
||||
|
||||
const publishAsset = async () => {
|
||||
const priceOptions = {
|
||||
price: 7,
|
||||
tokensToMint: 10,
|
||||
type: 'fixed',
|
||||
weightOnDataToken: '',
|
||||
swapFee: ''
|
||||
|
||||
const datatokenOptions = {
|
||||
|
||||
}
|
||||
|
||||
const ddo = await publish(asset as Metadata, priceOptions, 'access')
|
||||
const ddo = await publish(asset as Metadata, 'access', datatokenOptions)
|
||||
console.log(ddo)
|
||||
setDdo(ddo)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>Publish</div>
|
||||
@ -53,6 +51,7 @@ export function Publish() {
|
||||
IsLoading: {isLoading.toString()} || Status: {publishStepText}
|
||||
</div>
|
||||
<div>DID: {ddo && ddo.id} </div>
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -1521,9 +1521,9 @@
|
||||
"integrity": "sha512-LING+GvW37I0L40rZdPCZ1SvcZurDSGGhT0WOVPNO8oyh2C3bXModDBNE4+gCFa8pTbQBOc4ot1/Zoj9PfT/zA=="
|
||||
},
|
||||
"@oceanprotocol/lib": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.6.5.tgz",
|
||||
"integrity": "sha512-GH7ZujwmV997kZT4GJy7cZF0TBitM/RVm+xBLtqpr5qmrP/4Pq38WODbOol3dGEHsyT62qzDTvCGoBYSRSCU1g==",
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.7.0.tgz",
|
||||
"integrity": "sha512-XRQ58wWbohtz/buug0498EbpBchxrPwYBh8f/Iln1Vwh6h3IfLWvznmg4gNg/H1AE3qdPsuVcBJwYb0Bos/yGQ==",
|
||||
"requires": {
|
||||
"@ethereum-navigator/navigator": "^0.5.0",
|
||||
"@oceanprotocol/contracts": "^0.5.6",
|
||||
|
@ -25,7 +25,7 @@
|
||||
"dist/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@oceanprotocol/lib": "^0.6.5",
|
||||
"@oceanprotocol/lib": "^0.7.0",
|
||||
"axios": "^0.20.0",
|
||||
"decimal.js": "^10.2.1",
|
||||
"web3": "^1.3.0",
|
||||
|
@ -2,3 +2,4 @@ export * from './useConsume'
|
||||
export * from './useMetadata'
|
||||
export * from './usePublish'
|
||||
export * from './useCompute'
|
||||
export * from './usePricing'
|
||||
|
@ -4,7 +4,6 @@ import { ComputeValue } from './ComputeOptions'
|
||||
import { Logger, ServiceCompute } from '@oceanprotocol/lib'
|
||||
import { MetadataAlgorithm } from '@oceanprotocol/lib/dist/node/ddo/interfaces/MetadataAlgorithm'
|
||||
import { ComputeJob } from '@oceanprotocol/lib/dist/node/ocean/interfaces/ComputeJob'
|
||||
import { checkAndBuyDT } from 'utils/dtUtils'
|
||||
|
||||
interface UseCompute {
|
||||
compute: (
|
||||
@ -13,7 +12,7 @@ interface UseCompute {
|
||||
dataTokenAddress: string,
|
||||
algorithmRawCode: string,
|
||||
computeContainer: ComputeValue,
|
||||
marketFeeAddress: string
|
||||
marketFeeAddress?: string
|
||||
) => Promise<ComputeJob | void>
|
||||
computeStep?: number
|
||||
computeStepText?: string
|
||||
@ -62,7 +61,7 @@ function useCompute(): UseCompute {
|
||||
dataTokenAddress: string,
|
||||
algorithmRawCode: string,
|
||||
computeContainer: ComputeValue,
|
||||
marketFeeAddress: string
|
||||
marketFeeAddress?: string
|
||||
): Promise<ComputeJob | void> {
|
||||
if (!ocean || !account) return
|
||||
|
||||
@ -72,50 +71,47 @@ function useCompute(): UseCompute {
|
||||
setIsLoading(true)
|
||||
setStep(0)
|
||||
|
||||
await checkAndBuyDT(ocean, dataTokenAddress, account, config)
|
||||
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,
|
||||
const userOwnedTokens = await ocean.accounts.getTokenBalance(
|
||||
dataTokenAddress,
|
||||
account,
|
||||
undefined,
|
||||
rawAlgorithmMeta,
|
||||
output,
|
||||
`${computeService.index}`,
|
||||
computeService.type
|
||||
account
|
||||
)
|
||||
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) {
|
||||
Logger.error(error)
|
||||
setComputeError(error.message)
|
||||
|
@ -9,6 +9,7 @@ import React from 'react'
|
||||
import { useOcean, useConsume } from '@oceanprotocol/react'
|
||||
|
||||
const did = 'did:op:0x000000000'
|
||||
const dtBalance = 20
|
||||
|
||||
export default function MyComponent() {
|
||||
const { accountId } = useOcean()
|
||||
@ -16,10 +17,16 @@ export default function MyComponent() {
|
||||
// Get metadata for this asset
|
||||
const { title, price, ddo } = useMetadata(did)
|
||||
|
||||
// Pricing helpers
|
||||
const { buyDT } = usePricing(ddo)
|
||||
|
||||
// Consume helpers
|
||||
const { consume, consumeStep } = useConsume()
|
||||
|
||||
const hasDatatoken = dtBalance >= 1
|
||||
|
||||
async function handleDownload() {
|
||||
!hasDatatoken && (await buyDT('1'))
|
||||
await consume(did, ddo.dataToken, 'access')
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ import { useState } from 'react'
|
||||
import { useOcean } from 'providers'
|
||||
import { feedback } from 'utils'
|
||||
import { DID, Logger, ServiceType } from '@oceanprotocol/lib'
|
||||
import { checkAndBuyDT } from 'utils/dtUtils'
|
||||
|
||||
interface UseConsume {
|
||||
consume: (
|
||||
@ -26,7 +25,7 @@ export const consumeFeedback: { [key in number]: string } = {
|
||||
}
|
||||
|
||||
function useConsume(): UseConsume {
|
||||
const { ocean, account, accountId, config } = useOcean()
|
||||
const { ocean, account, accountId } = useOcean()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [consumeStep, setConsumeStep] = useState<number | undefined>()
|
||||
const [consumeStepText, setConsumeStepText] = useState<string | undefined>()
|
||||
@ -44,43 +43,40 @@ function useConsume(): UseConsume {
|
||||
marketFeeAddress: string
|
||||
): Promise<void> {
|
||||
if (!ocean || !account || !accountId) return
|
||||
|
||||
setIsLoading(true)
|
||||
setConsumeError(undefined)
|
||||
|
||||
try {
|
||||
setStep(0)
|
||||
await checkAndBuyDT(ocean, dataTokenAddress, account, config)
|
||||
|
||||
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,
|
||||
const userOwnedTokens = await ocean.accounts.getTokenBalance(
|
||||
dataTokenAddress,
|
||||
account,
|
||||
''
|
||||
account
|
||||
)
|
||||
|
||||
setStep(4)
|
||||
if (parseFloat(userOwnedTokens) < 1) {
|
||||
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) {
|
||||
setConsumeError(error.message)
|
||||
Logger.error(error)
|
||||
|
@ -1,6 +1,6 @@
|
||||
export interface PriceOptions {
|
||||
price: number
|
||||
tokensToMint: number
|
||||
dtAmount: number
|
||||
type: 'fixed' | 'dynamic' | string
|
||||
weightOnDataToken: string
|
||||
swapFee: string
|
58
src/hooks/usePricing/README.md
Normal file
58
src/hooks/usePricing/README.md
Normal 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>
|
||||
)
|
||||
}
|
||||
```
|
2
src/hooks/usePricing/index.ts
Normal file
2
src/hooks/usePricing/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './usePricing'
|
||||
export * from './PriceOptions'
|
257
src/hooks/usePricing/usePricing.ts
Normal file
257
src/hooks/usePricing/usePricing.ts
Normal 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
|
39
src/hooks/usePricing/utils.ts
Normal file
39
src/hooks/usePricing/utils.ts
Normal 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.`
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
# `usePublish`
|
||||
|
||||
Publish data sets, and create data tokens and liquidity pools for them.
|
||||
Publish data sets and create datatokens for them.
|
||||
|
||||
## Usage
|
||||
|
||||
@ -10,7 +10,7 @@ import { useOcean, usePublish } from '@oceanprotocol/react'
|
||||
import { Metadata } from '@oceanprotocol/lib'
|
||||
|
||||
export default function MyComponent() {
|
||||
const { accountId } = useOcean()
|
||||
const { ocean, accountId } = useOcean()
|
||||
|
||||
// Publish helpers
|
||||
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() {
|
||||
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 (
|
||||
|
@ -1,3 +1,2 @@
|
||||
export * from './usePublish'
|
||||
export * from './PriceOptions'
|
||||
export * from './DataTokenOptions'
|
||||
|
@ -5,21 +5,19 @@ import {
|
||||
ServiceType
|
||||
} from '@oceanprotocol/lib/dist/node/ddo/interfaces/Service'
|
||||
import { useState } from 'react'
|
||||
import { DataTokenOptions } from '.'
|
||||
import { DataTokenOptions } from './DataTokenOptions'
|
||||
import { useOcean } from 'providers'
|
||||
import ProviderStatus from 'providers/OceanProvider/ProviderStatus'
|
||||
import { publishFeedback } from 'utils'
|
||||
import { PriceOptions } from './PriceOptions'
|
||||
|
||||
interface UsePublish {
|
||||
publish: (
|
||||
asset: Metadata,
|
||||
priceOptions: PriceOptions,
|
||||
serviceConfigs: ServiceType,
|
||||
dataTokenOptions?: DataTokenOptions,
|
||||
timeout?: number,
|
||||
providerUri?: string
|
||||
) => Promise<DDO | undefined | null>
|
||||
mint: (tokenAddress: string, tokensToMint: string) => void
|
||||
publishStep?: number
|
||||
publishStepText?: string
|
||||
publishError?: string
|
||||
@ -27,7 +25,7 @@ interface UsePublish {
|
||||
}
|
||||
|
||||
function usePublish(): UsePublish {
|
||||
const { ocean, status, account, accountId, config } = useOcean()
|
||||
const { ocean, status, account } = useOcean()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const [publishStep, setPublishStep] = useState<number | undefined>()
|
||||
const [publishStepText, setPublishStepText] = useState<string | undefined>()
|
||||
@ -37,50 +35,6 @@ function usePublish(): UsePublish {
|
||||
setPublishStep(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
|
||||
* @param {Metadata} asset The metadata of the asset.
|
||||
@ -91,38 +45,37 @@ function usePublish(): UsePublish {
|
||||
*/
|
||||
async function publish(
|
||||
asset: Metadata,
|
||||
priceOptions: PriceOptions,
|
||||
serviceType: ServiceType,
|
||||
dataTokenOptions?: DataTokenOptions,
|
||||
timeout?: number,
|
||||
providerUri?: string
|
||||
): Promise<DDO | undefined | null> {
|
||||
if (status !== ProviderStatus.CONNECTED || !ocean || !account) return null
|
||||
|
||||
setIsLoading(true)
|
||||
setPublishError(undefined)
|
||||
|
||||
try {
|
||||
const tokensToMint = priceOptions.tokensToMint.toString()
|
||||
|
||||
const publishedDate =
|
||||
new Date(Date.now()).toISOString().split('.')[0] + 'Z'
|
||||
const timeout = 0
|
||||
const services: Service[] = []
|
||||
|
||||
const price = '1'
|
||||
|
||||
switch (serviceType) {
|
||||
case 'access': {
|
||||
if (!timeout) timeout = 0
|
||||
const accessService = await ocean.assets.createAccessServiceAttributes(
|
||||
account,
|
||||
price,
|
||||
publishedDate,
|
||||
timeout
|
||||
timeout,
|
||||
providerUri
|
||||
)
|
||||
Logger.log('access service created', accessService)
|
||||
services.push(accessService)
|
||||
break
|
||||
}
|
||||
case 'compute': {
|
||||
if (!timeout) timeout = 3600
|
||||
const cluster = ocean.compute.createClusterAttributes(
|
||||
'Kubernetes',
|
||||
'http://10.0.0.17/xxx'
|
||||
@ -163,7 +116,9 @@ function usePublish(): UsePublish {
|
||||
price,
|
||||
publishedDate,
|
||||
provider,
|
||||
origComputePrivacy as ServiceComputePrivacy
|
||||
origComputePrivacy as ServiceComputePrivacy,
|
||||
timeout,
|
||||
providerUri
|
||||
)
|
||||
services.push(computeService)
|
||||
break
|
||||
@ -186,11 +141,6 @@ function usePublish(): UsePublish {
|
||||
.next(setStep)
|
||||
Logger.log('ddo created', ddo)
|
||||
setStep(7)
|
||||
await mint(ddo.dataToken, tokensToMint)
|
||||
Logger.log(`minted ${tokensToMint} tokens`)
|
||||
|
||||
await createPricing(priceOptions, ddo.dataToken, tokensToMint)
|
||||
setStep(8)
|
||||
return ddo
|
||||
} catch (error) {
|
||||
setPublishError(error.message)
|
||||
@ -203,7 +153,6 @@ function usePublish(): UsePublish {
|
||||
|
||||
return {
|
||||
publish,
|
||||
mint,
|
||||
publishStep,
|
||||
publishStepText,
|
||||
isLoading,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Logger, Ocean, Account, Config, BestPrice } from '@oceanprotocol/lib'
|
||||
import { TransactionReceipt } from 'web3-core'
|
||||
import { Logger, Ocean, BestPrice } from '@oceanprotocol/lib'
|
||||
import { Decimal } from 'decimal.js'
|
||||
import Pool from 'hooks/useMetadata/Pool'
|
||||
import Web3 from 'web3'
|
||||
@ -146,62 +145,3 @@ export async function getBestDataTokenPrice(
|
||||
} 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,12 +31,11 @@ export const feedback: { [key in number]: string } = {
|
||||
}
|
||||
|
||||
export const publishFeedback: { [key in number]: string } = {
|
||||
0: '1/6 Creating datatoken ...',
|
||||
2: '2/6 Encrypting files ...',
|
||||
4: '3/6 Generating proof ...',
|
||||
6: '4/6 Storing ddo ...',
|
||||
7: '5/6 Minting tokens ...',
|
||||
8: '6/6 Asset published succesfully'
|
||||
0: '1/5 Creating datatoken ...',
|
||||
2: '2/5 Encrypting files ...',
|
||||
4: '3/5 Storing ddo ...',
|
||||
6: '4/5 Minting tokens ...',
|
||||
8: '5/5 Asset published succesfully'
|
||||
}
|
||||
|
||||
export * from './web3'
|
||||
|
@ -14,5 +14,5 @@
|
||||
"importHelpers": true,
|
||||
"strict": true
|
||||
},
|
||||
"include": ["./src/@types", "./src/index.ts"]
|
||||
"include": ["./src/@types", "./src/hooks", "./src/index.ts"]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user