mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Restore order (#1068)
* minor refactors * minor refactors * fixes * buy dt * consumePrice + estimation * various fixes * cleanup * fix build * fix ssh issue * feedback * build fix * ssh fix * remove console.log * suggested fixes * other fixes * switch to decimal * more fixes * more fixes * fix * some fee refactors * more fee refactoring * lib update, fre rename Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * minor refactors Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * build fixes Signed-off-by: mihaisc <mihai.scarlat@smartcontrol.ro> * update + more refactoring * calc price * fix build * restore accountId in effect * fix order * fix build and update lib * fix order index * fix comments * pool fix * remove console.log * fix order fixed rate exchange * fixed free order and messaging * add comment * minor type fix * more type fixes
This commit is contained in:
parent
4576151e0c
commit
8d1782a800
@ -1,6 +1,15 @@
|
|||||||
|
|
||||||
#NEXT_PUBLIC_INFURA_PROJECT_ID="xxx"
|
#NEXT_PUBLIC_INFURA_PROJECT_ID="xxx"
|
||||||
#NEXT_PUBLIC_MARKET_FEE_ADDRESS="0xxx"
|
#NEXT_PUBLIC_MARKET_FEE_ADDRESS="0xxx"
|
||||||
|
#NEXT_PUBLIC_PUBLISHER_MARKET_ORDER_FEE="1"
|
||||||
|
#NEXT_PUBLIC_PUBLISHER_MARKET_POOL_SWAP_FEE="1"
|
||||||
|
#NEXT_PUBLIC_PUBLISHER_MARKET_FIXED_SWAP_FEE="1"
|
||||||
|
#NEXT_PUBLIC_CONSUME_MARKET_ORDER_FEE="1"
|
||||||
|
#NEXT_PUBLIC_CONSUME_MARKET_POOL_SWAP_FEE="1"
|
||||||
|
#NEXT_PUBLIC_CONSUME_MARKET_FIXED_SWAP_FEE="1"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#NEXT_PUBLIC_PORTIS_ID="xxx"
|
#NEXT_PUBLIC_PORTIS_ID="xxx"
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,6 +22,25 @@ module.exports = {
|
|||||||
marketFeeAddress:
|
marketFeeAddress:
|
||||||
process.env.NEXT_PUBLIC_MARKET_FEE_ADDRESS ||
|
process.env.NEXT_PUBLIC_MARKET_FEE_ADDRESS ||
|
||||||
'0x9984b2453eC7D99a73A5B3a46Da81f197B753C8d',
|
'0x9984b2453eC7D99a73A5B3a46Da81f197B753C8d',
|
||||||
|
// publisher market fee that is taken upon ordering an asset, it is an absolute value, it is declared on erc20 creation
|
||||||
|
publisherMarketOrderFee:
|
||||||
|
process.env.NEXT_PUBLIC_PUBLISHER_MARKET_ORDER_FEE || '0',
|
||||||
|
// fee recieved by the publisher market when a dt is swaped from a pool, percent
|
||||||
|
publisherMarketPoolSwapFee:
|
||||||
|
process.env.NEXT_PUBLIC_PUBLISHER_MARKET_POOL_SWAP_FEE || '0',
|
||||||
|
// fee recieved by the publisher market when a dt is bought from a fixed rate exchange, percent
|
||||||
|
publisherMarketFixedSwapFee:
|
||||||
|
process.env.NEXT_PUBLIC_PUBLISHER_MARKET_FIXED_SWAP_FEE || '0',
|
||||||
|
|
||||||
|
// consume market fee that is taken upon ordering an asset, it is an absolute value, it is specified on order
|
||||||
|
consumeMarketOrderFee:
|
||||||
|
process.env.NEXT_PUBLIC_CONSUME_MARKET_ORDER_FEE || '0',
|
||||||
|
// fee recieved by the consume market when a dt is swaped from a pool, percent
|
||||||
|
consumeMarketPoolSwapFee:
|
||||||
|
process.env.NEXT_PUBLIC_CONSUME_MARKET_POOL_SWAP_FEE || '0',
|
||||||
|
// fee recieved by the consume market when a dt is bought from a fixed rate exchange, percent
|
||||||
|
consumeMarketFixedSwapFee:
|
||||||
|
process.env.NEXT_PUBLIC_CONSUME_MARKET_FIXED_SWAP_FEE || '0',
|
||||||
|
|
||||||
// Used for conversion display, can be whatever coingecko API supports
|
// Used for conversion display, can be whatever coingecko API supports
|
||||||
// see: https://api.coingecko.com/api/v3/simple/supported_vs_currencies
|
// see: https://api.coingecko.com/api/v3/simple/supported_vs_currencies
|
||||||
|
@ -17,24 +17,35 @@ module.exports = (phase, { defaultConfig }) => {
|
|||||||
type: 'asset/resource'
|
type: 'asset/resource'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// for old ocean.js, most likely can be removed later on
|
// for old ocean.js, most likely can be removed later on
|
||||||
config.plugins.push(
|
config.plugins.push(
|
||||||
new options.webpack.IgnorePlugin({
|
new options.webpack.IgnorePlugin({
|
||||||
resourceRegExp: /^electron$/
|
resourceRegExp: /^electron$/
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
const fallback = config.resolve.fallback || {}
|
||||||
config.resolve.fallback = {
|
Object.assign(fallback, {
|
||||||
|
// crypto: require.resolve('crypto-browserify'),
|
||||||
|
// stream: require.resolve('stream-browserify'),
|
||||||
|
// assert: require.resolve('assert'),
|
||||||
|
// os: require.resolve('os-browserify'),
|
||||||
|
// url: require.resolve('url'),
|
||||||
|
http: require.resolve('stream-http'),
|
||||||
|
https: require.resolve('https-browserify'),
|
||||||
fs: false,
|
fs: false,
|
||||||
crypto: false,
|
crypto: false,
|
||||||
os: false,
|
os: false,
|
||||||
stream: false,
|
stream: false,
|
||||||
http: false,
|
|
||||||
https: false,
|
|
||||||
assert: false
|
assert: false
|
||||||
}
|
})
|
||||||
|
config.resolve.fallback = fallback
|
||||||
|
|
||||||
|
config.plugins = (config.plugins || []).concat([
|
||||||
|
new options.webpack.ProvidePlugin({
|
||||||
|
process: 'process/browser',
|
||||||
|
Buffer: ['buffer', 'Buffer']
|
||||||
|
})
|
||||||
|
])
|
||||||
return typeof defaultConfig.webpack === 'function'
|
return typeof defaultConfig.webpack === 'function'
|
||||||
? defaultConfig.webpack(config, options)
|
? defaultConfig.webpack(config, options)
|
||||||
: config
|
: config
|
||||||
|
17
package-lock.json
generated
17
package-lock.json
generated
@ -13,7 +13,7 @@
|
|||||||
"@coingecko/cryptoformat": "^0.4.4",
|
"@coingecko/cryptoformat": "^0.4.4",
|
||||||
"@loadable/component": "^5.15.2",
|
"@loadable/component": "^5.15.2",
|
||||||
"@oceanprotocol/art": "^3.2.0",
|
"@oceanprotocol/art": "^3.2.0",
|
||||||
"@oceanprotocol/lib": "^1.0.0-next.14",
|
"@oceanprotocol/lib": "^1.0.0-next.17",
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
"@portis/web3": "^4.0.6",
|
"@portis/web3": "^4.0.6",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
@ -86,10 +86,13 @@
|
|||||||
"eslint-plugin-react": "^7.28.0",
|
"eslint-plugin-react": "^7.28.0",
|
||||||
"eslint-plugin-react-hooks": "^4.3.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
|
"https-browserify": "^1.0.0",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
|
"process": "^0.11.10",
|
||||||
"serve": "^13.0.2",
|
"serve": "^13.0.2",
|
||||||
|
"stream-http": "^2.8.3",
|
||||||
"typescript": "^4.5.4"
|
"typescript": "^4.5.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -3453,9 +3456,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@oceanprotocol/lib": {
|
"node_modules/@oceanprotocol/lib": {
|
||||||
"version": "1.0.0-next.14",
|
"version": "1.0.0-next.17",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.14.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.17.tgz",
|
||||||
"integrity": "sha512-qz41c6LlvfELvz9oTJncIsZ/cZudEzq2gjCgI4E3iQfo71qB7jzwPd6oqiqIYHmRHl8J/F6QXe9fQsp81R4TIg==",
|
"integrity": "sha512-qZQ2nWe/qNN/2M9YZEacwHSMyStwFoN6gXKDCw17G9E8QLwl3v5z54WjAqLlGOpNnGKMIvkrj4gUpUAMtjLSxw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@oceanprotocol/contracts": "1.0.0-alpha.18",
|
"@oceanprotocol/contracts": "1.0.0-alpha.18",
|
||||||
"bignumber.js": "^9.0.2",
|
"bignumber.js": "^9.0.2",
|
||||||
@ -30132,9 +30135,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@oceanprotocol/lib": {
|
"@oceanprotocol/lib": {
|
||||||
"version": "1.0.0-next.14",
|
"version": "1.0.0-next.17",
|
||||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.14.tgz",
|
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.17.tgz",
|
||||||
"integrity": "sha512-qz41c6LlvfELvz9oTJncIsZ/cZudEzq2gjCgI4E3iQfo71qB7jzwPd6oqiqIYHmRHl8J/F6QXe9fQsp81R4TIg==",
|
"integrity": "sha512-qZQ2nWe/qNN/2M9YZEacwHSMyStwFoN6gXKDCw17G9E8QLwl3v5z54WjAqLlGOpNnGKMIvkrj4gUpUAMtjLSxw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@oceanprotocol/contracts": "1.0.0-alpha.18",
|
"@oceanprotocol/contracts": "1.0.0-alpha.18",
|
||||||
"bignumber.js": "^9.0.2",
|
"bignumber.js": "^9.0.2",
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"@coingecko/cryptoformat": "^0.4.4",
|
"@coingecko/cryptoformat": "^0.4.4",
|
||||||
"@loadable/component": "^5.15.2",
|
"@loadable/component": "^5.15.2",
|
||||||
"@oceanprotocol/art": "^3.2.0",
|
"@oceanprotocol/art": "^3.2.0",
|
||||||
"@oceanprotocol/lib": "^1.0.0-next.14",
|
"@oceanprotocol/lib": "^1.0.0-next.17",
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
"@portis/web3": "^4.0.6",
|
"@portis/web3": "^4.0.6",
|
||||||
"@tippyjs/react": "^4.2.6",
|
"@tippyjs/react": "^4.2.6",
|
||||||
@ -94,10 +94,13 @@
|
|||||||
"eslint-plugin-react": "^7.28.0",
|
"eslint-plugin-react": "^7.28.0",
|
||||||
"eslint-plugin-react-hooks": "^4.3.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
|
"https-browserify": "^1.0.0",
|
||||||
"husky": "^7.0.4",
|
"husky": "^7.0.4",
|
||||||
"prettier": "^2.5.1",
|
"prettier": "^2.5.1",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
|
"process": "^0.11.10",
|
||||||
"serve": "^13.0.2",
|
"serve": "^13.0.2",
|
||||||
|
"stream-http": "^2.8.3",
|
||||||
"typescript": "^4.5.4"
|
"typescript": "^4.5.4"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -95,7 +95,6 @@ function AssetProvider({
|
|||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
const fetchAccessDetails = useCallback(async (): Promise<void> => {
|
const fetchAccessDetails = useCallback(async (): Promise<void> => {
|
||||||
if (!asset?.chainId || !asset?.services) return
|
if (!asset?.chainId || !asset?.services) return
|
||||||
|
|
||||||
const accessDetails = await getAccessDetails(
|
const accessDetails = await getAccessDetails(
|
||||||
asset.chainId,
|
asset.chainId,
|
||||||
asset.services[0].datatokenAddress,
|
asset.services[0].datatokenAddress,
|
||||||
|
@ -30,7 +30,8 @@ const initialPoolInfo: Partial<PoolInfo> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initialPoolInfoUser: Partial<PoolInfoUser> = {
|
const initialPoolInfoUser: Partial<PoolInfoUser> = {
|
||||||
liquidity: new Decimal(0)
|
liquidity: new Decimal(0),
|
||||||
|
poolShares: '0'
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialPoolInfoCreator: Partial<PoolInfoUser> = initialPoolInfoUser
|
const initialPoolInfoCreator: Partial<PoolInfoUser> = initialPoolInfoUser
|
||||||
@ -68,7 +69,7 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
|||||||
setPoolData(response.poolData)
|
setPoolData(response.poolData)
|
||||||
setPoolInfoUser((prevState) => ({
|
setPoolInfoUser((prevState) => ({
|
||||||
...prevState,
|
...prevState,
|
||||||
poolShares: response.poolDataUser?.shares[0]?.shares
|
poolShares: response.poolDataUser?.shares[0]?.shares || '0'
|
||||||
}))
|
}))
|
||||||
setPoolSnapshots(response.poolSnapshots)
|
setPoolSnapshots(response.poolSnapshots)
|
||||||
LoggerInstance.log('[pool] Fetched pool data:', response.poolData)
|
LoggerInstance.log('[pool] Fetched pool data:', response.poolData)
|
||||||
@ -193,10 +194,10 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
|||||||
!poolData ||
|
!poolData ||
|
||||||
!poolInfo?.totalPoolTokens ||
|
!poolInfo?.totalPoolTokens ||
|
||||||
!asset?.chainId ||
|
!asset?.chainId ||
|
||||||
!accountId
|
!accountId ||
|
||||||
|
!poolInfoUser
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
// Staking bot receives half the pool shares so for display purposes
|
// Staking bot receives half the pool shares so for display purposes
|
||||||
// we can multiply by 2 as we have a hardcoded 50/50 pool weight.
|
// we can multiply by 2 as we have a hardcoded 50/50 pool weight.
|
||||||
const userPoolShares = new Decimal(poolInfoUser.poolShares || 0)
|
const userPoolShares = new Decimal(poolInfoUser.poolShares || 0)
|
||||||
@ -237,6 +238,8 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
|
|||||||
poolShares: userPoolShares,
|
poolShares: userPoolShares,
|
||||||
...newPoolInfoUser
|
...newPoolInfoUser
|
||||||
})
|
})
|
||||||
|
// poolInfoUser was not added on purpose, we use setPoolInfoUser so it will just loop
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [
|
}, [
|
||||||
poolData,
|
poolData,
|
||||||
poolInfoUser?.poolShares,
|
poolInfoUser?.poolShares,
|
||||||
|
@ -1,159 +0,0 @@
|
|||||||
import { useState } from 'react'
|
|
||||||
import { consumeFeedback } from '@utils/feedback'
|
|
||||||
import {
|
|
||||||
approve,
|
|
||||||
Datatoken,
|
|
||||||
FreOrderParams,
|
|
||||||
LoggerInstance,
|
|
||||||
OrderParams,
|
|
||||||
Pool,
|
|
||||||
ProviderFees,
|
|
||||||
ProviderInstance,
|
|
||||||
signHash,
|
|
||||||
ZERO_ADDRESS
|
|
||||||
} from '@oceanprotocol/lib'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
import { getOceanConfig } from '@utils/ocean'
|
|
||||||
|
|
||||||
interface UseConsume {
|
|
||||||
consume: (
|
|
||||||
did: string,
|
|
||||||
dataTokenAddress: string,
|
|
||||||
serviceType: string,
|
|
||||||
marketFeeAddress: string,
|
|
||||||
orderId?: string
|
|
||||||
) => Promise<string>
|
|
||||||
consumeStep?: number
|
|
||||||
consumeStepText?: string
|
|
||||||
consumeError?: string
|
|
||||||
isLoading: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
function useConsume(): UseConsume {
|
|
||||||
const { accountId, web3, chainId } = useWeb3()
|
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
|
||||||
const [consumeStep, setConsumeStep] = useState<number | undefined>()
|
|
||||||
const [consumeStepText, setConsumeStepText] = useState<string | undefined>()
|
|
||||||
const [consumeError, setConsumeError] = useState<string | undefined>()
|
|
||||||
|
|
||||||
function setStep(index: number) {
|
|
||||||
setConsumeStep(index)
|
|
||||||
setConsumeStepText(consumeFeedback[index])
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this will be done in another PR
|
|
||||||
async function consume(
|
|
||||||
did: string,
|
|
||||||
datatokenAddress: string,
|
|
||||||
serviceType = 'access',
|
|
||||||
marketFeeAddress: string,
|
|
||||||
orderId?: string
|
|
||||||
): Promise<string> {
|
|
||||||
if (!accountId) return
|
|
||||||
|
|
||||||
setIsLoading(true)
|
|
||||||
setConsumeError(undefined)
|
|
||||||
|
|
||||||
try {
|
|
||||||
setStep(0)
|
|
||||||
if (!orderId) {
|
|
||||||
const datatoken = new Datatoken(web3)
|
|
||||||
// if we don't have a previous valid order, get one
|
|
||||||
const userOwnedTokens = await datatoken.balance(
|
|
||||||
datatokenAddress,
|
|
||||||
accountId
|
|
||||||
)
|
|
||||||
|
|
||||||
setStep(1)
|
|
||||||
try {
|
|
||||||
const config = getOceanConfig(chainId)
|
|
||||||
// const txApprove = await approve(
|
|
||||||
// web3,
|
|
||||||
// accountId,
|
|
||||||
// config.oceanTokenAddress,
|
|
||||||
// accountId,
|
|
||||||
// '1',
|
|
||||||
// false
|
|
||||||
// )
|
|
||||||
// console.log('approve tx', txApprove)
|
|
||||||
|
|
||||||
// const txApprove1 = await approve(
|
|
||||||
// web3,
|
|
||||||
// accountId,
|
|
||||||
// config.oceanTokenAddress,
|
|
||||||
// datatokenAddress,
|
|
||||||
// '1',
|
|
||||||
// false
|
|
||||||
// )
|
|
||||||
// console.log('approve tx', txApprove1)
|
|
||||||
|
|
||||||
// diference between timeout and validUntil?
|
|
||||||
const initializeData = await ProviderInstance.initialize(
|
|
||||||
did,
|
|
||||||
'fca052c239a62523be30ab8ee70c4046867f6cd89f228185fe2996ded3d23c3c',
|
|
||||||
0,
|
|
||||||
accountId,
|
|
||||||
'https://providerv4.rinkeby.oceanprotocol.com'
|
|
||||||
)
|
|
||||||
const orderParams = {
|
|
||||||
consumer: accountId,
|
|
||||||
serviceIndex: 1,
|
|
||||||
_providerFees: initializeData.providerFee
|
|
||||||
} as OrderParams
|
|
||||||
const freParams = {
|
|
||||||
exchangeContract: config.fixedRateExchangeAddress,
|
|
||||||
exchangeId:
|
|
||||||
'0x7ac824fef114255e5e3521a161ef692ec32003916fb6f3fe985cb74790d053ca',
|
|
||||||
maxBaseTokenAmount: web3.utils.toWei('2'),
|
|
||||||
swapMarketFee: web3.utils.toWei('0'),
|
|
||||||
marketFeeAddress: ZERO_ADDRESS
|
|
||||||
} as FreOrderParams
|
|
||||||
|
|
||||||
const esttx = await datatoken.estGasBuyFromFreAndOrder(
|
|
||||||
datatokenAddress,
|
|
||||||
accountId,
|
|
||||||
orderParams,
|
|
||||||
freParams
|
|
||||||
)
|
|
||||||
const tx = await datatoken.buyFromFreAndOrder(
|
|
||||||
datatokenAddress,
|
|
||||||
accountId,
|
|
||||||
orderParams,
|
|
||||||
freParams
|
|
||||||
)
|
|
||||||
|
|
||||||
LoggerInstance.log('ordercreated', orderId)
|
|
||||||
setStep(2)
|
|
||||||
} catch (error) {
|
|
||||||
setConsumeError(error.message)
|
|
||||||
return error.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setStep(3)
|
|
||||||
if (orderId)
|
|
||||||
// await ocean.assets.download(
|
|
||||||
// did as string,
|
|
||||||
// orderId,
|
|
||||||
// dataTokenAddress,
|
|
||||||
// account,
|
|
||||||
// ''
|
|
||||||
// )
|
|
||||||
setStep(4)
|
|
||||||
} catch (error) {
|
|
||||||
setConsumeError(error.message)
|
|
||||||
LoggerInstance.error(error)
|
|
||||||
return error.message
|
|
||||||
} finally {
|
|
||||||
setConsumeStep(undefined)
|
|
||||||
setConsumeStepText(undefined)
|
|
||||||
setIsLoading(false)
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
return { consume, consumeStep, consumeStepText, consumeError, isLoading }
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useConsume }
|
|
||||||
export default useConsume
|
|
@ -1,244 +0,0 @@
|
|||||||
import { Asset, Config, LoggerInstance } from '@oceanprotocol/lib'
|
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
import { TransactionReceipt } from 'web3-core'
|
|
||||||
import { Decimal } from 'decimal.js'
|
|
||||||
import {
|
|
||||||
getCreatePricingPoolFeedback,
|
|
||||||
getCreatePricingExchangeFeedback,
|
|
||||||
getBuyDTFeedback,
|
|
||||||
getCreateFreePricingFeedback,
|
|
||||||
getDispenseFeedback
|
|
||||||
} from '@utils/feedback'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
import { getOceanConfig } from '@utils/ocean'
|
|
||||||
|
|
||||||
interface UsePricing {
|
|
||||||
getDTSymbol: (ddo: Asset) => Promise<string>
|
|
||||||
getDTName: (ddo: Asset) => Promise<string>
|
|
||||||
mint: (tokensToMint: string, ddo: Asset) => Promise<TransactionReceipt | void>
|
|
||||||
buyDT: (
|
|
||||||
amountDataToken: number | string,
|
|
||||||
accessDetails: AccessDetails,
|
|
||||||
ddo: Asset
|
|
||||||
) => Promise<TransactionReceipt | void>
|
|
||||||
pricingStep?: number
|
|
||||||
pricingStepText?: string
|
|
||||||
pricingError?: string
|
|
||||||
pricingIsLoading: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
function usePricing(): UsePricing {
|
|
||||||
const { accountId, networkId } = useWeb3()
|
|
||||||
const [pricingIsLoading, setPricingIsLoading] = useState(false)
|
|
||||||
const [pricingStep, setPricingStep] = useState<number>()
|
|
||||||
const [pricingStepText, setPricingStepText] = useState<string>()
|
|
||||||
const [pricingError, setPricingError] = useState<string>()
|
|
||||||
const [oceanConfig, setOceanConfig] = useState<Config>()
|
|
||||||
|
|
||||||
// Grab ocen config based on passed networkId
|
|
||||||
useEffect(() => {
|
|
||||||
if (!networkId) return
|
|
||||||
|
|
||||||
const oceanConfig = getOceanConfig(networkId)
|
|
||||||
setOceanConfig(oceanConfig)
|
|
||||||
}, [networkId])
|
|
||||||
|
|
||||||
async function getDTSymbol(ddo: Asset): Promise<string> {
|
|
||||||
if (!accountId) return
|
|
||||||
|
|
||||||
const { datatokens } = ddo
|
|
||||||
return datatokens[0].symbol
|
|
||||||
// return dataTokenInfo
|
|
||||||
// ? dataTokenInfo.symbol
|
|
||||||
// : await ocean?.datatokens.getSymbol(dataTokenInfo.address)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getDTName(ddo: Asset): Promise<string> {
|
|
||||||
if (!accountId) return
|
|
||||||
const { datatokens } = ddo
|
|
||||||
return datatokens[0].name
|
|
||||||
// return dataTokenInfo
|
|
||||||
// ? dataTokenInfo.name
|
|
||||||
// : await ocean?.datatokens.getName(dataTokenInfo.address)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper for setting steps & feedback for all flows
|
|
||||||
async function setStep(
|
|
||||||
index: number,
|
|
||||||
type: 'pool' | 'exchange' | 'free' | 'buy' | 'dispense',
|
|
||||||
ddo: Asset
|
|
||||||
) {
|
|
||||||
const dtSymbol = await getDTSymbol(ddo)
|
|
||||||
setPricingStep(index)
|
|
||||||
if (!dtSymbol) return
|
|
||||||
|
|
||||||
let messages
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case 'pool':
|
|
||||||
messages = getCreatePricingPoolFeedback(dtSymbol)
|
|
||||||
break
|
|
||||||
case 'exchange':
|
|
||||||
messages = getCreatePricingExchangeFeedback(dtSymbol)
|
|
||||||
break
|
|
||||||
case 'free':
|
|
||||||
messages = getCreateFreePricingFeedback(dtSymbol)
|
|
||||||
break
|
|
||||||
case 'buy':
|
|
||||||
messages = getBuyDTFeedback(dtSymbol)
|
|
||||||
break
|
|
||||||
case 'dispense':
|
|
||||||
messages = getDispenseFeedback(dtSymbol)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
setPricingStepText(messages[index])
|
|
||||||
}
|
|
||||||
|
|
||||||
async function mint(
|
|
||||||
tokensToMint: string,
|
|
||||||
ddo: Asset
|
|
||||||
): Promise<TransactionReceipt | void> {
|
|
||||||
const { datatokens } = ddo
|
|
||||||
LoggerInstance.log('mint function', datatokens[0].address, accountId)
|
|
||||||
// const balance = new Decimal(
|
|
||||||
// await ocean.datatokens.balance(dataTokenInfo.address, accountId)
|
|
||||||
// )
|
|
||||||
// const tokens = new Decimal(tokensToMint)
|
|
||||||
// if (tokens.greaterThan(balance)) {
|
|
||||||
// const mintAmount = tokens.minus(balance)
|
|
||||||
// const tx = await ocean.datatokens.mint(
|
|
||||||
// dataTokenInfo.address,
|
|
||||||
// accountId,
|
|
||||||
// mintAmount.toString()
|
|
||||||
// )
|
|
||||||
// return tx
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
async function buyDT(
|
|
||||||
amountDataToken: number | string,
|
|
||||||
accessDetails: AccessDetails,
|
|
||||||
ddo: Asset
|
|
||||||
): Promise<TransactionReceipt | void> {
|
|
||||||
if (!accountId) return
|
|
||||||
|
|
||||||
let tx
|
|
||||||
|
|
||||||
try {
|
|
||||||
setPricingIsLoading(true)
|
|
||||||
setPricingError(undefined)
|
|
||||||
setStep(1, 'buy', ddo)
|
|
||||||
|
|
||||||
LoggerInstance.log('Price found for buying', accessDetails)
|
|
||||||
Decimal.set({ precision: 18 })
|
|
||||||
|
|
||||||
switch (accessDetails?.type) {
|
|
||||||
case 'dynamic': {
|
|
||||||
const oceanAmmount = new Decimal(accessDetails.price)
|
|
||||||
.times(1.05)
|
|
||||||
.toString()
|
|
||||||
const maxPrice = new Decimal(accessDetails.price).times(2).toString()
|
|
||||||
|
|
||||||
setStep(2, 'buy', ddo)
|
|
||||||
LoggerInstance.log(
|
|
||||||
'Buying token from pool',
|
|
||||||
accessDetails,
|
|
||||||
accountId,
|
|
||||||
oceanAmmount,
|
|
||||||
maxPrice
|
|
||||||
)
|
|
||||||
// tx = await ocean.pool.buyDT(
|
|
||||||
// accountId,
|
|
||||||
// price.address,
|
|
||||||
// String(amountDataToken),
|
|
||||||
// oceanAmmount,
|
|
||||||
// maxPrice
|
|
||||||
// )
|
|
||||||
setStep(3, 'buy', ddo)
|
|
||||||
LoggerInstance.log('DT buy response', tx)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'fixed': {
|
|
||||||
if (!oceanConfig.oceanTokenAddress) {
|
|
||||||
LoggerInstance.error(`'oceanTokenAddress' not set in oceanConfig`)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!oceanConfig.fixedRateExchangeAddress) {
|
|
||||||
LoggerInstance.error(
|
|
||||||
`'fixedRateExchangeAddress' not set in oceanConfig`
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
LoggerInstance.log(
|
|
||||||
'Buying token from exchange',
|
|
||||||
accessDetails,
|
|
||||||
accountId
|
|
||||||
)
|
|
||||||
// await ocean.datatokens.approve(
|
|
||||||
// oceanConfig.oceanTokenAddress,
|
|
||||||
// oceanConfig.fixedRateExchangeAddress,
|
|
||||||
// `${price.value}`,
|
|
||||||
// accountId
|
|
||||||
// )
|
|
||||||
setStep(2, 'buy', ddo)
|
|
||||||
// tx = await ocean.fixedRateExchange.buyDT(
|
|
||||||
// price.address,
|
|
||||||
// `${amountDataToken}`,
|
|
||||||
// accountId
|
|
||||||
// )
|
|
||||||
setStep(3, 'buy', ddo)
|
|
||||||
LoggerInstance.log('DT exchange buy response', tx)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
case 'free': {
|
|
||||||
setStep(1, 'dispense', ddo)
|
|
||||||
// const isDispensable = await ocean.OceanDispenser.isDispensable(
|
|
||||||
// ddo?.services[0].datatokenAddress,
|
|
||||||
// accountId,
|
|
||||||
// '1'
|
|
||||||
// )
|
|
||||||
|
|
||||||
// if (!isDispensable) {
|
|
||||||
// LoggerInstance.error(
|
|
||||||
// `Dispenser for ${ddo?.services[0].datatokenAddress} failed to dispense`
|
|
||||||
// )
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// tx = await ocean.OceanDispenser.dispense(
|
|
||||||
// ddo?.services[0].datatokenAddress,
|
|
||||||
// accountId,
|
|
||||||
// '1'
|
|
||||||
// )
|
|
||||||
setStep(2, 'dispense', ddo)
|
|
||||||
LoggerInstance.log('DT dispense response', tx)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
setPricingError(error.message)
|
|
||||||
LoggerInstance.error(error)
|
|
||||||
} finally {
|
|
||||||
setStep(0, 'buy', ddo)
|
|
||||||
setPricingStepText(undefined)
|
|
||||||
setPricingIsLoading(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tx
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getDTSymbol,
|
|
||||||
getDTName,
|
|
||||||
buyDT,
|
|
||||||
mint,
|
|
||||||
pricingStep,
|
|
||||||
pricingStepText,
|
|
||||||
pricingIsLoading,
|
|
||||||
pricingError
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { usePricing }
|
|
||||||
export default usePricing
|
|
@ -1,12 +1,6 @@
|
|||||||
import { UseSiteMetadata } from './types'
|
import { UseSiteMetadata } from './types'
|
||||||
import siteContent from '../../../content/site.json'
|
import { getSiteMetadata } from '@utils/siteConfig'
|
||||||
import appConfig from '../../../app.config'
|
|
||||||
|
|
||||||
export function useSiteMetadata(): UseSiteMetadata {
|
export function useSiteMetadata(): UseSiteMetadata {
|
||||||
const siteMeta: UseSiteMetadata = {
|
return getSiteMetadata()
|
||||||
...siteContent,
|
|
||||||
appConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
return siteMeta
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,12 @@ export interface UseSiteMetadata {
|
|||||||
chainIds: number[]
|
chainIds: number[]
|
||||||
chainIdsSupported: number[]
|
chainIdsSupported: number[]
|
||||||
marketFeeAddress: string
|
marketFeeAddress: string
|
||||||
|
publisherMarketOrderFee: string
|
||||||
|
publisherMarketPoolSwapFee: string
|
||||||
|
publisherMarketFixedSwapFee: string
|
||||||
|
consumeMarketOrderFee: string
|
||||||
|
consumeMarketPoolSwapFee: string
|
||||||
|
consumeMarketFixedSwapFee: string
|
||||||
currencies: string[]
|
currencies: string[]
|
||||||
portisId: string
|
portisId: string
|
||||||
allowFixedPricing: string
|
allowFixedPricing: string
|
||||||
|
50
src/@types/Price.d.ts
vendored
50
src/@types/Price.d.ts
vendored
@ -1,14 +1,54 @@
|
|||||||
|
import { ProviderFees } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @interface OrderPriceAndFee
|
||||||
|
* @prop {string} price total price including fees
|
||||||
|
* @prop {string} publisherMarketOrderFee fee received by the market where the asset was published. It is set on erc20 creation. It is a absolute value
|
||||||
|
* @prop {string} publisherMarketPoolSwapFee fee received by the market where the asset was published on any swap (pool or fre). Absolute value based on the configured percentage
|
||||||
|
* @prop {string} publisherMarketFixedSwapFee fee received by the market where the asset was published on any swap (pool or fre). Absolute value based on the configured percentage
|
||||||
|
* @prop {string} consumeMarketOrderFee fee received by the market where the asset is ordered. It is set on erc20 creation. It is a absolute value
|
||||||
|
* @prop {string} consumeMarketPoolSwapFee fee received by the market where the asset is ordered on any swap (pool or fre). Absolute value based on the configured percentage
|
||||||
|
* @prop {string} consumeMarketFixedSwapFee fee received by the market where the asset is ordered on any swap (pool or fre). Absolute value based on the configured percentage
|
||||||
|
* @prop {string} liquidityProviderSwapFee fee received by the liquidity providers of the pool. It is a percentage ( ex 50% means liquidityProviderSwapFee=0.5)
|
||||||
|
* @prop {ProviderFees} providerFee received from provider
|
||||||
|
* @prop {string} opcFee ocean protocol community fee, Absolute value based on the configured percentage
|
||||||
|
*/
|
||||||
|
interface OrderPriceAndFees {
|
||||||
|
price: string
|
||||||
|
publisherMarketOrderFee: string
|
||||||
|
publisherMarketPoolSwapFee: string
|
||||||
|
publisherMarketFixedSwapFee: string
|
||||||
|
consumeMarketOrderFee: string
|
||||||
|
consumeMarketPoolSwapFee: string
|
||||||
|
consumeMarketFixedSwapFee: string
|
||||||
|
liquidityProviderSwapFee: string
|
||||||
|
providerFee: ProviderFees
|
||||||
|
opcFee: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @interface AccessDetails
|
||||||
|
* @prop {'dynamic' | 'fixed' | 'free' | ''} type
|
||||||
|
* @prop {string} price can be either spotPrice/rate
|
||||||
|
* @prop {string} addressOrId if type is dynamic this is the pool address, for fixed/free this is an id.
|
||||||
|
* @prop {TokenInfo} baseToken
|
||||||
|
* @prop {TokenInfo} datatoken
|
||||||
|
* @prop {bool} isPurchasable checks if you can buy a datatoken from fixed rate exchange/pool/dispenser. For pool it also checks if there is enough dt liquidity
|
||||||
|
* @prop {bool} isOwned checks if there are valid orders for this, it also takes in consideration timeout
|
||||||
|
* @prop {string} validOrderTx the latest valid order tx, it also takes in consideration timeout
|
||||||
|
* @prop {string} publisherMarketOrderFee this is here just because it's more efficient, it's allready in the query
|
||||||
|
* @prop {FeeInfo} feeInfo values of the relevant fees
|
||||||
|
*/
|
||||||
interface AccessDetails {
|
interface AccessDetails {
|
||||||
type: 'dynamic' | 'fixed' | 'free' | ''
|
type: 'dynamic' | 'fixed' | 'free' | ''
|
||||||
price: number
|
price: string
|
||||||
// if type is dynamic this is the pool address, for fixed/free this is an id.
|
|
||||||
addressOrId: string
|
addressOrId: string
|
||||||
baseToken: TokenInfo
|
baseToken: TokenInfo
|
||||||
datatoken: TokenInfo
|
datatoken: TokenInfo
|
||||||
isConsumable?: boolean
|
isPurchasable?: boolean
|
||||||
// if there are valid orders for this
|
isOwned: bool
|
||||||
owned: bool
|
|
||||||
validOrderTx: string
|
validOrderTx: string
|
||||||
|
publisherMarketOrderFee: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PriceOptions {
|
interface PriceOptions {
|
||||||
|
@ -8,8 +8,13 @@ import {
|
|||||||
TokensPriceQuery,
|
TokensPriceQuery,
|
||||||
TokensPriceQuery_tokens as TokensPrice
|
TokensPriceQuery_tokens as TokensPrice
|
||||||
} from '../@types/subgraph/TokensPriceQuery'
|
} from '../@types/subgraph/TokensPriceQuery'
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
import { Asset, ProviderInstance } from '@oceanprotocol/lib'
|
||||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
import { calculateBuyPrice } from './pool'
|
||||||
|
import { getFixedBuyPrice } from './fixedRateExchange'
|
||||||
|
import { getSiteMetadata } from './siteConfig'
|
||||||
|
import { AccessDetails, OrderPriceAndFees } from 'src/@types/Price'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
|
||||||
const TokensPriceQuery = gql`
|
const TokensPriceQuery = gql`
|
||||||
query TokensPriceQuery($datatokenIds: [ID!], $account: String) {
|
query TokensPriceQuery($datatokenIds: [ID!], $account: String) {
|
||||||
@ -132,25 +137,33 @@ const TokenPriceQuery = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// TODO: fill in fees after subgraph update
|
||||||
function getAccessDetailsFromTokenPrice(
|
function getAccessDetailsFromTokenPrice(
|
||||||
tokenPrice: TokenPrice | TokensPrice,
|
tokenPrice: TokenPrice | TokensPrice,
|
||||||
timeout?: number
|
timeout?: number
|
||||||
): AccessDetails {
|
): AccessDetails {
|
||||||
const accessDetails = {} as AccessDetails
|
const accessDetails = {} as AccessDetails
|
||||||
|
if (
|
||||||
if (!timeout && !tokenPrice.orders && tokenPrice.orders.length > 0) {
|
tokenPrice &&
|
||||||
|
timeout &&
|
||||||
|
tokenPrice.orders &&
|
||||||
|
tokenPrice.orders.length > 0
|
||||||
|
) {
|
||||||
const order = tokenPrice.orders[0]
|
const order = tokenPrice.orders[0]
|
||||||
accessDetails.owned = Date.now() / 1000 - order.createdTimestamp < timeout
|
accessDetails.isOwned = Date.now() / 1000 - order.createdTimestamp < timeout
|
||||||
accessDetails.validOrderTx = order.tx
|
accessDetails.validOrderTx = order.tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: fetch order fee from sub query
|
||||||
|
accessDetails.publisherMarketOrderFee = '0'
|
||||||
|
|
||||||
// free is always the best price
|
// free is always the best price
|
||||||
if (tokenPrice.dispensers && tokenPrice.dispensers.length > 0) {
|
if (tokenPrice.dispensers && tokenPrice.dispensers.length > 0) {
|
||||||
const dispenser = tokenPrice.dispensers[0]
|
const dispenser = tokenPrice.dispensers[0]
|
||||||
accessDetails.type = 'free'
|
accessDetails.type = 'free'
|
||||||
accessDetails.addressOrId = dispenser.id
|
accessDetails.addressOrId = dispenser.id
|
||||||
accessDetails.price = 0
|
accessDetails.price = '0'
|
||||||
accessDetails.isConsumable = dispenser.active
|
accessDetails.isPurchasable = dispenser.active
|
||||||
accessDetails.datatoken = {
|
accessDetails.datatoken = {
|
||||||
address: dispenser.token.id,
|
address: dispenser.token.id,
|
||||||
name: dispenser.token.name,
|
name: dispenser.token.name,
|
||||||
@ -164,21 +177,21 @@ function getAccessDetailsFromTokenPrice(
|
|||||||
tokenPrice.fixedRateExchanges &&
|
tokenPrice.fixedRateExchanges &&
|
||||||
tokenPrice.fixedRateExchanges.length > 0
|
tokenPrice.fixedRateExchanges.length > 0
|
||||||
) {
|
) {
|
||||||
const fre = tokenPrice.fixedRateExchanges[0]
|
const fixed = tokenPrice.fixedRateExchanges[0]
|
||||||
accessDetails.type = 'fixed'
|
accessDetails.type = 'fixed'
|
||||||
accessDetails.addressOrId = fre.id
|
accessDetails.addressOrId = fixed.id
|
||||||
accessDetails.price = fre.price
|
accessDetails.price = fixed.price
|
||||||
// in theory we should check dt balance here, we can skip this because in the market we always create fre with minting capabilities.
|
// in theory we should check dt balance here, we can skip this because in the market we always create fre with minting capabilities.
|
||||||
accessDetails.isConsumable = fre.active
|
accessDetails.isPurchasable = fixed.active
|
||||||
accessDetails.baseToken = {
|
accessDetails.baseToken = {
|
||||||
address: fre.baseToken.address,
|
address: fixed.baseToken.address,
|
||||||
name: fre.baseToken.name,
|
name: fixed.baseToken.name,
|
||||||
symbol: fre.baseToken.symbol
|
symbol: fixed.baseToken.symbol
|
||||||
}
|
}
|
||||||
accessDetails.datatoken = {
|
accessDetails.datatoken = {
|
||||||
address: fre.datatoken.address,
|
address: fixed.datatoken.address,
|
||||||
name: fre.datatoken.name,
|
name: fixed.datatoken.name,
|
||||||
symbol: fre.datatoken.symbol
|
symbol: fixed.datatoken.symbol
|
||||||
}
|
}
|
||||||
return accessDetails
|
return accessDetails
|
||||||
}
|
}
|
||||||
@ -188,10 +201,10 @@ function getAccessDetailsFromTokenPrice(
|
|||||||
const pool = tokenPrice.pools[0]
|
const pool = tokenPrice.pools[0]
|
||||||
accessDetails.type = 'dynamic'
|
accessDetails.type = 'dynamic'
|
||||||
accessDetails.addressOrId = pool.id
|
accessDetails.addressOrId = pool.id
|
||||||
// TODO: this needs to be consumePrice
|
|
||||||
accessDetails.price = pool.spotPrice
|
accessDetails.price = pool.spotPrice
|
||||||
// TODO: pool.datatokenLiquidity > 3 is kinda random here, we shouldn't run into this anymore now , needs more thinking/testing
|
// TODO: pool.datatokenLiquidity > 3 is kinda random here, we shouldn't run into this anymore now , needs more thinking/testing
|
||||||
accessDetails.isConsumable = pool.isFinalized && pool.datatokenLiquidity > 3
|
accessDetails.isPurchasable =
|
||||||
|
pool.isFinalized && pool.datatokenLiquidity > 3
|
||||||
accessDetails.baseToken = {
|
accessDetails.baseToken = {
|
||||||
address: pool.baseToken.address,
|
address: pool.baseToken.address,
|
||||||
name: pool.baseToken.name,
|
name: pool.baseToken.name,
|
||||||
@ -208,20 +221,81 @@ function getAccessDetailsFromTokenPrice(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns various consume details for the desired datatoken
|
* This will be used to get price including feed before ordering
|
||||||
* @param chain chain on which the datatoken is preset
|
* @param {AssetExtended} asset
|
||||||
* @param datatokenAddress address of the datatoken
|
* @return {Promise<OrdePriceAndFee>}
|
||||||
* @param timeout timeout of the service, only needed if you want order details like owned and validOrderId
|
*/
|
||||||
* @param account account that wants to consume, only needed if you want order details like owned and validOrderId
|
export async function getOrderPriceAndFees(
|
||||||
* @returns AccessDetails
|
asset: AssetExtended,
|
||||||
|
accountId?: string
|
||||||
|
): Promise<OrderPriceAndFees> {
|
||||||
|
const orderPriceAndFee = {
|
||||||
|
price: '0',
|
||||||
|
publisherMarketOrderFee: '0',
|
||||||
|
publisherMarketPoolSwapFee: '0',
|
||||||
|
publisherMarketFixedSwapFee: '0',
|
||||||
|
consumeMarketOrderFee: '0',
|
||||||
|
consumeMarketPoolSwapFee: '0',
|
||||||
|
consumeMarketFixedSwapFee: '0',
|
||||||
|
providerFee: {},
|
||||||
|
opcFee: '0'
|
||||||
|
} as OrderPriceAndFees
|
||||||
|
const { accessDetails } = asset
|
||||||
|
const { appConfig } = getSiteMetadata()
|
||||||
|
|
||||||
|
// fetch publish market order fee
|
||||||
|
orderPriceAndFee.publisherMarketOrderFee =
|
||||||
|
asset.accessDetails.publisherMarketOrderFee
|
||||||
|
// fetch consume market order fee
|
||||||
|
orderPriceAndFee.consumeMarketOrderFee = appConfig.consumeMarketOrderFee
|
||||||
|
// fetch provider fee
|
||||||
|
const initializeData = await ProviderInstance.initialize(
|
||||||
|
asset.id,
|
||||||
|
asset.services[0].id,
|
||||||
|
0,
|
||||||
|
accountId,
|
||||||
|
asset.services[0].serviceEndpoint
|
||||||
|
)
|
||||||
|
orderPriceAndFee.providerFee = initializeData.providerFee
|
||||||
|
|
||||||
|
// fetch price and swap fees
|
||||||
|
switch (accessDetails.type) {
|
||||||
|
case 'dynamic': {
|
||||||
|
const poolPrice = await calculateBuyPrice(accessDetails, asset.chainId)
|
||||||
|
orderPriceAndFee.price = poolPrice
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'fixed': {
|
||||||
|
const fixed = await getFixedBuyPrice(accessDetails, asset.chainId)
|
||||||
|
orderPriceAndFee.price = fixed.baseTokenAmount
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate full price, we assume that all the values are in ocean, otherwise this will be incorrect
|
||||||
|
orderPriceAndFee.price = new Decimal(orderPriceAndFee.price)
|
||||||
|
.add(new Decimal(orderPriceAndFee.consumeMarketOrderFee))
|
||||||
|
.add(new Decimal(orderPriceAndFee.publisherMarketOrderFee))
|
||||||
|
.add(new Decimal(orderPriceAndFee.providerFee.providerFeeAmount))
|
||||||
|
.toString()
|
||||||
|
return orderPriceAndFee
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} chain
|
||||||
|
* @param {string} datatokenAddress
|
||||||
|
* @param {number=} timeout timout of the service, this is needed to return order details
|
||||||
|
* @param {string=} account account that wants to buy, is needed to return order details
|
||||||
|
* @param {bool=} includeOrderPriceAndFees if false price will be spot price (pool) and rate (fre), if true you will get the order price including fees !! fees not yet done
|
||||||
|
* @returns {Promise<AccessDetails>}
|
||||||
*/
|
*/
|
||||||
export async function getAccessDetails(
|
export async function getAccessDetails(
|
||||||
chain: number,
|
chainId: number,
|
||||||
datatokenAddress: string,
|
datatokenAddress: string,
|
||||||
timeout?: number,
|
timeout?: number,
|
||||||
account = ''
|
account = ''
|
||||||
): Promise<AccessDetails> {
|
): Promise<AccessDetails> {
|
||||||
const queryContext = getQueryContext(Number(chain))
|
const queryContext = getQueryContext(Number(chainId))
|
||||||
const tokenQueryResult: OperationResult<
|
const tokenQueryResult: OperationResult<
|
||||||
TokenPriceQuery,
|
TokenPriceQuery,
|
||||||
{ datatokenId: string; account: string }
|
{ datatokenId: string; account: string }
|
||||||
@ -229,7 +303,7 @@ export async function getAccessDetails(
|
|||||||
TokenPriceQuery,
|
TokenPriceQuery,
|
||||||
{
|
{
|
||||||
datatokenId: datatokenAddress.toLowerCase(),
|
datatokenId: datatokenAddress.toLowerCase(),
|
||||||
account: account.toLowerCase()
|
account: account?.toLowerCase()
|
||||||
},
|
},
|
||||||
queryContext
|
queryContext
|
||||||
)
|
)
|
||||||
@ -247,7 +321,6 @@ export async function getAccessDetailsForAssets(
|
|||||||
const chainAssetLists: { [key: number]: string[] } = {}
|
const chainAssetLists: { [key: number]: string[] } = {}
|
||||||
|
|
||||||
for (const asset of assets) {
|
for (const asset of assets) {
|
||||||
// harcoded until we have chainId on assets
|
|
||||||
if (chainAssetLists[asset.chainId]) {
|
if (chainAssetLists[asset.chainId]) {
|
||||||
chainAssetLists[asset.chainId].push(
|
chainAssetLists[asset.chainId].push(
|
||||||
asset?.services[0].datatokenAddress.toLowerCase()
|
asset?.services[0].datatokenAddress.toLowerCase()
|
||||||
@ -264,20 +337,24 @@ export async function getAccessDetailsForAssets(
|
|||||||
const queryContext = getQueryContext(Number(chainKey))
|
const queryContext = getQueryContext(Number(chainKey))
|
||||||
const tokenQueryResult: OperationResult<
|
const tokenQueryResult: OperationResult<
|
||||||
TokensPriceQuery,
|
TokensPriceQuery,
|
||||||
{ datatokenId: string; account: string }
|
{ datatokenIds: [string]; account: string }
|
||||||
> = await fetchData(
|
> = await fetchData(
|
||||||
TokensPriceQuery,
|
TokensPriceQuery,
|
||||||
{
|
{
|
||||||
datatokenIds: chainAssetLists[chainKey],
|
datatokenIds: chainAssetLists[chainKey],
|
||||||
account: account.toLowerCase()
|
account: account?.toLowerCase()
|
||||||
},
|
},
|
||||||
queryContext
|
queryContext
|
||||||
)
|
)
|
||||||
tokenQueryResult.data?.tokens.forEach((token) => {
|
tokenQueryResult.data?.tokens.forEach((token) => {
|
||||||
const accessDetails = getAccessDetailsFromTokenPrice(token)
|
|
||||||
const currentAsset = assetsExtended.find(
|
const currentAsset = assetsExtended.find(
|
||||||
(asset) => asset.services[0].datatokenAddress.toLowerCase() === token.id
|
(asset) => asset.services[0].datatokenAddress.toLowerCase() === token.id
|
||||||
)
|
)
|
||||||
|
const accessDetails = getAccessDetailsFromTokenPrice(
|
||||||
|
token,
|
||||||
|
currentAsset?.services[0]?.timeout
|
||||||
|
)
|
||||||
|
|
||||||
currentAsset.accessDetails = accessDetails
|
currentAsset.accessDetails = accessDetails
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,89 +1,19 @@
|
|||||||
export const feedback: { [key in number]: string } = {
|
// TODO: can be better
|
||||||
99: 'Decrypting file URL...',
|
export function getOrderFeedback(
|
||||||
0: '1/3 Looking for data token. Buying if none found...',
|
baseTokenSymbol: string,
|
||||||
1: '2/3 Transfering data token.',
|
datatokenSymbol: string
|
||||||
2: '3/3 Payment confirmed. Requesting access...'
|
): { [key in number]: string } {
|
||||||
}
|
return {
|
||||||
|
0: `Approving and buying one ${datatokenSymbol} from pool`,
|
||||||
export const publishFeedback: { [key in number]: string } = {
|
1: `Ordering asset`,
|
||||||
0: '1/5 Creating datatoken ...',
|
2: `Approving ${baseTokenSymbol} and ordering asset`,
|
||||||
2: '2/5 Encrypting files ...',
|
3: 'Generating signature to access download url'
|
||||||
4: '3/5 Storing ddo ...',
|
}
|
||||||
6: '4/5 Minting tokens ...',
|
|
||||||
8: '5/5 Asset published succesfully'
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: do something with this object,
|
|
||||||
// consumeStep should probably return one of those strings
|
|
||||||
// instead of just a number
|
|
||||||
export const consumeFeedback: { [key in number]: string } = {
|
|
||||||
...feedback,
|
|
||||||
3: '3/3 Access granted. Consuming file...'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: customize for compute
|
// TODO: customize for compute
|
||||||
export const computeFeedback: { [key in number]: string } = {
|
export const computeFeedback: { [key in number]: string } = {
|
||||||
0: '1/3 Ordering asset...',
|
0: 'Ordering asset...',
|
||||||
1: '2/3 Transfering data token.',
|
1: 'Transfering datatoken.',
|
||||||
2: '3/3 Access granted. Starting job...'
|
2: 'Access granted. Starting job...'
|
||||||
}
|
|
||||||
|
|
||||||
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 getCreateFreePricingFeedback(dtSymbol: string): {
|
|
||||||
[key: number]: string
|
|
||||||
} {
|
|
||||||
return {
|
|
||||||
99: `Creating ${dtSymbol} faucet...`,
|
|
||||||
0: 'Setting faucet as minter ...',
|
|
||||||
1: 'Approving minter...',
|
|
||||||
2: 'Faucet 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.`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDispenseFeedback(dtSymbol: string): {
|
|
||||||
[key: number]: string
|
|
||||||
} {
|
|
||||||
return {
|
|
||||||
1: `1/2 Requesting ${dtSymbol}...`,
|
|
||||||
2: `2/2 Received ${dtSymbol}.`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
34
src/@utils/fixedRateExchange.ts
Normal file
34
src/@utils/fixedRateExchange.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { FixedRateExchange, PriceAndFees } from '@oceanprotocol/lib'
|
||||||
|
import { AccessDetails } from 'src/@types/Price'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { getOceanConfig } from './ocean'
|
||||||
|
import { getDummyWeb3 } from './web3'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to calculate the price to buy one datatoken from a fixed rate exchange. You need to pass either a web3 object or a chainId. If you pass a chainId a dummy web3 object will be created
|
||||||
|
* @param {AccessDetails} accessDetails
|
||||||
|
* @param {number} chainId
|
||||||
|
* @param {Web3?} web3
|
||||||
|
* @return {Promise<PriceAndFees>}
|
||||||
|
*/
|
||||||
|
export async function getFixedBuyPrice(
|
||||||
|
accessDetails: AccessDetails,
|
||||||
|
chainId?: number,
|
||||||
|
web3?: Web3
|
||||||
|
): Promise<PriceAndFees> {
|
||||||
|
if (!web3 && !chainId)
|
||||||
|
throw new Error("web3 and chainId can't be undefined at the same time!")
|
||||||
|
|
||||||
|
if (!web3) {
|
||||||
|
web3 = await getDummyWeb3(chainId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = getOceanConfig(chainId)
|
||||||
|
|
||||||
|
const fixed = new FixedRateExchange(web3, config.fixedRateExchangeAddress)
|
||||||
|
const estimatedPrice = await fixed.calcBaseInGivenOutDT(
|
||||||
|
accessDetails.addressOrId,
|
||||||
|
'1'
|
||||||
|
)
|
||||||
|
return estimatedPrice
|
||||||
|
}
|
@ -6,8 +6,8 @@ import matter from 'gray-matter'
|
|||||||
// Next.js specifics to be used in getStaticProps / getStaticPaths
|
// Next.js specifics to be used in getStaticProps / getStaticPaths
|
||||||
// to automatically generate pages from Markdown files in `src/pages/[slug].tsx`.
|
// to automatically generate pages from Markdown files in `src/pages/[slug].tsx`.
|
||||||
//
|
//
|
||||||
const pagesDirectory = join(process.cwd(), 'content', 'pages')
|
// const pagesDirectory = join(process.cwd(), 'content', 'pages')
|
||||||
|
const pagesDirectory = './content/pages'
|
||||||
export interface PageData {
|
export interface PageData {
|
||||||
slug: string
|
slug: string
|
||||||
frontmatter: { [key: string]: any }
|
frontmatter: { [key: string]: any }
|
||||||
|
96
src/@utils/order.ts
Normal file
96
src/@utils/order.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import {
|
||||||
|
approve,
|
||||||
|
Datatoken,
|
||||||
|
FreOrderParams,
|
||||||
|
OrderParams,
|
||||||
|
ProviderInstance
|
||||||
|
} from '@oceanprotocol/lib'
|
||||||
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { getOceanConfig } from './ocean'
|
||||||
|
import { TransactionReceipt } from 'web3-eth'
|
||||||
|
import { getSiteMetadata } from './siteConfig'
|
||||||
|
import { OrderPriceAndFees } from 'src/@types/Price'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For pool you need to buy the datatoken beforehand, this always assumes you want to order the first service
|
||||||
|
* @param web3
|
||||||
|
* @param asset
|
||||||
|
* @param accountId
|
||||||
|
* @returns {TransactionReceipt} receipt of the order
|
||||||
|
*/
|
||||||
|
export async function order(
|
||||||
|
web3: Web3,
|
||||||
|
asset: AssetExtended,
|
||||||
|
orderPriceAndFees: OrderPriceAndFees,
|
||||||
|
accountId: string
|
||||||
|
): Promise<TransactionReceipt> {
|
||||||
|
const datatoken = new Datatoken(web3)
|
||||||
|
const config = getOceanConfig(asset.chainId)
|
||||||
|
const { appConfig } = getSiteMetadata()
|
||||||
|
|
||||||
|
const initializeData = await ProviderInstance.initialize(
|
||||||
|
asset.id,
|
||||||
|
asset.services[0].id,
|
||||||
|
0,
|
||||||
|
accountId,
|
||||||
|
asset.services[0].serviceEndpoint
|
||||||
|
)
|
||||||
|
|
||||||
|
const orderParams = {
|
||||||
|
consumer: accountId,
|
||||||
|
serviceIndex: 0,
|
||||||
|
_providerFees: initializeData.providerFee
|
||||||
|
} as OrderParams
|
||||||
|
|
||||||
|
// TODO: we need to approve provider fee
|
||||||
|
switch (asset.accessDetails?.type) {
|
||||||
|
case 'fixed': {
|
||||||
|
// this assumes all fees are in ocean
|
||||||
|
const txApprove = await approve(
|
||||||
|
web3,
|
||||||
|
accountId,
|
||||||
|
asset.accessDetails.baseToken.address,
|
||||||
|
asset.accessDetails.datatoken.address,
|
||||||
|
orderPriceAndFees.price,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
const freParams = {
|
||||||
|
exchangeContract: config.fixedRateExchangeAddress,
|
||||||
|
exchangeId: asset.accessDetails.addressOrId,
|
||||||
|
maxBaseTokenAmount: orderPriceAndFees.price,
|
||||||
|
swapMarketFee: appConfig.consumeMarketFixedSwapFee,
|
||||||
|
marketFeeAddress: appConfig.marketFeeAddress
|
||||||
|
} as FreOrderParams
|
||||||
|
const tx = await datatoken.buyFromFreAndOrder(
|
||||||
|
asset.accessDetails.datatoken.address,
|
||||||
|
accountId,
|
||||||
|
orderParams,
|
||||||
|
freParams
|
||||||
|
)
|
||||||
|
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
case 'dynamic': {
|
||||||
|
const tx = await datatoken.startOrder(
|
||||||
|
asset.accessDetails.datatoken.address,
|
||||||
|
accountId,
|
||||||
|
accountId,
|
||||||
|
0,
|
||||||
|
initializeData.providerFee
|
||||||
|
)
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'free': {
|
||||||
|
const tx = await datatoken.buyFromDispenserAndOrder(
|
||||||
|
asset.services[0].datatokenAddress,
|
||||||
|
accountId,
|
||||||
|
orderParams,
|
||||||
|
config.dispenserAddress
|
||||||
|
)
|
||||||
|
return tx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
75
src/@utils/pool.ts
Normal file
75
src/@utils/pool.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { approve, Pool } from '@oceanprotocol/lib'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
import { getSiteMetadata } from './siteConfig'
|
||||||
|
import { getDummyWeb3 } from './web3'
|
||||||
|
import { TransactionReceipt } from 'web3-eth'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
|
import { AccessDetails } from 'src/@types/Price'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to calculate the price to buy one datatoken from a pool, that is different from spot price. You need to pass either a web3 object or a chainId. If you pass a chainId a dummy web3 object will be created
|
||||||
|
* @param {AccessDetails} accessDetails
|
||||||
|
* @param {Web3?} [web3]
|
||||||
|
* @param {number?} [chainId]
|
||||||
|
* @return {Promise<PriceAndEstimation>}
|
||||||
|
*/
|
||||||
|
export async function calculateBuyPrice(
|
||||||
|
accessDetails: AccessDetails,
|
||||||
|
chainId?: number,
|
||||||
|
web3?: Web3
|
||||||
|
): Promise<string> {
|
||||||
|
if (!web3 && !chainId)
|
||||||
|
throw new Error("web3 and chainId can't be undefined at the same time!")
|
||||||
|
|
||||||
|
if (!web3) {
|
||||||
|
web3 = await getDummyWeb3(chainId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pool = new Pool(web3)
|
||||||
|
const { appConfig } = getSiteMetadata()
|
||||||
|
const estimatedPrice = await pool.getAmountInExactOut(
|
||||||
|
accessDetails.addressOrId,
|
||||||
|
accessDetails.baseToken.address,
|
||||||
|
accessDetails.datatoken.address,
|
||||||
|
'1',
|
||||||
|
appConfig.consumeMarketPoolSwapFee
|
||||||
|
)
|
||||||
|
|
||||||
|
return estimatedPrice
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buyDtFromPool(
|
||||||
|
accessDetails: AccessDetails,
|
||||||
|
accountId: string,
|
||||||
|
web3: Web3
|
||||||
|
): Promise<TransactionReceipt> {
|
||||||
|
const pool = new Pool(web3)
|
||||||
|
const { appConfig } = getSiteMetadata()
|
||||||
|
// we need to calculate the actual price to buy one datatoken
|
||||||
|
const dtPrice = await calculateBuyPrice(accessDetails, null, web3)
|
||||||
|
const approveTx = await approve(
|
||||||
|
web3,
|
||||||
|
accountId,
|
||||||
|
accessDetails.baseToken.address,
|
||||||
|
accessDetails.addressOrId,
|
||||||
|
dtPrice,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
const result = await pool.swapExactAmountOut(
|
||||||
|
accountId,
|
||||||
|
accessDetails.addressOrId,
|
||||||
|
{
|
||||||
|
marketFeeAddress: appConfig.marketFeeAddress,
|
||||||
|
tokenIn: accessDetails.baseToken.address,
|
||||||
|
tokenOut: accessDetails.datatoken.address
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// this is just to be safe
|
||||||
|
maxAmountIn: new Decimal(dtPrice).mul(10).toString(),
|
||||||
|
swapMarketFee: appConfig.consumeMarketPoolSwapFee,
|
||||||
|
tokenAmountOut: '1'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
@ -1,10 +1,13 @@
|
|||||||
import {
|
import {
|
||||||
|
downloadFileBrowser,
|
||||||
FileMetadata,
|
FileMetadata,
|
||||||
LoggerInstance,
|
LoggerInstance,
|
||||||
ProviderInstance
|
ProviderInstance
|
||||||
} from '@oceanprotocol/lib'
|
} from '@oceanprotocol/lib'
|
||||||
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
import Web3 from 'web3'
|
||||||
|
|
||||||
// TODO: Why do we have these functions ?!?!?!
|
// TODO: Why do we have these one line functions ?!?!?!
|
||||||
export async function getEncryptedFiles(
|
export async function getEncryptedFiles(
|
||||||
files: FileMetadata[],
|
files: FileMetadata[],
|
||||||
providerUrl: string
|
providerUrl: string
|
||||||
@ -46,3 +49,21 @@ export async function getFileUrlInfo(
|
|||||||
LoggerInstance.error(error.message)
|
LoggerInstance.error(error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function downloadFile(
|
||||||
|
web3: Web3,
|
||||||
|
asset: AssetExtended,
|
||||||
|
accountId: string,
|
||||||
|
validOrderTx?: string
|
||||||
|
) {
|
||||||
|
const downloadUrl = await ProviderInstance.getDownloadUrl(
|
||||||
|
asset.id,
|
||||||
|
accountId,
|
||||||
|
asset.services[0].id,
|
||||||
|
0,
|
||||||
|
validOrderTx || asset.accessDetails.validOrderTx,
|
||||||
|
asset.services[0].serviceEndpoint,
|
||||||
|
web3
|
||||||
|
)
|
||||||
|
await downloadFileBrowser(downloadUrl)
|
||||||
|
}
|
||||||
|
12
src/@utils/siteConfig.ts
Normal file
12
src/@utils/siteConfig.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { UseSiteMetadata } from '@hooks/useSiteMetadata/types'
|
||||||
|
import siteContent from '../../content/site.json'
|
||||||
|
import appConfig from '../../app.config'
|
||||||
|
|
||||||
|
export function getSiteMetadata(): UseSiteMetadata {
|
||||||
|
const siteMeta: UseSiteMetadata = {
|
||||||
|
...siteContent,
|
||||||
|
appConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
return siteMeta
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
import { getNetworkDisplayName } from '@hooks/useNetworkMetadata'
|
import { getNetworkDisplayName } from '@hooks/useNetworkMetadata'
|
||||||
import { LoggerInstance } from '@oceanprotocol/lib'
|
import { LoggerInstance } from '@oceanprotocol/lib'
|
||||||
|
import Web3 from 'web3'
|
||||||
import { getOceanConfig } from './ocean'
|
import { getOceanConfig } from './ocean'
|
||||||
|
|
||||||
export function accountTruncate(account: string): string {
|
export function accountTruncate(account: string): string {
|
||||||
@ -8,6 +9,15 @@ export function accountTruncate(account: string): string {
|
|||||||
const truncated = account.replace(middle, '…')
|
const truncated = account.replace(middle, '…')
|
||||||
return truncated
|
return truncated
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* returns a dummy web3 instance, only usable to get info from the chain
|
||||||
|
* @param chainId
|
||||||
|
* @returns Web3 instance
|
||||||
|
*/
|
||||||
|
export async function getDummyWeb3(chainId: number): Promise<Web3> {
|
||||||
|
const config = getOceanConfig(chainId)
|
||||||
|
return new Web3(config.nodeUri)
|
||||||
|
}
|
||||||
|
|
||||||
export async function addCustomNetwork(
|
export async function addCustomNetwork(
|
||||||
web3Provider: any,
|
web3Provider: any,
|
||||||
|
@ -10,6 +10,7 @@ import { useIsMounted } from '@hooks/useIsMounted'
|
|||||||
import { AssetExtended } from 'src/@types/AssetExtended'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
import { Asset } from '@oceanprotocol/lib'
|
||||||
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
||||||
|
import { useWeb3 } from '@context/Web3'
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ export default function AssetList({
|
|||||||
noPublisher
|
noPublisher
|
||||||
}: AssetListProps): ReactElement {
|
}: AssetListProps): ReactElement {
|
||||||
const { chainIds } = useUserPreferences()
|
const { chainIds } = useUserPreferences()
|
||||||
|
const { accountId } = useWeb3()
|
||||||
const [assetsWithPrices, setAssetsWithPrices] = useState<AssetExtended[]>()
|
const [assetsWithPrices, setAssetsWithPrices] = useState<AssetExtended[]>()
|
||||||
const [loading, setLoading] = useState<boolean>(isLoading)
|
const [loading, setLoading] = useState<boolean>(isLoading)
|
||||||
const isMounted = useIsMounted()
|
const isMounted = useIsMounted()
|
||||||
@ -51,14 +53,16 @@ export default function AssetList({
|
|||||||
if (!assets) return
|
if (!assets) return
|
||||||
setAssetsWithPrices(assets as AssetExtended[])
|
setAssetsWithPrices(assets as AssetExtended[])
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
|
||||||
async function fetchPrices() {
|
async function fetchPrices() {
|
||||||
const assetsWithPrices = await getAccessDetailsForAssets(assets)
|
const assetsWithPrices = await getAccessDetailsForAssets(
|
||||||
|
assets,
|
||||||
|
accountId || ''
|
||||||
|
)
|
||||||
if (!isMounted()) return
|
if (!isMounted()) return
|
||||||
setAssetsWithPrices([...assetsWithPrices])
|
setAssetsWithPrices([...assetsWithPrices])
|
||||||
}
|
}
|
||||||
fetchPrices()
|
fetchPrices()
|
||||||
}, [assets, isMounted])
|
}, [assets, isMounted, accountId])
|
||||||
|
|
||||||
// // This changes the page field inside the query
|
// // This changes the page field inside the query
|
||||||
function handlePageChange(selected: number) {
|
function handlePageChange(selected: number) {
|
||||||
|
@ -31,6 +31,8 @@ interface ButtonBuyProps {
|
|||||||
algorithmConsumableStatus?: number
|
algorithmConsumableStatus?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: we need to take a look at these messages
|
||||||
|
|
||||||
function getConsumeHelpText(
|
function getConsumeHelpText(
|
||||||
dtBalance: string,
|
dtBalance: string,
|
||||||
dtSymbol: string,
|
dtSymbol: string,
|
||||||
|
@ -3,21 +3,24 @@ import styles from './index.module.css'
|
|||||||
import Loader from '../atoms/Loader'
|
import Loader from '../atoms/Loader'
|
||||||
import Tooltip from '../atoms/Tooltip'
|
import Tooltip from '../atoms/Tooltip'
|
||||||
import PriceUnit from './PriceUnit'
|
import PriceUnit from './PriceUnit'
|
||||||
|
import { AccessDetails, OrderPriceAndFees } from 'src/@types/Price'
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
accessDetails,
|
accessDetails,
|
||||||
|
orderPriceAndFees,
|
||||||
className,
|
className,
|
||||||
small,
|
small,
|
||||||
conversion
|
conversion
|
||||||
}: {
|
}: {
|
||||||
accessDetails: AccessDetails
|
accessDetails: AccessDetails
|
||||||
|
orderPriceAndFees?: OrderPriceAndFees
|
||||||
className?: string
|
className?: string
|
||||||
small?: boolean
|
small?: boolean
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return accessDetails?.price || accessDetails?.type === 'free' ? (
|
return accessDetails?.price || accessDetails?.type === 'free' ? (
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={`${accessDetails.price}`}
|
price={`${orderPriceAndFees?.price || accessDetails?.price}`}
|
||||||
symbol={accessDetails.baseToken?.symbol}
|
symbol={accessDetails.baseToken?.symbol}
|
||||||
className={className}
|
className={className}
|
||||||
small={small}
|
small={small}
|
||||||
|
@ -6,12 +6,13 @@ import AssetComputeList from '@shared/AssetList/AssetComputeList'
|
|||||||
import { useCancelToken } from '@hooks/useCancelToken'
|
import { useCancelToken } from '@hooks/useCancelToken'
|
||||||
import { getServiceByName } from '@utils/ddo'
|
import { getServiceByName } from '@utils/ddo'
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
import { Asset } from '@oceanprotocol/lib'
|
||||||
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
|
||||||
export default function AlgorithmDatasetsListForCompute({
|
export default function AlgorithmDatasetsListForCompute({
|
||||||
ddo,
|
asset,
|
||||||
algorithmDid
|
algorithmDid
|
||||||
}: {
|
}: {
|
||||||
ddo: Asset
|
asset: AssetExtended
|
||||||
algorithmDid: string
|
algorithmDid: string
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const [datasetsForCompute, setDatasetsForCompute] =
|
const [datasetsForCompute, setDatasetsForCompute] =
|
||||||
@ -19,24 +20,24 @@ export default function AlgorithmDatasetsListForCompute({
|
|||||||
const newCancelToken = useCancelToken()
|
const newCancelToken = useCancelToken()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ddo) return
|
if (!asset) return
|
||||||
|
|
||||||
async function getDatasetsAllowedForCompute() {
|
async function getDatasetsAllowedForCompute() {
|
||||||
const isCompute = Boolean(getServiceByName(ddo, 'compute'))
|
const isCompute = Boolean(getServiceByName(asset, 'compute'))
|
||||||
const datasetComputeService = getServiceByName(
|
const datasetComputeService = getServiceByName(
|
||||||
ddo,
|
asset,
|
||||||
isCompute ? 'compute' : 'access'
|
isCompute ? 'compute' : 'access'
|
||||||
)
|
)
|
||||||
const datasets = await getAlgorithmDatasetsForCompute(
|
const datasets = await getAlgorithmDatasetsForCompute(
|
||||||
algorithmDid,
|
algorithmDid,
|
||||||
datasetComputeService?.serviceEndpoint,
|
datasetComputeService?.serviceEndpoint,
|
||||||
ddo?.chainId,
|
asset?.chainId,
|
||||||
newCancelToken()
|
newCancelToken()
|
||||||
)
|
)
|
||||||
setDatasetsForCompute(datasets)
|
setDatasetsForCompute(datasets)
|
||||||
}
|
}
|
||||||
ddo.metadata.type === 'algorithm' && getDatasetsAllowedForCompute()
|
asset.metadata.type === 'algorithm' && getDatasetsAllowedForCompute()
|
||||||
}, [ddo?.metadata?.type])
|
}, [asset?.metadata?.type])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.datasetsContainer}>
|
<div className={styles.datasetsContainer}>
|
||||||
|
@ -10,6 +10,7 @@ import { useAsset } from '@context/Asset'
|
|||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
||||||
import content from '../../../../../content/pages/startComputeDataset.json'
|
import content from '../../../../../content/pages/startComputeDataset.json'
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
import { Asset } from '@oceanprotocol/lib'
|
||||||
|
import { AccessDetails } from 'src/@types/Price'
|
||||||
|
|
||||||
export default function FormStartCompute({
|
export default function FormStartCompute({
|
||||||
algorithms,
|
algorithms,
|
||||||
@ -106,7 +107,7 @@ export default function FormStartCompute({
|
|||||||
? 0
|
? 0
|
||||||
: Number(algorithmConsumeDetails.price)
|
: Number(algorithmConsumeDetails.price)
|
||||||
|
|
||||||
setTotalPrice(priceDataset + priceAlgo)
|
setTotalPrice((priceDataset + priceAlgo).toString())
|
||||||
}, [
|
}, [
|
||||||
asset?.accessDetails,
|
asset?.accessDetails,
|
||||||
algorithmConsumeDetails,
|
algorithmConsumeDetails,
|
||||||
@ -145,7 +146,7 @@ export default function FormStartCompute({
|
|||||||
hasDatatokenSelectedComputeAsset={hasDatatokenSelectedComputeAsset}
|
hasDatatokenSelectedComputeAsset={hasDatatokenSelectedComputeAsset}
|
||||||
algorithmConsumeDetails={algorithmConsumeDetails}
|
algorithmConsumeDetails={algorithmConsumeDetails}
|
||||||
symbol={oceanSymbol}
|
symbol={oceanSymbol}
|
||||||
totalPrice={totalPrice}
|
totalPrice={Number.parseFloat(totalPrice)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ButtonBuy
|
<ButtonBuy
|
||||||
|
@ -3,6 +3,7 @@ import { useAsset } from '@context/Asset'
|
|||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
import PriceUnit from '@shared/Price/PriceUnit'
|
||||||
import Tooltip from '@shared/atoms/Tooltip'
|
import Tooltip from '@shared/atoms/Tooltip'
|
||||||
import styles from './PriceOutput.module.css'
|
import styles from './PriceOutput.module.css'
|
||||||
|
import { AccessDetails } from 'src/@types/Price'
|
||||||
|
|
||||||
interface PriceOutputProps {
|
interface PriceOutputProps {
|
||||||
totalPrice: number
|
totalPrice: number
|
||||||
@ -74,14 +75,14 @@ export default function PriceOutput({
|
|||||||
<Row
|
<Row
|
||||||
hasPreviousOrder={hasPreviousOrder}
|
hasPreviousOrder={hasPreviousOrder}
|
||||||
hasDatatoken={hasDatatoken}
|
hasDatatoken={hasDatatoken}
|
||||||
price={asset?.accessDetails?.price}
|
price={Number.parseFloat(asset?.accessDetails?.price)}
|
||||||
timeout={assetTimeout}
|
timeout={assetTimeout}
|
||||||
symbol={symbol}
|
symbol={symbol}
|
||||||
/>
|
/>
|
||||||
<Row
|
<Row
|
||||||
hasPreviousOrder={hasPreviousOrderSelectedComputeAsset}
|
hasPreviousOrder={hasPreviousOrderSelectedComputeAsset}
|
||||||
hasDatatoken={hasDatatokenSelectedComputeAsset}
|
hasDatatoken={hasDatatokenSelectedComputeAsset}
|
||||||
price={algorithmConsumeDetails?.price}
|
price={Number.parseFloat(algorithmConsumeDetails?.price)}
|
||||||
timeout={selectedComputeAssetTimeout}
|
timeout={selectedComputeAssetTimeout}
|
||||||
symbol={symbol}
|
symbol={symbol}
|
||||||
sign="+"
|
sign="+"
|
||||||
|
@ -14,7 +14,6 @@ import FileIcon from '@shared/FileIcon'
|
|||||||
import Alert from '@shared/atoms/Alert'
|
import Alert from '@shared/atoms/Alert'
|
||||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
||||||
import { usePricing } from '@hooks/usePricing'
|
|
||||||
import {
|
import {
|
||||||
generateBaseQuery,
|
generateBaseQuery,
|
||||||
getFilterTerm,
|
getFilterTerm,
|
||||||
@ -37,6 +36,7 @@ import { useCancelToken } from '@hooks/useCancelToken'
|
|||||||
import { useIsMounted } from '@hooks/useIsMounted'
|
import { useIsMounted } from '@hooks/useIsMounted'
|
||||||
import { SortTermOptions } from '../../../../@types/aquarius/SearchQuery'
|
import { SortTermOptions } from '../../../../@types/aquarius/SearchQuery'
|
||||||
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
|
import { getAccessDetails } from '@utils/accessDetailsAndPricing'
|
||||||
|
import { AccessDetails } from 'src/@types/Price'
|
||||||
|
|
||||||
export default function Compute({
|
export default function Compute({
|
||||||
ddo,
|
ddo,
|
||||||
@ -57,7 +57,6 @@ export default function Compute({
|
|||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { appConfig } = useSiteMetadata()
|
const { appConfig } = useSiteMetadata()
|
||||||
const { accountId } = useWeb3()
|
const { accountId } = useWeb3()
|
||||||
const { buyDT, pricingError, pricingStepText } = usePricing()
|
|
||||||
const [isJobStarting, setIsJobStarting] = useState(false)
|
const [isJobStarting, setIsJobStarting] = useState(false)
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
|
|
||||||
@ -181,13 +180,13 @@ export default function Compute({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!algorithmConsumeDetails) return
|
if (!algorithmConsumeDetails) return
|
||||||
|
|
||||||
setIsAlgoConsumablePrice(algorithmConsumeDetails.isConsumable)
|
setIsAlgoConsumablePrice(algorithmConsumeDetails.isPurchasable)
|
||||||
}, [algorithmConsumeDetails])
|
}, [algorithmConsumeDetails])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accessDetails) return
|
if (!accessDetails) return
|
||||||
|
|
||||||
setIsConsumablePrice(accessDetails.isConsumable)
|
setIsConsumablePrice(accessDetails.isPurchasable)
|
||||||
}, [accessDetails])
|
}, [accessDetails])
|
||||||
|
|
||||||
// useEffect(() => {
|
// useEffect(() => {
|
||||||
@ -234,10 +233,10 @@ export default function Compute({
|
|||||||
|
|
||||||
// Output errors in toast UI
|
// Output errors in toast UI
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newError = error || pricingError
|
const newError = error
|
||||||
if (!newError) return
|
if (!newError) return
|
||||||
toast.error(newError)
|
toast.error(newError)
|
||||||
}, [error, pricingError])
|
}, [error])
|
||||||
|
|
||||||
// async function startJob(algorithmId: string) {
|
// async function startJob(algorithmId: string) {
|
||||||
// try {
|
// try {
|
||||||
@ -400,7 +399,7 @@ export default function Compute({
|
|||||||
text="This algorithm has been set to private by the publisher and can't be downloaded. You can run it against any allowed data sets though!"
|
text="This algorithm has been set to private by the publisher and can't be downloaded. You can run it against any allowed data sets though!"
|
||||||
state="info"
|
state="info"
|
||||||
/>
|
/>
|
||||||
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} ddo={ddo} />
|
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} asset={ddo} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Formik
|
<Formik
|
||||||
@ -433,7 +432,8 @@ export default function Compute({
|
|||||||
selectedComputeAssetLowPoolLiquidity={!isAlgoConsumablePrice}
|
selectedComputeAssetLowPoolLiquidity={!isAlgoConsumablePrice}
|
||||||
selectedComputeAssetType="algorithm"
|
selectedComputeAssetType="algorithm"
|
||||||
selectedComputeAssetTimeout={algorithmTimeout}
|
selectedComputeAssetTimeout={algorithmTimeout}
|
||||||
stepText={pricingStepText || 'Starting Compute Job...'}
|
// lazy comment when removing pricingStepText
|
||||||
|
stepText={'pricingStepText' || 'Starting Compute Job...'}
|
||||||
algorithmConsumeDetails={algorithmConsumeDetails}
|
algorithmConsumeDetails={algorithmConsumeDetails}
|
||||||
isConsumable={isConsumable}
|
isConsumable={isConsumable}
|
||||||
consumableFeedback={consumableFeedback}
|
consumableFeedback={consumableFeedback}
|
||||||
|
@ -1,154 +0,0 @@
|
|||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
|
||||||
import { toast } from 'react-toastify'
|
|
||||||
import FileIcon from '@shared/FileIcon'
|
|
||||||
import Price from '@shared/Price'
|
|
||||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
|
||||||
import { useAsset } from '@context/Asset'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
import { usePricing } from '@hooks/usePricing'
|
|
||||||
import { useConsume } from '@hooks/useConsume'
|
|
||||||
import ButtonBuy from '@shared/ButtonBuy'
|
|
||||||
import { secondsToString } from '@utils/ddo'
|
|
||||||
import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute'
|
|
||||||
import styles from './Consume.module.css'
|
|
||||||
import { useIsMounted } from '@hooks/useIsMounted'
|
|
||||||
import { Asset, FileMetadata } from '@oceanprotocol/lib'
|
|
||||||
|
|
||||||
export default function Consume({
|
|
||||||
ddo,
|
|
||||||
accessDetails,
|
|
||||||
file,
|
|
||||||
isBalanceSufficient,
|
|
||||||
dtBalance,
|
|
||||||
fileIsLoading,
|
|
||||||
isConsumable,
|
|
||||||
consumableFeedback
|
|
||||||
}: {
|
|
||||||
ddo: Asset
|
|
||||||
accessDetails: AccessDetails
|
|
||||||
file: FileMetadata
|
|
||||||
isBalanceSufficient: boolean
|
|
||||||
dtBalance: string
|
|
||||||
fileIsLoading?: boolean
|
|
||||||
isConsumable?: boolean
|
|
||||||
consumableFeedback?: string
|
|
||||||
}): ReactElement {
|
|
||||||
const { accountId } = useWeb3()
|
|
||||||
const { appConfig } = useSiteMetadata()
|
|
||||||
const [hasPreviousOrder, setHasPreviousOrder] = useState(false)
|
|
||||||
const [previousOrderId, setPreviousOrderId] = useState<string>()
|
|
||||||
const { isInPurgatory, isAssetNetwork } = useAsset()
|
|
||||||
const { buyDT, pricingStepText, pricingError, pricingIsLoading } =
|
|
||||||
usePricing()
|
|
||||||
const { consumeStepText, consume, consumeError, isLoading } = useConsume()
|
|
||||||
const [isDisabled, setIsDisabled] = useState(true)
|
|
||||||
const [hasDatatoken, setHasDatatoken] = useState(false)
|
|
||||||
const [isConsumablePrice, setIsConsumablePrice] = useState(true)
|
|
||||||
const [assetTimeout, setAssetTimeout] = useState('')
|
|
||||||
const isMounted = useIsMounted()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!ddo) return
|
|
||||||
|
|
||||||
const { timeout } = ddo.services[0]
|
|
||||||
setAssetTimeout(`${timeout}`)
|
|
||||||
}, [ddo])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!accessDetails) return
|
|
||||||
|
|
||||||
setIsConsumablePrice(accessDetails.isConsumable)
|
|
||||||
setHasPreviousOrder(accessDetails.owned)
|
|
||||||
setPreviousOrderId(accessDetails.validOrderTx)
|
|
||||||
}, [accessDetails])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setHasDatatoken(Number(dtBalance) >= 1)
|
|
||||||
}, [dtBalance])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!accountId) return
|
|
||||||
setIsDisabled(
|
|
||||||
!isConsumable ||
|
|
||||||
((!isBalanceSufficient ||
|
|
||||||
!isAssetNetwork ||
|
|
||||||
typeof consumeStepText !== 'undefined' ||
|
|
||||||
pricingIsLoading ||
|
|
||||||
!isConsumablePrice) &&
|
|
||||||
!hasPreviousOrder &&
|
|
||||||
!hasDatatoken)
|
|
||||||
)
|
|
||||||
}, [
|
|
||||||
hasPreviousOrder,
|
|
||||||
isBalanceSufficient,
|
|
||||||
isAssetNetwork,
|
|
||||||
consumeStepText,
|
|
||||||
pricingIsLoading,
|
|
||||||
isConsumablePrice,
|
|
||||||
hasDatatoken,
|
|
||||||
isConsumable,
|
|
||||||
accountId
|
|
||||||
])
|
|
||||||
|
|
||||||
async function handleConsume() {
|
|
||||||
// if (!hasPreviousOrder && !hasDatatoken) {
|
|
||||||
// const tx = await buyDT('1', price, ddo)
|
|
||||||
// if (tx === undefined) return
|
|
||||||
// }
|
|
||||||
const error = await consume(
|
|
||||||
ddo.id,
|
|
||||||
ddo.services[0].datatokenAddress,
|
|
||||||
'access',
|
|
||||||
appConfig.marketFeeAddress,
|
|
||||||
previousOrderId
|
|
||||||
)
|
|
||||||
error || setHasPreviousOrder(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Output errors in UI
|
|
||||||
useEffect(() => {
|
|
||||||
consumeError && toast.error(consumeError)
|
|
||||||
}, [consumeError])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
pricingError && toast.error(pricingError)
|
|
||||||
}, [pricingError])
|
|
||||||
|
|
||||||
const PurchaseButton = () => (
|
|
||||||
<ButtonBuy
|
|
||||||
action="download"
|
|
||||||
disabled={isDisabled}
|
|
||||||
hasPreviousOrder={hasPreviousOrder}
|
|
||||||
hasDatatoken={hasDatatoken}
|
|
||||||
dtSymbol={ddo?.datatokens[0]?.symbol}
|
|
||||||
dtBalance={dtBalance}
|
|
||||||
datasetLowPoolLiquidity={!isConsumablePrice}
|
|
||||||
onClick={handleConsume}
|
|
||||||
assetTimeout={secondsToString(parseInt(assetTimeout))}
|
|
||||||
assetType={ddo?.metadata?.type}
|
|
||||||
stepText={consumeStepText || pricingStepText}
|
|
||||||
isLoading={pricingIsLoading || isLoading}
|
|
||||||
priceType={accessDetails?.type}
|
|
||||||
isConsumable={isConsumable}
|
|
||||||
isBalanceSufficient={isBalanceSufficient}
|
|
||||||
consumableFeedback={consumableFeedback}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<aside className={styles.consume}>
|
|
||||||
<div className={styles.info}>
|
|
||||||
<div className={styles.filewrapper}>
|
|
||||||
<FileIcon file={file} isLoading={fileIsLoading} />
|
|
||||||
</div>
|
|
||||||
<div className={styles.pricewrapper}>
|
|
||||||
<Price accessDetails={accessDetails} conversion />
|
|
||||||
{!isInPurgatory && <PurchaseButton />}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{ddo?.metadata?.type === 'algorithm' && (
|
|
||||||
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} ddo={ddo} />
|
|
||||||
)}
|
|
||||||
</aside>
|
|
||||||
)
|
|
||||||
}
|
|
175
src/components/Asset/AssetActions/Download.tsx
Normal file
175
src/components/Asset/AssetActions/Download.tsx
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
import React, { ReactElement, useEffect, useState } from 'react'
|
||||||
|
import FileIcon from '@shared/FileIcon'
|
||||||
|
import Price from '@shared/Price'
|
||||||
|
import { useAsset } from '@context/Asset'
|
||||||
|
import { useWeb3 } from '@context/Web3'
|
||||||
|
import ButtonBuy from '@shared/ButtonBuy'
|
||||||
|
import { secondsToString } from '@utils/ddo'
|
||||||
|
import AlgorithmDatasetsListForCompute from './Compute/AlgorithmDatasetsListForCompute'
|
||||||
|
import styles from './Download.module.css'
|
||||||
|
import { FileMetadata, LoggerInstance, ZERO_ADDRESS } from '@oceanprotocol/lib'
|
||||||
|
import { order } from '@utils/order'
|
||||||
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
import { buyDtFromPool, calculateBuyPrice } from '@utils/pool'
|
||||||
|
import { downloadFile } from '@utils/provider'
|
||||||
|
import { getOrderFeedback } from '@utils/feedback'
|
||||||
|
import { getOrderPriceAndFees } from '@utils/accessDetailsAndPricing'
|
||||||
|
import { OrderPriceAndFees } from 'src/@types/Price'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
|
||||||
|
export default function Download({
|
||||||
|
asset,
|
||||||
|
file,
|
||||||
|
isBalanceSufficient,
|
||||||
|
dtBalance,
|
||||||
|
fileIsLoading,
|
||||||
|
consumableFeedback
|
||||||
|
}: {
|
||||||
|
asset: AssetExtended
|
||||||
|
file: FileMetadata
|
||||||
|
isBalanceSufficient: boolean
|
||||||
|
dtBalance: string
|
||||||
|
fileIsLoading?: boolean
|
||||||
|
consumableFeedback?: string
|
||||||
|
}): ReactElement {
|
||||||
|
const { accountId, web3 } = useWeb3()
|
||||||
|
const { isInPurgatory, isAssetNetwork } = useAsset()
|
||||||
|
const [isDisabled, setIsDisabled] = useState(true)
|
||||||
|
const [hasDatatoken, setHasDatatoken] = useState(false)
|
||||||
|
const [statusText, setStatusText] = useState('')
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [isOwned, setIsOwned] = useState(false)
|
||||||
|
const [validOrderTx, setValidOrderTx] = useState('')
|
||||||
|
const [orderPriceAndFees, setOrderPriceAndFees] =
|
||||||
|
useState<OrderPriceAndFees>()
|
||||||
|
useEffect(() => {
|
||||||
|
if (!asset?.accessDetails) return
|
||||||
|
|
||||||
|
setIsOwned(asset?.accessDetails?.isOwned)
|
||||||
|
setValidOrderTx(asset?.accessDetails?.validOrderTx)
|
||||||
|
// get full price and fees
|
||||||
|
async function init() {
|
||||||
|
if (asset?.accessDetails?.addressOrId === ZERO_ADDRESS) return
|
||||||
|
setIsLoading(true)
|
||||||
|
setStatusText('Calculating price including fees.')
|
||||||
|
const orderPriceAndFees = await getOrderPriceAndFees(asset, ZERO_ADDRESS)
|
||||||
|
setOrderPriceAndFees(orderPriceAndFees)
|
||||||
|
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
init()
|
||||||
|
}, [asset, accountId])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setHasDatatoken(Number(dtBalance) >= 1)
|
||||||
|
}, [dtBalance])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!accountId || !asset?.accessDetails) return
|
||||||
|
setIsDisabled(
|
||||||
|
!asset?.accessDetails.isPurchasable ||
|
||||||
|
((!isBalanceSufficient || !isAssetNetwork) && !isOwned && !hasDatatoken)
|
||||||
|
)
|
||||||
|
}, [
|
||||||
|
asset?.accessDetails,
|
||||||
|
isBalanceSufficient,
|
||||||
|
isAssetNetwork,
|
||||||
|
hasDatatoken,
|
||||||
|
accountId,
|
||||||
|
isOwned
|
||||||
|
])
|
||||||
|
|
||||||
|
async function handleOrderOrDownload() {
|
||||||
|
setIsLoading(true)
|
||||||
|
if (isOwned) {
|
||||||
|
setStatusText(
|
||||||
|
getOrderFeedback(
|
||||||
|
asset.accessDetails?.baseToken?.symbol,
|
||||||
|
asset.accessDetails?.datatoken?.symbol
|
||||||
|
)[3]
|
||||||
|
)
|
||||||
|
await downloadFile(web3, asset, accountId, validOrderTx)
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (!hasDatatoken && asset.accessDetails.type === 'dynamic') {
|
||||||
|
setStatusText(
|
||||||
|
getOrderFeedback(
|
||||||
|
asset.accessDetails.baseToken?.symbol,
|
||||||
|
asset.accessDetails.datatoken?.symbol
|
||||||
|
)[0]
|
||||||
|
)
|
||||||
|
|
||||||
|
const tx = await buyDtFromPool(asset.accessDetails, accountId, web3)
|
||||||
|
|
||||||
|
if (!tx) {
|
||||||
|
toast.error('Failed to buy datatoken from pool!')
|
||||||
|
setIsLoading(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setStatusText(
|
||||||
|
getOrderFeedback(
|
||||||
|
asset.accessDetails.baseToken?.symbol,
|
||||||
|
asset.accessDetails.datatoken?.symbol
|
||||||
|
)[asset.accessDetails?.type === 'fixed' ? 2 : 1]
|
||||||
|
)
|
||||||
|
const orderTx = await order(web3, asset, orderPriceAndFees, accountId)
|
||||||
|
|
||||||
|
setIsOwned(true)
|
||||||
|
setValidOrderTx(orderTx.transactionHash)
|
||||||
|
} catch (ex) {
|
||||||
|
LoggerInstance.log(ex.message)
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsLoading(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const PurchaseButton = () => (
|
||||||
|
<ButtonBuy
|
||||||
|
action="download"
|
||||||
|
disabled={isDisabled}
|
||||||
|
hasPreviousOrder={isOwned}
|
||||||
|
hasDatatoken={hasDatatoken}
|
||||||
|
dtSymbol={asset?.datatokens[0]?.symbol}
|
||||||
|
dtBalance={dtBalance}
|
||||||
|
datasetLowPoolLiquidity={!asset.accessDetails?.isPurchasable}
|
||||||
|
onClick={handleOrderOrDownload}
|
||||||
|
assetTimeout={secondsToString(asset.services[0].timeout)}
|
||||||
|
assetType={asset?.metadata?.type}
|
||||||
|
stepText={statusText}
|
||||||
|
// isLoading={pricingIsLoading || isLoading}
|
||||||
|
isLoading={isLoading}
|
||||||
|
priceType={asset.accessDetails?.type}
|
||||||
|
isConsumable={asset.accessDetails?.isPurchasable}
|
||||||
|
isBalanceSufficient={isBalanceSufficient}
|
||||||
|
consumableFeedback={consumableFeedback}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<aside className={styles.consume}>
|
||||||
|
<div className={styles.info}>
|
||||||
|
<div className={styles.filewrapper}>
|
||||||
|
<FileIcon file={file} isLoading={fileIsLoading} />
|
||||||
|
</div>
|
||||||
|
<div className={styles.pricewrapper}>
|
||||||
|
<Price
|
||||||
|
accessDetails={asset.accessDetails}
|
||||||
|
orderPriceAndFees={orderPriceAndFees}
|
||||||
|
conversion
|
||||||
|
/>
|
||||||
|
{!isInPurgatory && <PurchaseButton />}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{asset?.metadata?.type === 'algorithm' && (
|
||||||
|
<AlgorithmDatasetsListForCompute
|
||||||
|
algorithmDid={asset.id}
|
||||||
|
asset={asset}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import React, { ReactElement, useState, useEffect } from 'react'
|
import React, { ReactElement, useState, useEffect } from 'react'
|
||||||
import Compute from './Compute'
|
import Compute from './Compute'
|
||||||
import Consume from './Consume'
|
import Consume from './Download'
|
||||||
import { FileMetadata, LoggerInstance, Datatoken } from '@oceanprotocol/lib'
|
import { FileMetadata, LoggerInstance, Datatoken } from '@oceanprotocol/lib'
|
||||||
import Tabs, { TabsItem } from '@shared/atoms/Tabs'
|
import Tabs, { TabsItem } from '@shared/atoms/Tabs'
|
||||||
import { compareAsBN } from '@utils/numbers'
|
import { compareAsBN } from '@utils/numbers'
|
||||||
@ -141,13 +141,11 @@ export default function AssetActions({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Consume
|
<Consume
|
||||||
ddo={asset}
|
asset={asset}
|
||||||
accessDetails={asset?.accessDetails}
|
|
||||||
dtBalance={dtBalance}
|
dtBalance={dtBalance}
|
||||||
isBalanceSufficient={isBalanceSufficient}
|
isBalanceSufficient={isBalanceSufficient}
|
||||||
file={fileMetadata}
|
file={fileMetadata}
|
||||||
fileIsLoading={fileIsLoading}
|
fileIsLoading={fileIsLoading}
|
||||||
isConsumable={isConsumable}
|
|
||||||
consumableFeedback={consumableFeedback}
|
consumableFeedback={consumableFeedback}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -4,37 +4,36 @@ import { FormPublishData } from '../_types'
|
|||||||
import { useFormikContext } from 'formik'
|
import { useFormikContext } from 'formik'
|
||||||
import AssetContent from 'src/components/Asset/AssetContent'
|
import AssetContent from 'src/components/Asset/AssetContent'
|
||||||
import { transformPublishFormToDdo } from '../_utils'
|
import { transformPublishFormToDdo } from '../_utils'
|
||||||
import { Asset } from '@oceanprotocol/lib'
|
import { AssetExtended } from 'src/@types/AssetExtended'
|
||||||
|
import { ZERO_ADDRESS } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
export default function Preview(): ReactElement {
|
export default function Preview(): ReactElement {
|
||||||
const [asset, setAsset] = useState<Asset>()
|
const [asset, setAsset] = useState<AssetExtended>()
|
||||||
const [accessDetails, setAccessDetails] = useState<AccessDetails>()
|
|
||||||
const { values } = useFormikContext<FormPublishData>()
|
const { values } = useFormikContext<FormPublishData>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function makeDdo() {
|
async function makeDdo() {
|
||||||
const asset = await transformPublishFormToDdo(values)
|
const asset = (await transformPublishFormToDdo(values)) as AssetExtended
|
||||||
setAsset(asset as Asset)
|
|
||||||
|
|
||||||
// dummy BestPrice to trigger certain AssetActions
|
// dummy BestPrice to trigger certain AssetActions
|
||||||
const accessDetails: AccessDetails = {
|
asset.accessDetails = {
|
||||||
type: values.pricing.type,
|
type: values.pricing.type,
|
||||||
addressOrId: '0x...',
|
addressOrId: ZERO_ADDRESS,
|
||||||
price: values.pricing.price,
|
price: values.pricing.price,
|
||||||
baseToken: {
|
baseToken: {
|
||||||
address: '0x..',
|
address: ZERO_ADDRESS,
|
||||||
name: '',
|
name: 'OCEAN',
|
||||||
symbol: ''
|
symbol: 'OCEAN'
|
||||||
},
|
},
|
||||||
datatoken: {
|
datatoken: {
|
||||||
address: '0x..',
|
address: ZERO_ADDRESS,
|
||||||
name: '',
|
name: '',
|
||||||
symbol: ''
|
symbol: ''
|
||||||
},
|
},
|
||||||
owned: false,
|
isPurchasable: true,
|
||||||
|
isOwned: false,
|
||||||
validOrderTx: ''
|
validOrderTx: ''
|
||||||
}
|
}
|
||||||
setAccessDetails(accessDetails)
|
setAsset(asset)
|
||||||
}
|
}
|
||||||
makeDdo()
|
makeDdo()
|
||||||
}, [values])
|
}, [values])
|
||||||
@ -44,7 +43,7 @@ export default function Preview(): ReactElement {
|
|||||||
<h2 className={styles.previewTitle}>Preview</h2>
|
<h2 className={styles.previewTitle}>Preview</h2>
|
||||||
|
|
||||||
<h3 className={styles.assetTitle}>{values.metadata.name}</h3>
|
<h3 className={styles.assetTitle}>{values.metadata.name}</h3>
|
||||||
<AssetContent asset={asset} />
|
{asset && <AssetContent asset={asset} />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,14 @@ export default function PricingFields(): ReactElement {
|
|||||||
: 0
|
: 0
|
||||||
|
|
||||||
setFieldValue('pricing.amountDataToken', amountDataToken)
|
setFieldValue('pricing.amountDataToken', amountDataToken)
|
||||||
}, [price, amountOcean, weightOnOcean, weightOnDataToken, type])
|
}, [
|
||||||
|
price,
|
||||||
|
amountOcean,
|
||||||
|
weightOnOcean,
|
||||||
|
weightOnDataToken,
|
||||||
|
type,
|
||||||
|
setFieldValue
|
||||||
|
])
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
appConfig.allowFixedPricing === 'true'
|
appConfig.allowFixedPricing === 'true'
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ServiceComputeOptions } from '@oceanprotocol/lib'
|
import { ServiceComputeOptions } from '@oceanprotocol/lib'
|
||||||
import { NftMetadata } from '@utils/nft'
|
import { NftMetadata } from '@utils/nft'
|
||||||
import { ReactElement } from 'react'
|
import { ReactElement } from 'react'
|
||||||
|
import { PriceOptions } from 'src/@types/Price'
|
||||||
|
|
||||||
interface FileMetadata {
|
interface FileMetadata {
|
||||||
url: string
|
url: string
|
||||||
|
@ -18,6 +18,8 @@ import {
|
|||||||
import { mapTimeoutStringToSeconds } from '@utils/ddo'
|
import { mapTimeoutStringToSeconds } from '@utils/ddo'
|
||||||
import { generateNftCreateData } from '@utils/nft'
|
import { generateNftCreateData } from '@utils/nft'
|
||||||
import { getEncryptedFiles } from '@utils/provider'
|
import { getEncryptedFiles } from '@utils/provider'
|
||||||
|
import { getSiteMetadata } from '@utils/siteConfig'
|
||||||
|
import Decimal from 'decimal.js'
|
||||||
import slugify from 'slugify'
|
import slugify from 'slugify'
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import {
|
import {
|
||||||
@ -191,7 +193,6 @@ export async function transformPublishFormToDdo(
|
|||||||
export async function createTokensAndPricing(
|
export async function createTokensAndPricing(
|
||||||
values: FormPublishData,
|
values: FormPublishData,
|
||||||
accountId: string,
|
accountId: string,
|
||||||
marketFeeAddress: string,
|
|
||||||
config: Config,
|
config: Config,
|
||||||
nftFactory: NftFactory,
|
nftFactory: NftFactory,
|
||||||
web3: Web3
|
web3: Web3
|
||||||
@ -199,19 +200,17 @@ export async function createTokensAndPricing(
|
|||||||
const nftCreateData: NftCreateData = generateNftCreateData(
|
const nftCreateData: NftCreateData = generateNftCreateData(
|
||||||
values.metadata.nft
|
values.metadata.nft
|
||||||
)
|
)
|
||||||
|
const { appConfig } = getSiteMetadata()
|
||||||
LoggerInstance.log('[publish] Creating NFT with metadata', nftCreateData)
|
LoggerInstance.log('[publish] Creating NFT with metadata', nftCreateData)
|
||||||
|
|
||||||
// TODO: cap is hardcoded for now to 1000, this needs to be discussed at some point
|
// TODO: cap is hardcoded for now to 1000, this needs to be discussed at some point
|
||||||
// fee is default 0 for now
|
|
||||||
// TODO: templateIndex is hardcoded for now but this is incorrect, in the future it should be something like 1 for pools, and 2 for fre and free
|
|
||||||
const ercParams: Erc20CreateParams = {
|
const ercParams: Erc20CreateParams = {
|
||||||
templateIndex: values.pricing.type === 'dynamic' ? 1 : 2,
|
templateIndex: values.pricing.type === 'dynamic' ? 1 : 2,
|
||||||
minter: accountId,
|
minter: accountId,
|
||||||
feeManager: accountId,
|
feeManager: accountId,
|
||||||
mpFeeAddress: marketFeeAddress,
|
mpFeeAddress: appConfig.marketFeeAddress,
|
||||||
feeToken: config.oceanTokenAddress,
|
feeToken: config.oceanTokenAddress,
|
||||||
feeAmount: `0`,
|
feeAmount: appConfig.publisherMarketOrderFee,
|
||||||
cap: '1000',
|
cap: '1000',
|
||||||
name: values.services[0].dataTokenOptions.name,
|
name: values.services[0].dataTokenOptions.name,
|
||||||
symbol: values.services[0].dataTokenOptions.symbol
|
symbol: values.services[0].dataTokenOptions.symbol
|
||||||
@ -226,21 +225,22 @@ export async function createTokensAndPricing(
|
|||||||
case 'dynamic': {
|
case 'dynamic': {
|
||||||
// no vesting in market by default, maybe at a later time , vestingAmount and vestedBlocks are hardcoded
|
// no vesting in market by default, maybe at a later time , vestingAmount and vestedBlocks are hardcoded
|
||||||
// we use only ocean as basetoken
|
// we use only ocean as basetoken
|
||||||
// TODO: discuss swapFeeLiquidityProvider, swapFeeMarketPlaceRunner
|
// swapFeeLiquidityProvider is the swap fee of the liquidity providers
|
||||||
|
// swapFeeMarketRunner is the swap fee of the market where the swap occurs
|
||||||
const poolParams: PoolCreationParams = {
|
const poolParams: PoolCreationParams = {
|
||||||
ssContract: config.sideStakingAddress,
|
ssContract: config.sideStakingAddress,
|
||||||
baseTokenAddress: config.oceanTokenAddress,
|
baseTokenAddress: config.oceanTokenAddress,
|
||||||
baseTokenSender: config.erc721FactoryAddress,
|
baseTokenSender: config.erc721FactoryAddress,
|
||||||
publisherAddress: accountId,
|
publisherAddress: accountId,
|
||||||
marketFeeCollector: marketFeeAddress,
|
marketFeeCollector: appConfig.marketFeeAddress,
|
||||||
poolTemplateAddress: config.poolTemplateAddress,
|
poolTemplateAddress: config.poolTemplateAddress,
|
||||||
rate: values.pricing.price.toString(),
|
rate: new Decimal(1).div(values.pricing.price).toString(),
|
||||||
baseTokenDecimals: 18,
|
baseTokenDecimals: 18,
|
||||||
vestingAmount: '0',
|
vestingAmount: '0',
|
||||||
vestedBlocks: 2726000,
|
vestedBlocks: 2726000,
|
||||||
initialBaseTokenLiquidity: values.pricing.amountOcean.toString(),
|
initialBaseTokenLiquidity: values.pricing.amountOcean.toString(),
|
||||||
swapFeeLiquidityProvider: '0.1',
|
swapFeeLiquidityProvider: (values.pricing.swapFee / 100).toString(),
|
||||||
swapFeeMarketRunner: '0'
|
swapFeeMarketRunner: appConfig.publisherMarketPoolSwapFee
|
||||||
}
|
}
|
||||||
|
|
||||||
LoggerInstance.log(
|
LoggerInstance.log(
|
||||||
@ -249,16 +249,15 @@ export async function createTokensAndPricing(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// the spender in this case is the erc721Factory because we are delegating
|
// the spender in this case is the erc721Factory because we are delegating
|
||||||
const pool = new Pool(web3)
|
|
||||||
const txApprove = await approve(
|
const txApprove = await approve(
|
||||||
web3,
|
web3,
|
||||||
accountId,
|
accountId,
|
||||||
config.oceanTokenAddress,
|
config.oceanTokenAddress,
|
||||||
config.erc721FactoryAddress,
|
config.erc721FactoryAddress,
|
||||||
'200',
|
values.pricing.amountOcean.toString(),
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
LoggerInstance.log('[publish] pool.approve tx', txApprove)
|
LoggerInstance.log('[publish] pool.approve tx', txApprove, nftFactory)
|
||||||
|
|
||||||
const result = await nftFactory.createNftErc20WithPool(
|
const result = await nftFactory.createNftErc20WithPool(
|
||||||
accountId,
|
accountId,
|
||||||
@ -279,11 +278,11 @@ export async function createTokensAndPricing(
|
|||||||
fixedRateAddress: config.fixedRateExchangeAddress,
|
fixedRateAddress: config.fixedRateExchangeAddress,
|
||||||
baseTokenAddress: config.oceanTokenAddress,
|
baseTokenAddress: config.oceanTokenAddress,
|
||||||
owner: accountId,
|
owner: accountId,
|
||||||
marketFeeCollector: marketFeeAddress,
|
marketFeeCollector: appConfig.marketFeeAddress,
|
||||||
baseTokenDecimals: 18,
|
baseTokenDecimals: 18,
|
||||||
datatokenDecimals: 18,
|
datatokenDecimals: 18,
|
||||||
fixedRate: values.pricing.price.toString(),
|
fixedRate: values.pricing.price.toString(),
|
||||||
marketFee: '0',
|
marketFee: appConfig.publisherMarketFixedSwapFee,
|
||||||
withMint: true
|
withMint: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ import {
|
|||||||
LoggerInstance,
|
LoggerInstance,
|
||||||
DDO
|
DDO
|
||||||
} from '@oceanprotocol/lib'
|
} from '@oceanprotocol/lib'
|
||||||
import { useSiteMetadata } from '@hooks/useSiteMetadata'
|
|
||||||
import { getOceanConfig } from '@utils/ocean'
|
import { getOceanConfig } from '@utils/ocean'
|
||||||
import { validationSchema } from './_validation'
|
import { validationSchema } from './_validation'
|
||||||
import { useAbortController } from '@hooks/useAbortController'
|
import { useAbortController } from '@hooks/useAbortController'
|
||||||
@ -38,7 +37,6 @@ export default function PublishPage({
|
|||||||
const { accountId, web3, chainId } = useWeb3()
|
const { accountId, web3, chainId } = useWeb3()
|
||||||
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
const { isInPurgatory, purgatoryData } = useAccountPurgatory(accountId)
|
||||||
const scrollToRef = useRef()
|
const scrollToRef = useRef()
|
||||||
const { appConfig } = useSiteMetadata()
|
|
||||||
const nftFactory = useNftFactory()
|
const nftFactory = useNftFactory()
|
||||||
const newAbortController = useAbortController()
|
const newAbortController = useAbortController()
|
||||||
|
|
||||||
@ -75,7 +73,6 @@ export default function PublishPage({
|
|||||||
await createTokensAndPricing(
|
await createTokensAndPricing(
|
||||||
values,
|
values,
|
||||||
accountId,
|
accountId,
|
||||||
appConfig.marketFeeAddress,
|
|
||||||
config,
|
config,
|
||||||
nftFactory,
|
nftFactory,
|
||||||
web3
|
web3
|
||||||
|
Loading…
Reference in New Issue
Block a user