mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
[EPIC] Free Pricing (#681)
* Free Pricing Option at create Pricing (#621) * Free Pricing Option + env var toggle * Create Pricing step msg * Default 'allowFreePricing' to true temp for review * Fix price 0 on free tab * Attempt fix useSiteMetadata * Fix linting * Feature/free price support consume compute (#654) * Update fetch free price * Feedback change UI remove 0's * update button msg && fix * compute algorithm list show 'Free' instead of '0' * updateMetadata() v3 workaround solution for free pricing (#677) * compute algorithm list show 'Free' instead of '0' * workaround editMetaData free price * utils function for compute & download * `allowFreePricing` default to false
This commit is contained in:
parent
eb8c6afb62
commit
e02babf2c2
@ -11,5 +11,6 @@ GATSBY_NETWORK="rinkeby"
|
||||
#GATSBY_PORTIS_ID="xxx"
|
||||
#GATSBY_ALLOW_FIXED_PRICING="true"
|
||||
#GATSBY_ALLOW_DYNAMIC_PRICING="true"
|
||||
#GATSBY_ALLOW_FREE_PRICING="true"
|
||||
#GATSBY_ALLOW_ADVANCED_SETTINGS="true"
|
||||
#GATSBY_CREDENTIAL_TYPE="address"
|
||||
|
@ -2,8 +2,7 @@ module.exports = {
|
||||
client: {
|
||||
service: {
|
||||
name: 'ocean',
|
||||
url:
|
||||
'https://subgraph.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph',
|
||||
url: 'https://subgraph.rinkeby.oceanprotocol.com/subgraphs/name/oceanprotocol/ocean-subgraph',
|
||||
// optional disable SSL validation check
|
||||
skipSSLValidation: true
|
||||
}
|
||||
|
@ -41,10 +41,11 @@ module.exports = {
|
||||
// Wallets
|
||||
portisId: process.env.GATSBY_PORTIS_ID || 'xxx',
|
||||
|
||||
// Used to show or hide the fixed and dynamic price options
|
||||
// Used to show or hide the fixed, dynamic or free price options
|
||||
// tab to publishers during the price creation.
|
||||
allowFixedPricing: process.env.GATSBY_ALLOW_FIXED_PRICING || 'true',
|
||||
allowDynamicPricing: process.env.GATSBY_ALLOW_DYNAMIC_PRICING || 'true',
|
||||
allowFreePricing: process.env.GATSBY_ALLOW_FREE_PRICING || 'false',
|
||||
|
||||
// Used to show or hide advanced settings button in asset details page
|
||||
allowAdvancedSettings: process.env.GATSBY_ALLOW_ADVANCED_SETTINGS || 'false',
|
||||
|
@ -21,6 +21,10 @@
|
||||
"communityFee": "Explain community fee...",
|
||||
"marketplaceFee": "Explain marketplace fee..."
|
||||
}
|
||||
},
|
||||
"free": {
|
||||
"title": "Free",
|
||||
"info": "Set your data set as free. The datatoken for this data set will be given for free via creating a faucet."
|
||||
}
|
||||
},
|
||||
"pool": {
|
||||
|
@ -21,6 +21,8 @@ interface ButtonBuyProps {
|
||||
onClick?: (e: FormEvent<HTMLButtonElement>) => void
|
||||
stepText?: string
|
||||
type?: 'submit'
|
||||
priceType?: string
|
||||
algorithmPriceType?: string
|
||||
}
|
||||
|
||||
function getConsumeHelpText(
|
||||
@ -87,15 +89,21 @@ export default function ButtonBuy({
|
||||
onClick,
|
||||
stepText,
|
||||
isLoading,
|
||||
type
|
||||
type,
|
||||
priceType,
|
||||
algorithmPriceType
|
||||
}: ButtonBuyProps): ReactElement {
|
||||
const buttonText =
|
||||
action === 'download'
|
||||
? hasPreviousOrder
|
||||
? 'Download'
|
||||
: priceType === 'free'
|
||||
? 'Get'
|
||||
: `Buy ${assetTimeout === 'Forever' ? '' : ` for ${assetTimeout}`}`
|
||||
: hasPreviousOrder && hasPreviousOrderSelectedComputeAsset
|
||||
? 'Start Compute Job'
|
||||
: priceType === 'free' && algorithmPriceType === 'free'
|
||||
? 'Order Compute Job'
|
||||
: `Buy Compute Job`
|
||||
|
||||
return (
|
||||
|
@ -42,15 +42,20 @@ export default function PriceUnit({
|
||||
|
||||
return (
|
||||
<div className={styleClasses}>
|
||||
<div>
|
||||
{Number.isNaN(Number(price)) ? '-' : formatPrice(price, locale)}{' '}
|
||||
<span className={styles.symbol}>{symbol || 'OCEAN'}</span>
|
||||
{type && type === 'pool' && (
|
||||
<Badge label="pool" className={styles.badge} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{conversion && <Conversion price={price} />}
|
||||
{type && type === 'free' ? (
|
||||
<div> Free </div>
|
||||
) : (
|
||||
<>
|
||||
<div>
|
||||
{Number.isNaN(Number(price)) ? '-' : formatPrice(price, locale)}{' '}
|
||||
<span className={styles.symbol}>{symbol || 'OCEAN'}</span>
|
||||
{type && type === 'pool' && (
|
||||
<Badge label="pool" className={styles.badge} />
|
||||
)}
|
||||
</div>
|
||||
{conversion && <Conversion price={price} />}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ export default function Price({
|
||||
small?: boolean
|
||||
conversion?: boolean
|
||||
}): ReactElement {
|
||||
return price?.value ? (
|
||||
return price?.value || price?.type === 'free' ? (
|
||||
<PriceUnit
|
||||
price={`${price.value}`}
|
||||
className={className}
|
||||
|
@ -107,7 +107,12 @@ export default function AssetSelection({
|
||||
</Dotdotdot>
|
||||
</label>
|
||||
|
||||
<PriceUnit price={asset.price} small className={styles.price} />
|
||||
<PriceUnit
|
||||
price={asset.price}
|
||||
type={asset.price === '0' ? 'free' : undefined}
|
||||
small
|
||||
className={styles.price}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
|
@ -166,6 +166,8 @@ export default function FormStartCompute({
|
||||
stepText={stepText}
|
||||
isLoading={isLoading}
|
||||
type="submit"
|
||||
priceType={price?.type}
|
||||
algorithmPriceType={algorithmPrice?.type}
|
||||
/>
|
||||
</Form>
|
||||
)
|
||||
|
@ -160,6 +160,7 @@ export default function Consume({
|
||||
assetType={type}
|
||||
stepText={consumeStepText || pricingStepText}
|
||||
isLoading={pricingIsLoading || isLoading}
|
||||
priceType={price?.type}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -16,6 +16,10 @@ import { useUserPreferences } from '../../../../providers/UserPreferences'
|
||||
import DebugEditCompute from './DebugEditCompute'
|
||||
import styles from './index.module.css'
|
||||
import { transformComputeFormToServiceComputePrivacy } from '../../../../utils/compute'
|
||||
import {
|
||||
setMinterToDispenser,
|
||||
setMinterToPublisher
|
||||
} from '../../../../utils/freePrice'
|
||||
|
||||
const contentQuery = graphql`
|
||||
query EditComputeDataQuery {
|
||||
@ -62,7 +66,7 @@ export default function EditComputeDataset({
|
||||
const { debug } = useUserPreferences()
|
||||
const { ocean } = useOcean()
|
||||
const { accountId } = useWeb3()
|
||||
const { ddo, refreshDdo } = useAsset()
|
||||
const { ddo, refreshDdo, price } = useAsset()
|
||||
const [success, setSuccess] = useState<string>()
|
||||
const [error, setError] = useState<string>()
|
||||
|
||||
@ -73,6 +77,15 @@ export default function EditComputeDataset({
|
||||
resetForm: () => void
|
||||
) {
|
||||
try {
|
||||
if (price.type === 'free') {
|
||||
const tx = await setMinterToPublisher(
|
||||
ocean,
|
||||
ddo.dataToken,
|
||||
accountId,
|
||||
setError
|
||||
)
|
||||
if (!tx) return
|
||||
}
|
||||
const privacy = await transformComputeFormToServiceComputePrivacy(
|
||||
values,
|
||||
ocean
|
||||
@ -99,6 +112,15 @@ export default function EditComputeDataset({
|
||||
Logger.error(content.form.error)
|
||||
return
|
||||
} else {
|
||||
if (price.type === 'free') {
|
||||
const tx = await setMinterToDispenser(
|
||||
ocean,
|
||||
ddo.dataToken,
|
||||
accountId,
|
||||
setError
|
||||
)
|
||||
if (!tx) return
|
||||
}
|
||||
// Edit succeeded
|
||||
setSuccess(content.form.success)
|
||||
resetForm()
|
||||
|
@ -18,6 +18,10 @@ import MetadataFeedback from '../../../molecules/MetadataFeedback'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import { useWeb3 } from '../../../../providers/Web3'
|
||||
import { useOcean } from '../../../../providers/Ocean'
|
||||
import {
|
||||
setMinterToDispenser,
|
||||
setMinterToPublisher
|
||||
} from '../../../../utils/freePrice'
|
||||
|
||||
const contentQuery = graphql`
|
||||
query EditMetadataQuery {
|
||||
@ -88,6 +92,15 @@ export default function Edit({
|
||||
resetForm: () => void
|
||||
) {
|
||||
try {
|
||||
if (price.type === 'free') {
|
||||
const tx = await setMinterToPublisher(
|
||||
ocean,
|
||||
ddo.dataToken,
|
||||
accountId,
|
||||
setError
|
||||
)
|
||||
if (!tx) return
|
||||
}
|
||||
// Construct new DDO with new values
|
||||
const ddoEditedMetdata = await ocean.assets.editMetadata(ddo, {
|
||||
title: values.name,
|
||||
@ -132,6 +145,15 @@ export default function Edit({
|
||||
Logger.error(content.form.error)
|
||||
return
|
||||
} else {
|
||||
if (price.type === 'free') {
|
||||
const tx = await setMinterToDispenser(
|
||||
ocean,
|
||||
ddo.dataToken,
|
||||
accountId,
|
||||
setError
|
||||
)
|
||||
if (!tx) return
|
||||
}
|
||||
// Edit succeeded
|
||||
setSuccess(content.form.success)
|
||||
resetForm()
|
||||
|
@ -65,6 +65,7 @@ export default function AssetActions(): ReactElement {
|
||||
|
||||
// Check user balance against price
|
||||
useEffect(() => {
|
||||
if (price?.type === 'free') setIsBalanceSufficient(true)
|
||||
if (!price?.value || !account || !balance?.ocean || !dtBalance) return
|
||||
|
||||
setIsBalanceSufficient(
|
||||
|
@ -0,0 +1,3 @@
|
||||
.free {
|
||||
composes: content from './index.module.css';
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import stylesIndex from './index.module.css'
|
||||
import styles from './Free.module.css'
|
||||
import FormHelp from '../../../../atoms/Input/Help'
|
||||
import { DDO } from '@oceanprotocol/lib'
|
||||
import Price from './Price'
|
||||
|
||||
export default function Free({
|
||||
ddo,
|
||||
content
|
||||
}: {
|
||||
ddo: DDO
|
||||
content: any
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={styles.free}>
|
||||
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
||||
<Price ddo={ddo} free />
|
||||
</div>
|
||||
)
|
||||
}
|
@ -10,10 +10,12 @@ import usePricing from '../../../../../hooks/usePricing'
|
||||
|
||||
export default function Price({
|
||||
ddo,
|
||||
firstPrice
|
||||
firstPrice,
|
||||
free
|
||||
}: {
|
||||
ddo: DDO
|
||||
firstPrice?: string
|
||||
free?: boolean
|
||||
}): ReactElement {
|
||||
const [field, meta] = useField('price')
|
||||
const { getDTName, getDTSymbol } = usePricing()
|
||||
@ -38,17 +40,27 @@ export default function Price({
|
||||
<div className={styles.price}>
|
||||
<div className={styles.grid}>
|
||||
<div className={styles.form}>
|
||||
<Input
|
||||
value={field.value}
|
||||
name="price"
|
||||
type="number"
|
||||
prefix="OCEAN"
|
||||
min="1"
|
||||
{...field}
|
||||
additionalComponent={
|
||||
<Conversion price={field.value} className={styles.conversion} />
|
||||
}
|
||||
/>
|
||||
{free ? (
|
||||
<Input
|
||||
value="0"
|
||||
name="price"
|
||||
type="number"
|
||||
prefix="OCEAN"
|
||||
readOnly
|
||||
/>
|
||||
) : (
|
||||
<Input
|
||||
value={field.value}
|
||||
name="price"
|
||||
type="number"
|
||||
prefix="OCEAN"
|
||||
min="1"
|
||||
{...field}
|
||||
additionalComponent={
|
||||
<Conversion price={field.value} className={styles.conversion} />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Error meta={meta} />
|
||||
</div>
|
||||
<div className={styles.datatoken}>
|
||||
|
@ -45,3 +45,8 @@
|
||||
padding-left: var(--spacer);
|
||||
padding-right: var(--spacer);
|
||||
}
|
||||
|
||||
.free {
|
||||
text-align: center;
|
||||
margin-bottom: calc(var(--spacer) / 1.5);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import styles from './index.module.css'
|
||||
import Tabs from '../../../../atoms/Tabs'
|
||||
import Fixed from './Fixed'
|
||||
import Dynamic from './Dynamic'
|
||||
import Free from './Free'
|
||||
import { useFormikContext } from 'formik'
|
||||
import { useUserPreferences } from '../../../../../providers/UserPreferences'
|
||||
import { PriceOptionsMarket } from '../../../../../@types/MetaData'
|
||||
@ -33,6 +34,7 @@ export default function FormPricing({
|
||||
const type = tabName.toLowerCase()
|
||||
setFieldValue('type', type)
|
||||
type === 'fixed' && setFieldValue('dtAmount', 1000)
|
||||
type === 'free' && price < 1 && setFieldValue('price', 1)
|
||||
}
|
||||
|
||||
// Always update everything when price value changes
|
||||
@ -57,6 +59,12 @@ export default function FormPricing({
|
||||
title: content.dynamic.title,
|
||||
content: <Dynamic content={content.dynamic} ddo={ddo} />
|
||||
}
|
||||
: undefined,
|
||||
appConfig.allowFreePricing === 'true'
|
||||
? {
|
||||
title: content.free.title,
|
||||
content: <Free content={content.free} ddo={ddo} />
|
||||
}
|
||||
: undefined
|
||||
].filter((tab) => tab !== undefined)
|
||||
|
||||
|
@ -40,6 +40,10 @@ const query = graphql`
|
||||
marketplaceFee
|
||||
}
|
||||
}
|
||||
free {
|
||||
title
|
||||
info
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,9 @@ import { Decimal } from 'decimal.js'
|
||||
import {
|
||||
getCreatePricingPoolFeedback,
|
||||
getCreatePricingExchangeFeedback,
|
||||
getBuyDTFeedback
|
||||
getBuyDTFeedback,
|
||||
getCreateFreePricingFeedback,
|
||||
getDispenseFeedback
|
||||
} from '../utils/feedback'
|
||||
import { sleep } from '../utils'
|
||||
|
||||
@ -16,7 +18,7 @@ interface PriceOptions {
|
||||
price: number
|
||||
dtAmount: number
|
||||
oceanAmount: number
|
||||
type: 'fixed' | 'dynamic' | string
|
||||
type: 'fixed' | 'dynamic' | 'free' | string
|
||||
weightOnDataToken: string
|
||||
swapFee: string
|
||||
}
|
||||
@ -68,7 +70,7 @@ function usePricing(): UsePricing {
|
||||
// Helper for setting steps & feedback for all flows
|
||||
async function setStep(
|
||||
index: number,
|
||||
type: 'pool' | 'exchange' | 'buy',
|
||||
type: 'pool' | 'exchange' | 'free' | 'buy' | 'dispense',
|
||||
ddo: DDO
|
||||
) {
|
||||
const dtSymbol = await getDTSymbol(ddo)
|
||||
@ -84,9 +86,15 @@ function usePricing(): UsePricing {
|
||||
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])
|
||||
@ -180,6 +188,28 @@ function usePricing(): UsePricing {
|
||||
Logger.log('DT exchange buy response', tx)
|
||||
break
|
||||
}
|
||||
case 'free': {
|
||||
setStep(1, 'dispense', ddo)
|
||||
const isDispensable = await ocean.OceanDispenser.isDispensable(
|
||||
ddo.dataToken,
|
||||
accountId,
|
||||
'1'
|
||||
)
|
||||
|
||||
if (!isDispensable) {
|
||||
Logger.error(`Dispenser for ${ddo.dataToken} failed to dispense`)
|
||||
return
|
||||
}
|
||||
|
||||
tx = await ocean.OceanDispenser.dispense(
|
||||
ddo.dataToken,
|
||||
accountId,
|
||||
'1'
|
||||
)
|
||||
setStep(2, 'dispense', ddo)
|
||||
Logger.log('DT dispense response', tx)
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
setPricingError(error.message)
|
||||
@ -219,9 +249,14 @@ function usePricing(): UsePricing {
|
||||
setStep(99, 'pool', ddo)
|
||||
|
||||
try {
|
||||
// if fixedPrice set dt to max amount
|
||||
if (!isPool) dtAmount = 1000
|
||||
await mint(`${dtAmount}`, ddo)
|
||||
if (type === 'free') {
|
||||
setStep(99, 'free', ddo)
|
||||
await ocean.OceanDispenser.activate(dataToken, '1', '1', accountId)
|
||||
} else {
|
||||
// if fixedPrice set dt to max amount
|
||||
if (!isPool) dtAmount = 1000
|
||||
await mint(`${dtAmount}`, ddo)
|
||||
}
|
||||
|
||||
// dtAmount for fixed price is set to max
|
||||
const tx = isPool
|
||||
@ -235,9 +270,13 @@ function usePricing(): UsePricing {
|
||||
swapFee
|
||||
)
|
||||
.next((step: number) => setStep(step, 'pool', ddo))
|
||||
: await ocean.fixedRateExchange
|
||||
: type === 'fixed'
|
||||
? await ocean.fixedRateExchange
|
||||
.create(dataToken, `${price}`, accountId, `${dtAmount}`)
|
||||
.next((step: number) => setStep(step, 'exchange', ddo))
|
||||
: await ocean.OceanDispenser.makeMinter(dataToken, accountId).next(
|
||||
(step: number) => setStep(step, 'free', ddo)
|
||||
)
|
||||
await sleep(20000)
|
||||
return tx
|
||||
} catch (error) {
|
||||
|
@ -27,6 +27,7 @@ interface UseSiteMetadata {
|
||||
portisId: string
|
||||
allowFixedPricing: string
|
||||
allowDynamicPricing: string
|
||||
allowFreePricing: string
|
||||
allowAdvancedSettings: string
|
||||
credentialType: string
|
||||
}
|
||||
@ -61,6 +62,7 @@ const query = graphql`
|
||||
portisId
|
||||
allowFixedPricing
|
||||
allowDynamicPricing
|
||||
allowFreePricing
|
||||
allowAdvancedSettings
|
||||
credentialType
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export const validationSchema: Yup.SchemaOf<PriceOptionsMarket> =
|
||||
.min(21, (param) => `Must be more or equal to ${param.min}`)
|
||||
.required('Required'),
|
||||
type: Yup.string()
|
||||
.matches(/fixed|dynamic/g, { excludeEmptyString: true })
|
||||
.matches(/fixed|dynamic|free/g, { excludeEmptyString: true })
|
||||
.required('Required'),
|
||||
weightOnDataToken: Yup.string().required('Required'),
|
||||
weightOnOcean: Yup.string().required('Required'),
|
||||
|
@ -52,6 +52,17 @@ export function getCreatePricingExchangeFeedback(dtSymbol: string): {
|
||||
}
|
||||
}
|
||||
|
||||
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 ...',
|
||||
@ -67,3 +78,12 @@ export function getSellDTFeedback(dtSymbol: string): { [key: number]: string } {
|
||||
3: `3/3 ${dtSymbol} sold.`
|
||||
}
|
||||
}
|
||||
|
||||
export function getDispenseFeedback(dtSymbol: string): {
|
||||
[key: number]: string
|
||||
} {
|
||||
return {
|
||||
1: `1/2 Requesting ${dtSymbol}...`,
|
||||
2: `2/2 Received ${dtSymbol}.`
|
||||
}
|
||||
}
|
||||
|
37
src/utils/freePrice.ts
Normal file
37
src/utils/freePrice.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Logger, Ocean } from '@oceanprotocol/lib'
|
||||
|
||||
export async function setMinterToPublisher(
|
||||
ocean: Ocean,
|
||||
dataTokenAddress: string,
|
||||
accountId: string,
|
||||
setError: (msg: string) => void
|
||||
): Promise<any> {
|
||||
// free pricing v3 workaround part1
|
||||
const response = await ocean.OceanDispenser.cancelMinter(
|
||||
dataTokenAddress,
|
||||
accountId
|
||||
)
|
||||
if (!response) {
|
||||
setError('Updating DDO failed.')
|
||||
Logger.error('Failed at cancelMinter')
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
export async function setMinterToDispenser(
|
||||
ocean: Ocean,
|
||||
dataTokenAddress: string,
|
||||
accountId: string,
|
||||
setError: (msg: string) => void
|
||||
): Promise<any> {
|
||||
// free pricing v3 workaround part2
|
||||
const response = await ocean.OceanDispenser.makeMinter(
|
||||
dataTokenAddress,
|
||||
accountId
|
||||
)
|
||||
if (!response) {
|
||||
setError('Updating DDO failed.')
|
||||
Logger.error('Failed at makeMinter')
|
||||
}
|
||||
return response
|
||||
}
|
@ -10,6 +10,10 @@ import {
|
||||
AssetsFrePrice_fixedRateExchanges as AssetsFrePriceFixedRateExchanges
|
||||
} from '../@types/apollo/AssetsFrePrice'
|
||||
import { AssetPreviousOrder } from '../@types/apollo/AssetPreviousOrder'
|
||||
import {
|
||||
AssetsFreePrice,
|
||||
AssetsFreePrice_dispensers as AssetFreePriceDispenser
|
||||
} from '../@types/apollo/AssetsFreePrice'
|
||||
import web3 from 'web3'
|
||||
|
||||
export interface PriceList {
|
||||
@ -25,6 +29,36 @@ interface DidAndDatatokenMap {
|
||||
[name: string]: string
|
||||
}
|
||||
|
||||
const FreeQuery = gql`
|
||||
query AssetsFreePrice($datatoken_in: [String!]) {
|
||||
dispensers(orderBy: id, where: { datatoken_in: $datatoken_in }) {
|
||||
datatoken {
|
||||
id
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const AssetFreeQuery = gql`
|
||||
query AssetFreePrice($datatoken: String) {
|
||||
dispensers(orderBy: id, where: { datatoken: $datatoken }) {
|
||||
active
|
||||
owner {
|
||||
id
|
||||
}
|
||||
minterApproved
|
||||
isTrueMinter
|
||||
maxTokens
|
||||
maxBalance
|
||||
balance
|
||||
datatoken {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const FreQuery = gql`
|
||||
query AssetsFrePrice($datatoken_in: [String!]) {
|
||||
fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) {
|
||||
@ -146,7 +180,8 @@ export async function getPreviousOrders(
|
||||
|
||||
function transformPriceToBestPrice(
|
||||
frePrice: AssetsFrePriceFixedRateExchanges[],
|
||||
poolPrice: AssetsPoolPricePools[]
|
||||
poolPrice: AssetsPoolPricePools[],
|
||||
freePrice: AssetFreePriceDispenser[]
|
||||
) {
|
||||
if (poolPrice?.length > 0) {
|
||||
const price: BestPrice = {
|
||||
@ -176,6 +211,18 @@ function transformPriceToBestPrice(
|
||||
isConsumable: 'true'
|
||||
}
|
||||
return price
|
||||
} else if (freePrice?.length > 0) {
|
||||
const price: BestPrice = {
|
||||
type: 'free',
|
||||
value: 0,
|
||||
address: freePrice[0]?.datatoken.id,
|
||||
exchange_id: '',
|
||||
ocean: 0,
|
||||
datatoken: 0,
|
||||
pools: [],
|
||||
isConsumable: 'true'
|
||||
}
|
||||
return price
|
||||
} else {
|
||||
const price: BestPrice = {
|
||||
type: '',
|
||||
@ -197,6 +244,7 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
||||
[
|
||||
ApolloQueryResult<AssetsPoolPrice>,
|
||||
ApolloQueryResult<AssetsFrePrice>,
|
||||
ApolloQueryResult<AssetsFreePrice>,
|
||||
DidAndDatatokenMap
|
||||
]
|
||||
> {
|
||||
@ -214,6 +262,10 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
||||
datatokenAddress_in: dataTokenList
|
||||
}
|
||||
|
||||
const freeVariables = {
|
||||
datatoken_in: dataTokenList
|
||||
}
|
||||
|
||||
const poolPriceResponse: ApolloQueryResult<AssetsPoolPrice> = await fetchData(
|
||||
PoolQuery,
|
||||
poolVariables
|
||||
@ -223,7 +275,12 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
||||
freVariables
|
||||
)
|
||||
|
||||
return [poolPriceResponse, frePriceResponse, didDTMap]
|
||||
const freePriceResponse: ApolloQueryResult<AssetsFreePrice> = await fetchData(
|
||||
FreeQuery,
|
||||
freeVariables
|
||||
)
|
||||
|
||||
return [poolPriceResponse, frePriceResponse, freePriceResponse, didDTMap]
|
||||
}
|
||||
|
||||
export async function getAssetsPriceList(assets: DDO[]): Promise<PriceList> {
|
||||
@ -232,11 +289,13 @@ export async function getAssetsPriceList(assets: DDO[]): Promise<PriceList> {
|
||||
const values: [
|
||||
ApolloQueryResult<AssetsPoolPrice>,
|
||||
ApolloQueryResult<AssetsFrePrice>,
|
||||
ApolloQueryResult<AssetsFreePrice>,
|
||||
DidAndDatatokenMap
|
||||
] = await getAssetsPoolsExchangesAndDatatokenMap(assets)
|
||||
const poolPriceResponse = values[0]
|
||||
const frePriceResponse = values[1]
|
||||
const didDTMap: DidAndDatatokenMap = values[2]
|
||||
const freePriceResponse = values[2]
|
||||
const didDTMap: DidAndDatatokenMap = values[3]
|
||||
|
||||
for (const poolPrice of poolPriceResponse.data?.pools) {
|
||||
priceList[didDTMap[poolPrice.datatokenAddress]] =
|
||||
@ -247,6 +306,9 @@ export async function getAssetsPriceList(assets: DDO[]): Promise<PriceList> {
|
||||
for (const frePrice of frePriceResponse.data?.fixedRateExchanges) {
|
||||
priceList[didDTMap[frePrice.datatoken?.address]] = frePrice.rate
|
||||
}
|
||||
for (const freePrice of freePriceResponse.data?.dispensers) {
|
||||
priceList[didDTMap[freePrice.datatoken?.address]] = '0'
|
||||
}
|
||||
return priceList
|
||||
}
|
||||
|
||||
@ -259,6 +321,10 @@ export async function getPrice(asset: DDO): Promise<BestPrice> {
|
||||
datatokenAddress: asset?.dataToken.toLowerCase()
|
||||
}
|
||||
|
||||
const freeVariables = {
|
||||
datatoken: asset?.dataToken.toLowerCase()
|
||||
}
|
||||
|
||||
const poolPriceResponse: ApolloQueryResult<AssetsPoolPrice> = await fetchData(
|
||||
AssetPoolPriceQuerry,
|
||||
poolVariables
|
||||
@ -267,10 +333,15 @@ export async function getPrice(asset: DDO): Promise<BestPrice> {
|
||||
AssetFreQuery,
|
||||
freVariables
|
||||
)
|
||||
const freePriceResponse: ApolloQueryResult<AssetsFreePrice> = await fetchData(
|
||||
AssetFreeQuery,
|
||||
freeVariables
|
||||
)
|
||||
|
||||
const bestPrice: BestPrice = transformPriceToBestPrice(
|
||||
frePriceResponse.data.fixedRateExchanges,
|
||||
poolPriceResponse.data.pools
|
||||
poolPriceResponse.data.pools,
|
||||
freePriceResponse.data.dispensers
|
||||
)
|
||||
|
||||
return bestPrice
|
||||
@ -284,15 +355,18 @@ export async function getAssetsBestPrices(
|
||||
const values: [
|
||||
ApolloQueryResult<AssetsPoolPrice>,
|
||||
ApolloQueryResult<AssetsFrePrice>,
|
||||
ApolloQueryResult<AssetsFreePrice>,
|
||||
DidAndDatatokenMap
|
||||
] = await getAssetsPoolsExchangesAndDatatokenMap(assets)
|
||||
const poolPriceResponse = values[0]
|
||||
const frePriceResponse = values[1]
|
||||
const freePriceResponse = values[2]
|
||||
|
||||
for (const ddo of assets) {
|
||||
const dataToken = ddo.dataToken.toLowerCase()
|
||||
const poolPrice: AssetsPoolPricePools[] = []
|
||||
const frePrice: AssetsFrePriceFixedRateExchanges[] = []
|
||||
const freePrice: AssetFreePriceDispenser[] = []
|
||||
const pool = poolPriceResponse.data?.pools.find(
|
||||
(pool: any) => pool.datatokenAddress === dataToken
|
||||
)
|
||||
@ -301,7 +375,11 @@ export async function getAssetsBestPrices(
|
||||
(fre: any) => fre.datatoken.address === dataToken
|
||||
)
|
||||
fre && frePrice.push(fre)
|
||||
const bestPrice = transformPriceToBestPrice(frePrice, poolPrice)
|
||||
const free = freePriceResponse.data?.dispensers.find(
|
||||
(free: any) => free.datatoken.address === dataToken
|
||||
)
|
||||
free && freePrice.push(free)
|
||||
const bestPrice = transformPriceToBestPrice(frePrice, poolPrice, freePrice)
|
||||
assetsWithPrice.push({
|
||||
ddo: ddo,
|
||||
price: bestPrice
|
||||
|
Loading…
Reference in New Issue
Block a user