mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
merged multinetwork into poc-urql
This commit is contained in:
commit
8d50eb92c0
22
.env.example
22
.env.example
@ -1,15 +1,27 @@
|
|||||||
# Default network, possible values:
|
# Default network, possible values:
|
||||||
# "development", "ropsten", "rinkeby", "mainnet", "polygon", "moonbeamalpha"
|
# "development", "ropsten", "rinkeby", "mainnet", "polygon", "moonbeamalpha",
|
||||||
|
# "gaiaxtestnet", "mumbai", "bsc"
|
||||||
GATSBY_NETWORK="rinkeby"
|
GATSBY_NETWORK="rinkeby"
|
||||||
|
|
||||||
## Define a GATSBY_RBAC_URL to implement permission based restrictions
|
|
||||||
#GATSBY_RBAC_URL="http://localhost:3000"
|
|
||||||
|
|
||||||
#GATSBY_INFURA_PROJECT_ID="xxx"
|
#GATSBY_INFURA_PROJECT_ID="xxx"
|
||||||
#GATSBY_MARKET_FEE_ADDRESS="0xxx"
|
#GATSBY_MARKET_FEE_ADDRESS="0xxx"
|
||||||
#GATSBY_ANALYTICS_ID="xxx"
|
|
||||||
#GATSBY_PORTIS_ID="xxx"
|
#GATSBY_PORTIS_ID="xxx"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# ADVANCED SETTINGS
|
||||||
|
#
|
||||||
|
|
||||||
|
# Toggle pricing options presented during price creation
|
||||||
#GATSBY_ALLOW_FIXED_PRICING="true"
|
#GATSBY_ALLOW_FIXED_PRICING="true"
|
||||||
#GATSBY_ALLOW_DYNAMIC_PRICING="true"
|
#GATSBY_ALLOW_DYNAMIC_PRICING="true"
|
||||||
|
#GATSBY_ALLOW_FREE_PRICING="false"
|
||||||
|
|
||||||
|
# Define RBAC server URL to implement permission based restrictions
|
||||||
|
#GATSBY_RBAC_URL="http://localhost:3000"
|
||||||
|
|
||||||
|
# Enables another asset editing button holder further advanced settings
|
||||||
#GATSBY_ALLOW_ADVANCED_SETTINGS="true"
|
#GATSBY_ALLOW_ADVANCED_SETTINGS="true"
|
||||||
|
|
||||||
|
# Allow/Deny Lists
|
||||||
#GATSBY_CREDENTIAL_TYPE="address"
|
#GATSBY_CREDENTIAL_TYPE="address"
|
||||||
|
11
README.md
11
README.md
@ -26,6 +26,7 @@
|
|||||||
- [⬆️ Deployment](#️-deployment)
|
- [⬆️ Deployment](#️-deployment)
|
||||||
- [💖 Contributing](#-contributing)
|
- [💖 Contributing](#-contributing)
|
||||||
- [🍴 Forking](#-forking)
|
- [🍴 Forking](#-forking)
|
||||||
|
- [💻 Advanced Features](#-advanced-features)
|
||||||
- [🏛 License](#-license)
|
- [🏛 License](#-license)
|
||||||
|
|
||||||
## 🏄 Get Started
|
## 🏄 Get Started
|
||||||
@ -374,6 +375,16 @@ Additionally, we would also advise that your retain the text saying "Powered by
|
|||||||
|
|
||||||
Everything else is made open according to the apache2 license. We look forward to seeing your data marketplace!
|
Everything else is made open according to the apache2 license. We look forward to seeing your data marketplace!
|
||||||
|
|
||||||
|
## 💻 Advanced Features
|
||||||
|
|
||||||
|
Ocean Market also includes a number of advanced features that are suitable for an enterprise data market, such as:
|
||||||
|
|
||||||
|
- Role based access control
|
||||||
|
- Allow and deny lists
|
||||||
|
- Free pricing
|
||||||
|
|
||||||
|
[See our seperate guide on advanced features](docs/advancedSettings.md)
|
||||||
|
|
||||||
## 🏛 License
|
## 🏛 License
|
||||||
|
|
||||||
```text
|
```text
|
||||||
|
@ -8,7 +8,7 @@ module.exports = {
|
|||||||
chainIds: [1, 137],
|
chainIds: [1, 137],
|
||||||
|
|
||||||
// List of all supported chainIds. Used to populate the Chains user preferences list.
|
// List of all supported chainIds. Used to populate the Chains user preferences list.
|
||||||
chainIdsSupported: [1, 3, 4, 137, 1287],
|
chainIdsSupported: [1, 3, 4, 137, 1287, 56],
|
||||||
|
|
||||||
rbacUrl: process.env.GATSBY_RBAC_URL,
|
rbacUrl: process.env.GATSBY_RBAC_URL,
|
||||||
|
|
||||||
@ -47,10 +47,11 @@ module.exports = {
|
|||||||
// Wallets
|
// Wallets
|
||||||
portisId: process.env.GATSBY_PORTIS_ID || 'xxx',
|
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.
|
// tab to publishers during the price creation.
|
||||||
allowFixedPricing: process.env.GATSBY_ALLOW_FIXED_PRICING || 'true',
|
allowFixedPricing: process.env.GATSBY_ALLOW_FIXED_PRICING || 'true',
|
||||||
allowDynamicPricing: process.env.GATSBY_ALLOW_DYNAMIC_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
|
// Used to show or hide advanced settings button in asset details page
|
||||||
allowAdvancedSettings: process.env.GATSBY_ALLOW_ADVANCED_SETTINGS || 'false',
|
allowAdvancedSettings: process.env.GATSBY_ALLOW_ADVANCED_SETTINGS || 'false',
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
"communityFee": "Explain community fee...",
|
"communityFee": "Explain community fee...",
|
||||||
"marketplaceFee": "Explain marketplace 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": {
|
"pool": {
|
||||||
|
29
docs/advancedSettings.md
Normal file
29
docs/advancedSettings.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Advanced Settings
|
||||||
|
|
||||||
|
**Table of Contents**
|
||||||
|
|
||||||
|
- [Role based Access Control](#rbac-settings)
|
||||||
|
- [Allow and Deny lists](#allow-and-deny-list-settings)
|
||||||
|
- [Free Pricing](#free-pricing-settings)
|
||||||
|
|
||||||
|
## RBAC settings
|
||||||
|
|
||||||
|
- Setup and host the Ocean role based access control (RBAC) server. Follow the instructions in the [RBAC repository](https://github.com/oceanprotocol/RBAC-Server)
|
||||||
|
- The RBAC server can store roles in [Keycloak](https://www.keycloak.org/) or a json file.
|
||||||
|
- In your .env file, set the value of the `GATSBY_RBAC_URL` environmental variable to the URL of the Ocean RBAC server that you have hosted, e.g. `GATSBY_RBAC_URL= "http://localhost:3000"`
|
||||||
|
- Users of your marketplace will now require the correct role ("user", "consumer", "publisher") to access features in your marketplace. The market will check the role that has been allocated to the user based on the address that they have connected to the market with.
|
||||||
|
- The following features have been wrapped in the `Permission` component and will be restricted once the `GATSBY_RBAC_URL` has been defined:
|
||||||
|
- Viewing or searching datasets requires the user to have permison to `browse`
|
||||||
|
- Purchasing or trading a datatoken, or adding liquidity to a pool require the user to have permison to `consume`
|
||||||
|
- Publishing a dataset requires the user to have permison to `publish`
|
||||||
|
- You can change the permission resrictions by either removing the `Permission` component or passing in a different eventType prop e.g. `<Permission eventType="browse">`.
|
||||||
|
|
||||||
|
## Allow and Deny List Settings
|
||||||
|
|
||||||
|
- To enable allow and deny lists you need to add the following environmental variable to your .env file: `GATSBY_ALLOW_ADVANCED_SETTINGS="true"`
|
||||||
|
- Publishers in your market will now have the ability to restrict who can consume their datasets.
|
||||||
|
|
||||||
|
## Free Pricing Settings
|
||||||
|
|
||||||
|
- To allow publishers to set pricing as "Free" you need to add the following environmental variable to your .env file: `GATSBY_ALLOW_FREE_PRICING="true"`
|
||||||
|
- This allocates the datatokens to the [dispenser contract](https://github.com/oceanprotocol/contracts/blob/main/contracts/dispenser/Dispenser.sol) which dispenses data tokens to users for free. Publishers in your market will now be able to offer their datasets to users for free (excluding gas costs).
|
25960
package-lock.json
generated
25960
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -26,7 +26,7 @@
|
|||||||
"@coingecko/cryptoformat": "^0.4.2",
|
"@coingecko/cryptoformat": "^0.4.2",
|
||||||
"@loadable/component": "^5.15.0",
|
"@loadable/component": "^5.15.0",
|
||||||
"@oceanprotocol/art": "^3.0.0",
|
"@oceanprotocol/art": "^3.0.0",
|
||||||
"@oceanprotocol/lib": "^0.15.1",
|
"@oceanprotocol/lib": "^0.16.1",
|
||||||
"@oceanprotocol/typographies": "^0.1.0",
|
"@oceanprotocol/typographies": "^0.1.0",
|
||||||
"@portis/web3": "^4.0.4",
|
"@portis/web3": "^4.0.4",
|
||||||
"@sindresorhus/slugify": "^2.1.0",
|
"@sindresorhus/slugify": "^2.1.0",
|
||||||
@ -60,7 +60,6 @@
|
|||||||
"gatsby-transformer-remark": "^2.16.1",
|
"gatsby-transformer-remark": "^2.16.1",
|
||||||
"gatsby-transformer-sharp": "^2.12.1",
|
"gatsby-transformer-sharp": "^2.12.1",
|
||||||
"graphql": "14.7.0",
|
"graphql": "14.7.0",
|
||||||
"graphql-schema-typescript": "^1.5.2",
|
|
||||||
"is-url-superb": "^6.0.0",
|
"is-url-superb": "^6.0.0",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
|
@ -21,6 +21,8 @@ interface ButtonBuyProps {
|
|||||||
onClick?: (e: FormEvent<HTMLButtonElement>) => void
|
onClick?: (e: FormEvent<HTMLButtonElement>) => void
|
||||||
stepText?: string
|
stepText?: string
|
||||||
type?: 'submit'
|
type?: 'submit'
|
||||||
|
priceType?: string
|
||||||
|
algorithmPriceType?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConsumeHelpText(
|
function getConsumeHelpText(
|
||||||
@ -87,15 +89,21 @@ export default function ButtonBuy({
|
|||||||
onClick,
|
onClick,
|
||||||
stepText,
|
stepText,
|
||||||
isLoading,
|
isLoading,
|
||||||
type
|
type,
|
||||||
|
priceType,
|
||||||
|
algorithmPriceType
|
||||||
}: ButtonBuyProps): ReactElement {
|
}: ButtonBuyProps): ReactElement {
|
||||||
const buttonText =
|
const buttonText =
|
||||||
action === 'download'
|
action === 'download'
|
||||||
? hasPreviousOrder
|
? hasPreviousOrder
|
||||||
? 'Download'
|
? 'Download'
|
||||||
|
: priceType === 'free'
|
||||||
|
? 'Get'
|
||||||
: `Buy ${assetTimeout === 'Forever' ? '' : ` for ${assetTimeout}`}`
|
: `Buy ${assetTimeout === 'Forever' ? '' : ` for ${assetTimeout}`}`
|
||||||
: hasPreviousOrder && hasPreviousOrderSelectedComputeAsset
|
: hasPreviousOrder && hasPreviousOrderSelectedComputeAsset
|
||||||
? 'Start Compute Job'
|
? 'Start Compute Job'
|
||||||
|
: priceType === 'free' && algorithmPriceType === 'free'
|
||||||
|
? 'Order Compute Job'
|
||||||
: `Buy Compute Job`
|
: `Buy Compute Job`
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -42,6 +42,10 @@ export default function PriceUnit({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styleClasses}>
|
<div className={styleClasses}>
|
||||||
|
{type && type === 'free' ? (
|
||||||
|
<div> Free </div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<div>
|
<div>
|
||||||
{Number.isNaN(Number(price)) ? '-' : formatPrice(price, locale)}{' '}
|
{Number.isNaN(Number(price)) ? '-' : formatPrice(price, locale)}{' '}
|
||||||
<span className={styles.symbol}>{symbol || 'OCEAN'}</span>
|
<span className={styles.symbol}>{symbol || 'OCEAN'}</span>
|
||||||
@ -49,8 +53,9 @@ export default function PriceUnit({
|
|||||||
<Badge label="pool" className={styles.badge} />
|
<Badge label="pool" className={styles.badge} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{conversion && <Conversion price={price} />}
|
{conversion && <Conversion price={price} />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ export default function Price({
|
|||||||
small?: boolean
|
small?: boolean
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
return price?.value ? (
|
return price?.value || price?.type === 'free' ? (
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={`${price.value}`}
|
price={`${price.value}`}
|
||||||
className={className}
|
className={className}
|
||||||
|
@ -107,7 +107,12 @@ export default function AssetSelection({
|
|||||||
</Dotdotdot>
|
</Dotdotdot>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<PriceUnit price={asset.price} small className={styles.price} />
|
<PriceUnit
|
||||||
|
price={asset.price}
|
||||||
|
type={asset.price === '0' ? 'free' : undefined}
|
||||||
|
small
|
||||||
|
className={styles.price}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
@ -23,7 +23,11 @@ export default function SearchBar({
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
if (value === '') value = ' '
|
if (value === '') value = ' '
|
||||||
const urlEncodedValue = encodeURIComponent(value)
|
const urlEncodedValue = encodeURIComponent(value)
|
||||||
const url = await addExistingParamsToUrl(location, 'text')
|
const url = await addExistingParamsToUrl(location, [
|
||||||
|
'text',
|
||||||
|
'owner',
|
||||||
|
'tags'
|
||||||
|
])
|
||||||
navigate(`${url}&text=${urlEncodedValue}`)
|
navigate(`${url}&text=${urlEncodedValue}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +35,11 @@ export default function SearchBar({
|
|||||||
const searchParams = new URLSearchParams(window.location.href)
|
const searchParams = new URLSearchParams(window.location.href)
|
||||||
const text = searchParams.get('text')
|
const text = searchParams.get('text')
|
||||||
if (text !== ('' || undefined || null)) {
|
if (text !== ('' || undefined || null)) {
|
||||||
const url = await addExistingParamsToUrl(location, 'text')
|
const url = await addExistingParamsToUrl(location, [
|
||||||
|
'text',
|
||||||
|
'owner',
|
||||||
|
'tags'
|
||||||
|
])
|
||||||
navigate(`${url}&text=%20`)
|
navigate(`${url}&text=%20`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,6 +166,8 @@ export default function FormStartCompute({
|
|||||||
stepText={stepText}
|
stepText={stepText}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
type="submit"
|
type="submit"
|
||||||
|
priceType={price?.type}
|
||||||
|
algorithmPriceType={algorithmPrice?.type}
|
||||||
/>
|
/>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
)
|
||||||
|
@ -157,7 +157,9 @@ export default function Compute({
|
|||||||
source.token
|
source.token
|
||||||
)
|
)
|
||||||
setDdoAlgorithmList(gueryResults.results)
|
setDdoAlgorithmList(gueryResults.results)
|
||||||
|
const datasetComputeService = ddo.findServiceByType('compute')
|
||||||
algorithmSelectionList = await transformDDOToAssetSelection(
|
algorithmSelectionList = await transformDDOToAssetSelection(
|
||||||
|
datasetComputeService?.serviceEndpoint,
|
||||||
gueryResults.results,
|
gueryResults.results,
|
||||||
appConfig.metadataCacheUri,
|
appConfig.metadataCacheUri,
|
||||||
[]
|
[]
|
||||||
@ -384,7 +386,10 @@ 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} />
|
<AlgorithmDatasetsListForCompute
|
||||||
|
algorithmDid={ddo.id}
|
||||||
|
dataset={ddo}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Formik
|
<Formik
|
||||||
|
@ -12,6 +12,7 @@ import { useWeb3 } from '../../../providers/Web3'
|
|||||||
import { usePricing } from '../../../hooks/usePricing'
|
import { usePricing } from '../../../hooks/usePricing'
|
||||||
import { useConsume } from '../../../hooks/useConsume'
|
import { useConsume } from '../../../hooks/useConsume'
|
||||||
import ButtonBuy from '../../atoms/ButtonBuy'
|
import ButtonBuy from '../../atoms/ButtonBuy'
|
||||||
|
import { secondsToString } from '../../../utils/metadata'
|
||||||
import AlgorithmDatasetsListForCompute from '../AssetContent/AlgorithmDatasetsListForCompute'
|
import AlgorithmDatasetsListForCompute from '../AssetContent/AlgorithmDatasetsListForCompute'
|
||||||
import styles from './Consume.module.css'
|
import styles from './Consume.module.css'
|
||||||
|
|
||||||
@ -157,10 +158,11 @@ export default function Consume({
|
|||||||
dtSymbol={ddo.dataTokenInfo?.symbol}
|
dtSymbol={ddo.dataTokenInfo?.symbol}
|
||||||
dtBalance={dtBalance}
|
dtBalance={dtBalance}
|
||||||
onClick={handleConsume}
|
onClick={handleConsume}
|
||||||
assetTimeout={assetTimeout}
|
assetTimeout={secondsToString(parseInt(assetTimeout))}
|
||||||
assetType={type}
|
assetType={type}
|
||||||
stepText={consumeStepText || pricingStepText}
|
stepText={consumeStepText || pricingStepText}
|
||||||
isLoading={pricingIsLoading || isLoading}
|
isLoading={pricingIsLoading || isLoading}
|
||||||
|
priceType={price?.type}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -176,7 +178,7 @@ export default function Consume({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{type === 'algorithm' && (
|
{type === 'algorithm' && (
|
||||||
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} />
|
<AlgorithmDatasetsListForCompute algorithmDid={ddo.id} dataset={ddo} />
|
||||||
)}
|
)}
|
||||||
</aside>
|
</aside>
|
||||||
)
|
)
|
||||||
|
@ -16,6 +16,10 @@ import {
|
|||||||
} from '../../../../models/FormEditCredential'
|
} from '../../../../models/FormEditCredential'
|
||||||
import DebugEditCredential from './DebugEditAdvancedSettings'
|
import DebugEditCredential from './DebugEditAdvancedSettings'
|
||||||
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
|
import { useSiteMetadata } from '../../../../hooks/useSiteMetadata'
|
||||||
|
import {
|
||||||
|
setMinterToDispenser,
|
||||||
|
setMinterToPublisher
|
||||||
|
} from '../../../../utils/freePrice'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query EditAvanceSettingsQuery {
|
query EditAvanceSettingsQuery {
|
||||||
@ -68,7 +72,7 @@ export default function EditAdvancedSettings({
|
|||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
const { accountId } = useWeb3()
|
const { accountId } = useWeb3()
|
||||||
const { ocean } = useOcean()
|
const { ocean } = useOcean()
|
||||||
const { metadata, ddo, refreshDdo } = useAsset()
|
const { metadata, ddo, refreshDdo, price } = useAsset()
|
||||||
const [success, setSuccess] = useState<string>()
|
const [success, setSuccess] = useState<string>()
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
const { appConfig } = useSiteMetadata()
|
const { appConfig } = useSiteMetadata()
|
||||||
@ -82,6 +86,16 @@ export default function EditAdvancedSettings({
|
|||||||
resetForm: () => void
|
resetForm: () => void
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
if (price.type === 'free') {
|
||||||
|
const tx = await setMinterToPublisher(
|
||||||
|
ocean,
|
||||||
|
ddo.dataToken,
|
||||||
|
accountId,
|
||||||
|
setError
|
||||||
|
)
|
||||||
|
if (!tx) return
|
||||||
|
}
|
||||||
|
|
||||||
let newDdo: DDO
|
let newDdo: DDO
|
||||||
newDdo = await ocean.assets.updateCredentials(
|
newDdo = await ocean.assets.updateCredentials(
|
||||||
ddo,
|
ddo,
|
||||||
@ -103,6 +117,15 @@ export default function EditAdvancedSettings({
|
|||||||
Logger.error(content.form.error)
|
Logger.error(content.form.error)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
if (price.type === 'free') {
|
||||||
|
const tx = await setMinterToDispenser(
|
||||||
|
ocean,
|
||||||
|
ddo.dataToken,
|
||||||
|
accountId,
|
||||||
|
setError
|
||||||
|
)
|
||||||
|
if (!tx) return
|
||||||
|
}
|
||||||
setSuccess(content.form.success)
|
setSuccess(content.form.success)
|
||||||
resetForm()
|
resetForm()
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@ import { useUserPreferences } from '../../../../providers/UserPreferences'
|
|||||||
import DebugEditCompute from './DebugEditCompute'
|
import DebugEditCompute from './DebugEditCompute'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import { transformComputeFormToServiceComputePrivacy } from '../../../../utils/compute'
|
import { transformComputeFormToServiceComputePrivacy } from '../../../../utils/compute'
|
||||||
|
import {
|
||||||
|
setMinterToDispenser,
|
||||||
|
setMinterToPublisher
|
||||||
|
} from '../../../../utils/freePrice'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query EditComputeDataQuery {
|
query EditComputeDataQuery {
|
||||||
@ -62,7 +66,7 @@ export default function EditComputeDataset({
|
|||||||
const { debug } = useUserPreferences()
|
const { debug } = useUserPreferences()
|
||||||
const { ocean } = useOcean()
|
const { ocean } = useOcean()
|
||||||
const { accountId } = useWeb3()
|
const { accountId } = useWeb3()
|
||||||
const { ddo, refreshDdo } = useAsset()
|
const { ddo, refreshDdo, price } = useAsset()
|
||||||
const [success, setSuccess] = useState<string>()
|
const [success, setSuccess] = useState<string>()
|
||||||
const [error, setError] = useState<string>()
|
const [error, setError] = useState<string>()
|
||||||
|
|
||||||
@ -73,6 +77,15 @@ export default function EditComputeDataset({
|
|||||||
resetForm: () => void
|
resetForm: () => void
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
if (price.type === 'free') {
|
||||||
|
const tx = await setMinterToPublisher(
|
||||||
|
ocean,
|
||||||
|
ddo.dataToken,
|
||||||
|
accountId,
|
||||||
|
setError
|
||||||
|
)
|
||||||
|
if (!tx) return
|
||||||
|
}
|
||||||
const privacy = await transformComputeFormToServiceComputePrivacy(
|
const privacy = await transformComputeFormToServiceComputePrivacy(
|
||||||
values,
|
values,
|
||||||
ocean
|
ocean
|
||||||
@ -99,6 +112,15 @@ export default function EditComputeDataset({
|
|||||||
Logger.error(content.form.error)
|
Logger.error(content.form.error)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
if (price.type === 'free') {
|
||||||
|
const tx = await setMinterToDispenser(
|
||||||
|
ocean,
|
||||||
|
ddo.dataToken,
|
||||||
|
accountId,
|
||||||
|
setError
|
||||||
|
)
|
||||||
|
if (!tx) return
|
||||||
|
}
|
||||||
// Edit succeeded
|
// Edit succeeded
|
||||||
setSuccess(content.form.success)
|
setSuccess(content.form.success)
|
||||||
resetForm()
|
resetForm()
|
||||||
|
@ -56,7 +56,9 @@ export default function FormEditComputeDataset({
|
|||||||
appConfig.metadataCacheUri,
|
appConfig.metadataCacheUri,
|
||||||
source.token
|
source.token
|
||||||
)
|
)
|
||||||
|
const datasetComputeService = ddo.findServiceByType('compute')
|
||||||
const algorithmSelectionList = await transformDDOToAssetSelection(
|
const algorithmSelectionList = await transformDDOToAssetSelection(
|
||||||
|
datasetComputeService?.serviceEndpoint,
|
||||||
querryResult.results,
|
querryResult.results,
|
||||||
appConfig.metadataCacheUri,
|
appConfig.metadataCacheUri,
|
||||||
publisherTrustedAlgorithms
|
publisherTrustedAlgorithms
|
||||||
|
@ -18,6 +18,10 @@ import MetadataFeedback from '../../../molecules/MetadataFeedback'
|
|||||||
import { graphql, useStaticQuery } from 'gatsby'
|
import { graphql, useStaticQuery } from 'gatsby'
|
||||||
import { useWeb3 } from '../../../../providers/Web3'
|
import { useWeb3 } from '../../../../providers/Web3'
|
||||||
import { useOcean } from '../../../../providers/Ocean'
|
import { useOcean } from '../../../../providers/Ocean'
|
||||||
|
import {
|
||||||
|
setMinterToDispenser,
|
||||||
|
setMinterToPublisher
|
||||||
|
} from '../../../../utils/freePrice'
|
||||||
|
|
||||||
const contentQuery = graphql`
|
const contentQuery = graphql`
|
||||||
query EditMetadataQuery {
|
query EditMetadataQuery {
|
||||||
@ -88,6 +92,15 @@ export default function Edit({
|
|||||||
resetForm: () => void
|
resetForm: () => void
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
|
if (price.type === 'free') {
|
||||||
|
const tx = await setMinterToPublisher(
|
||||||
|
ocean,
|
||||||
|
ddo.dataToken,
|
||||||
|
accountId,
|
||||||
|
setError
|
||||||
|
)
|
||||||
|
if (!tx) return
|
||||||
|
}
|
||||||
// Construct new DDO with new values
|
// Construct new DDO with new values
|
||||||
const ddoEditedMetdata = await ocean.assets.editMetadata(ddo, {
|
const ddoEditedMetdata = await ocean.assets.editMetadata(ddo, {
|
||||||
title: values.name,
|
title: values.name,
|
||||||
@ -132,6 +145,15 @@ export default function Edit({
|
|||||||
Logger.error(content.form.error)
|
Logger.error(content.form.error)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
if (price.type === 'free') {
|
||||||
|
const tx = await setMinterToDispenser(
|
||||||
|
ocean,
|
||||||
|
ddo.dataToken,
|
||||||
|
accountId,
|
||||||
|
setError
|
||||||
|
)
|
||||||
|
if (!tx) return
|
||||||
|
}
|
||||||
// Edit succeeded
|
// Edit succeeded
|
||||||
setSuccess(content.form.success)
|
setSuccess(content.form.success)
|
||||||
resetForm()
|
resetForm()
|
||||||
|
@ -122,11 +122,10 @@ export default function Graph(): ReactElement {
|
|||||||
|
|
||||||
const { price } = useAsset()
|
const { price } = useAsset()
|
||||||
|
|
||||||
const [lastBlock, setLastBlock] = useState(0)
|
const [lastBlock, setLastBlock] = useState<number>(0)
|
||||||
const [priceHistory, setPriceHistory] = useState([])
|
const [priceHistory, setPriceHistory] = useState([])
|
||||||
const [liquidityHistory, setLiquidityHistory] = useState([])
|
const [liquidityHistory, setLiquidityHistory] = useState([])
|
||||||
const [timestamps, setTimestamps] = useState([])
|
const [timestamps, setTimestamps] = useState([])
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const [graphData, setGraphData] = useState<ChartData>()
|
const [graphData, setGraphData] = useState<ChartData>()
|
||||||
|
|
||||||
@ -157,7 +156,6 @@ export default function Graph(): ReactElement {
|
|||||||
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
|
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
|
|
||||||
setTimestamps(latestTimestamps)
|
setTimestamps(latestTimestamps)
|
||||||
|
|
||||||
const latestLiquidtyHistory = [
|
const latestLiquidtyHistory = [
|
||||||
@ -171,17 +169,20 @@ export default function Graph(): ReactElement {
|
|||||||
...priceHistory,
|
...priceHistory,
|
||||||
...data.poolTransactions.map((item) => item.spotPrice)
|
...data.poolTransactions.map((item) => item.spotPrice)
|
||||||
]
|
]
|
||||||
|
|
||||||
setPriceHistory(latestPriceHistory)
|
setPriceHistory(latestPriceHistory)
|
||||||
|
|
||||||
if (data.poolTransactions.length > 0) {
|
if (data.poolTransactions.length > 0) {
|
||||||
|
const newBlock =
|
||||||
|
data.poolTransactions[data.poolTransactions.length - 1].block
|
||||||
|
if (newBlock === lastBlock) return
|
||||||
setLastBlock(
|
setLastBlock(
|
||||||
data.poolTransactions[data.poolTransactions.length - 1].block
|
data.poolTransactions[data.poolTransactions.length - 1].block
|
||||||
)
|
)
|
||||||
refetch()
|
refetch()
|
||||||
} else {
|
} else {
|
||||||
setIsLoading(false)
|
|
||||||
setGraphData({
|
setGraphData({
|
||||||
labels: timestamps.slice(0),
|
labels: latestTimestamps.slice(0),
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
...lineStyle,
|
...lineStyle,
|
||||||
@ -195,6 +196,7 @@ export default function Graph(): ReactElement {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
}, [data, graphType])
|
}, [data, graphType])
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import { useAsset } from '../../../providers/Asset'
|
|||||||
import { useOcean } from '../../../providers/Ocean'
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import { useWeb3 } from '../../../providers/Web3'
|
import { useWeb3 } from '../../../providers/Web3'
|
||||||
import Web3Feedback from '../../molecules/Web3Feedback'
|
import Web3Feedback from '../../molecules/Web3Feedback'
|
||||||
import { getFileInfo } from '../../../utils/provider'
|
import { fileinfo, getFileInfo } from '../../../utils/provider'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
export default function AssetActions(): ReactElement {
|
export default function AssetActions(): ReactElement {
|
||||||
@ -27,29 +27,27 @@ export default function AssetActions(): ReactElement {
|
|||||||
const isCompute = Boolean(ddo?.findServiceByType('compute'))
|
const isCompute = Boolean(ddo?.findServiceByType('compute'))
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!config) return
|
const { attributes } = ddo.findServiceByType('metadata')
|
||||||
|
setFileMetadata(attributes.main.files[0])
|
||||||
const source = axios.CancelToken.source()
|
// !!!!! do not remove this, we will enable this again after fileInfo endpoint is fixed !!!
|
||||||
async function initFileInfo() {
|
// if (!config) return
|
||||||
setFileIsLoading(true)
|
// const source = axios.CancelToken.source()
|
||||||
try {
|
// async function initFileInfo() {
|
||||||
const fileInfo = await getFileInfo(
|
// setFileIsLoading(true)
|
||||||
DID.parse(`${ddo.id}`),
|
// try {
|
||||||
config.providerUri,
|
// const fileInfo = await getFileInfo(
|
||||||
source.token
|
// DID.parse(`${ddo.id}`),
|
||||||
)
|
// config.providerUri,
|
||||||
setFileMetadata(fileInfo.data[0])
|
// source.token
|
||||||
} catch (error) {
|
// )
|
||||||
Logger.error(error.message)
|
// setFileMetadata(fileInfo.data[0])
|
||||||
} finally {
|
// } catch (error) {
|
||||||
setFileIsLoading(false)
|
// Logger.error(error.message)
|
||||||
}
|
// } finally {
|
||||||
}
|
// setFileIsLoading(false)
|
||||||
initFileInfo()
|
// }
|
||||||
|
// }
|
||||||
return () => {
|
// initFileInfo()
|
||||||
source.cancel()
|
|
||||||
}
|
|
||||||
}, [config, ddo.id])
|
}, [config, ddo.id])
|
||||||
|
|
||||||
// Get and set user DT balance
|
// Get and set user DT balance
|
||||||
@ -72,6 +70,7 @@ export default function AssetActions(): ReactElement {
|
|||||||
|
|
||||||
// Check user balance against price
|
// Check user balance against price
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (price?.type === 'free') setIsBalanceSufficient(true)
|
||||||
if (!price?.value || !account || !balance?.ocean || !dtBalance) return
|
if (!price?.value || !account || !balance?.ocean || !dtBalance) return
|
||||||
|
|
||||||
setIsBalanceSufficient(
|
setIsBalanceSufficient(
|
||||||
|
@ -5,11 +5,14 @@ import { AssetSelectionAsset } from '../../molecules/FormFields/AssetSelection'
|
|||||||
import AssetComputeList from '../../molecules/AssetComputeList'
|
import AssetComputeList from '../../molecules/AssetComputeList'
|
||||||
import { useOcean } from '../../../providers/Ocean'
|
import { useOcean } from '../../../providers/Ocean'
|
||||||
import { useAsset } from '../../../providers/Asset'
|
import { useAsset } from '../../../providers/Asset'
|
||||||
|
import { DDO } from '@oceanprotocol/lib'
|
||||||
|
|
||||||
export default function AlgorithmDatasetsListForCompute({
|
export default function AlgorithmDatasetsListForCompute({
|
||||||
algorithmDid
|
algorithmDid,
|
||||||
|
dataset
|
||||||
}: {
|
}: {
|
||||||
algorithmDid: string
|
algorithmDid: string
|
||||||
|
dataset: DDO
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const { config } = useOcean()
|
const { config } = useOcean()
|
||||||
const { type } = useAsset()
|
const { type } = useAsset()
|
||||||
@ -18,8 +21,10 @@ export default function AlgorithmDatasetsListForCompute({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function getDatasetsAllowedForCompute() {
|
async function getDatasetsAllowedForCompute() {
|
||||||
|
const datasetComputeService = dataset.findServiceByType('compute')
|
||||||
const datasets = await getAlgorithmDatasetsForCompute(
|
const datasets = await getAlgorithmDatasetsForCompute(
|
||||||
algorithmDid,
|
algorithmDid,
|
||||||
|
datasetComputeService?.serviceEndpoint,
|
||||||
config.metadataCacheUri
|
config.metadataCacheUri
|
||||||
)
|
)
|
||||||
setDatasetsForCompute(datasets)
|
setDatasetsForCompute(datasets)
|
||||||
|
@ -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({
|
export default function Price({
|
||||||
ddo,
|
ddo,
|
||||||
firstPrice
|
firstPrice,
|
||||||
|
free
|
||||||
}: {
|
}: {
|
||||||
ddo: DDO
|
ddo: DDO
|
||||||
firstPrice?: string
|
firstPrice?: string
|
||||||
|
free?: boolean
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const [field, meta] = useField('price')
|
const [field, meta] = useField('price')
|
||||||
const { getDTName, getDTSymbol } = usePricing()
|
const { getDTName, getDTSymbol } = usePricing()
|
||||||
@ -38,6 +40,15 @@ export default function Price({
|
|||||||
<div className={styles.price}>
|
<div className={styles.price}>
|
||||||
<div className={styles.grid}>
|
<div className={styles.grid}>
|
||||||
<div className={styles.form}>
|
<div className={styles.form}>
|
||||||
|
{free ? (
|
||||||
|
<Input
|
||||||
|
value="0"
|
||||||
|
name="price"
|
||||||
|
type="number"
|
||||||
|
prefix="OCEAN"
|
||||||
|
readOnly
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
<Input
|
<Input
|
||||||
value={field.value}
|
value={field.value}
|
||||||
name="price"
|
name="price"
|
||||||
@ -49,6 +60,7 @@ export default function Price({
|
|||||||
<Conversion price={field.value} className={styles.conversion} />
|
<Conversion price={field.value} className={styles.conversion} />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<Error meta={meta} />
|
<Error meta={meta} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.datatoken}>
|
<div className={styles.datatoken}>
|
||||||
|
@ -45,3 +45,8 @@
|
|||||||
padding-left: var(--spacer);
|
padding-left: var(--spacer);
|
||||||
padding-right: 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 Tabs from '../../../../atoms/Tabs'
|
||||||
import Fixed from './Fixed'
|
import Fixed from './Fixed'
|
||||||
import Dynamic from './Dynamic'
|
import Dynamic from './Dynamic'
|
||||||
|
import Free from './Free'
|
||||||
import { useFormikContext } from 'formik'
|
import { useFormikContext } from 'formik'
|
||||||
import { useUserPreferences } from '../../../../../providers/UserPreferences'
|
import { useUserPreferences } from '../../../../../providers/UserPreferences'
|
||||||
import { PriceOptionsMarket } from '../../../../../@types/MetaData'
|
import { PriceOptionsMarket } from '../../../../../@types/MetaData'
|
||||||
@ -33,6 +34,7 @@ export default function FormPricing({
|
|||||||
const type = tabName.toLowerCase()
|
const type = tabName.toLowerCase()
|
||||||
setFieldValue('type', type)
|
setFieldValue('type', type)
|
||||||
type === 'fixed' && setFieldValue('dtAmount', 1000)
|
type === 'fixed' && setFieldValue('dtAmount', 1000)
|
||||||
|
type === 'free' && price < 1 && setFieldValue('price', 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always update everything when price value changes
|
// Always update everything when price value changes
|
||||||
@ -57,6 +59,12 @@ export default function FormPricing({
|
|||||||
title: content.dynamic.title,
|
title: content.dynamic.title,
|
||||||
content: <Dynamic content={content.dynamic} ddo={ddo} />
|
content: <Dynamic content={content.dynamic} ddo={ddo} />
|
||||||
}
|
}
|
||||||
|
: undefined,
|
||||||
|
appConfig.allowFreePricing === 'true'
|
||||||
|
? {
|
||||||
|
title: content.free.title,
|
||||||
|
content: <Free content={content.free} ddo={ddo} />
|
||||||
|
}
|
||||||
: undefined
|
: undefined
|
||||||
].filter((tab) => tab !== undefined)
|
].filter((tab) => tab !== undefined)
|
||||||
|
|
||||||
|
@ -40,6 +40,10 @@ const query = graphql`
|
|||||||
marketplaceFee
|
marketplaceFee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free {
|
||||||
|
title
|
||||||
|
info
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,11 @@ const columns = [
|
|||||||
{
|
{
|
||||||
name: 'Finished',
|
name: 'Finished',
|
||||||
selector: function getTimeRow(row: ComputeJobMetaData) {
|
selector: function getTimeRow(row: ComputeJobMetaData) {
|
||||||
return <Time date={row.dateFinished} isUnix relative />
|
return row.dateFinished ? (
|
||||||
|
<Time date={row.dateFinished} isUnix relative />
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -117,6 +121,7 @@ export default function ComputeJobs(): ReactElement {
|
|||||||
|
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
|
|
||||||
|
// await refetch()
|
||||||
const dtList = []
|
const dtList = []
|
||||||
const computeJobs: ComputeJobMetaData[] = []
|
const computeJobs: ComputeJobMetaData[] = []
|
||||||
for (let i = 0; i < data.tokenOrders.length; i++) {
|
for (let i = 0; i < data.tokenOrders.length; i++) {
|
||||||
|
@ -85,7 +85,7 @@ function SectionQueryResult({
|
|||||||
appConfig.metadataCacheUri,
|
appConfig.metadataCacheUri,
|
||||||
source.token
|
source.token
|
||||||
)
|
)
|
||||||
if (result.totalResults <= 15) {
|
if (queryData && result.totalResults > 0 && result.totalResults <= 15) {
|
||||||
const searchDIDs = queryData.split(' ')
|
const searchDIDs = queryData.split(' ')
|
||||||
const sortedAssets = sortElements(result.results, searchDIDs)
|
const sortedAssets = sortElements(result.results, searchDIDs)
|
||||||
// We take more assets than we need from the subgraph (to make sure
|
// We take more assets than we need from the subgraph (to make sure
|
||||||
@ -95,7 +95,6 @@ function SectionQueryResult({
|
|||||||
sortedAssets.splice(sortedAssets.length - overflow, overflow)
|
sortedAssets.splice(sortedAssets.length - overflow, overflow)
|
||||||
result.results = sortedAssets
|
result.results = sortedAssets
|
||||||
}
|
}
|
||||||
if (result.results.length === 0) return
|
|
||||||
setResult(result)
|
setResult(result)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -25,7 +25,7 @@ export default function FilterPrice({
|
|||||||
const [serviceSelections, setServiceSelections] = useState<string[]>([])
|
const [serviceSelections, setServiceSelections] = useState<string[]>([])
|
||||||
|
|
||||||
async function applyServiceFilter(filterBy: string) {
|
async function applyServiceFilter(filterBy: string) {
|
||||||
let urlLocation = await addExistingParamsToUrl(location, 'serviceType')
|
let urlLocation = await addExistingParamsToUrl(location, ['serviceType'])
|
||||||
if (filterBy && location.search.indexOf('&serviceType') === -1) {
|
if (filterBy && location.search.indexOf('&serviceType') === -1) {
|
||||||
urlLocation = `${urlLocation}&serviceType=${filterBy}`
|
urlLocation = `${urlLocation}&serviceType=${filterBy}`
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ export default function FilterPrice({
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function applyClearFilter() {
|
async function applyClearFilter() {
|
||||||
let urlLocation = await addExistingParamsToUrl(location, 'serviceType')
|
let urlLocation = await addExistingParamsToUrl(location, ['serviceType'])
|
||||||
|
|
||||||
urlLocation = `${urlLocation}`
|
urlLocation = `${urlLocation}`
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ export default function SearchPage({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!appConfig.metadataCacheUri) return
|
if (!appConfig.metadataCacheUri) return
|
||||||
|
|
||||||
async function initSearch() {
|
async function initSearch() {
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setTotalResults(undefined)
|
setTotalResults(undefined)
|
||||||
@ -66,7 +65,7 @@ export default function SearchPage({
|
|||||||
<Permission eventType="browse">
|
<Permission eventType="browse">
|
||||||
<>
|
<>
|
||||||
<div className={styles.search}>
|
<div className={styles.search}>
|
||||||
{(text || owner) && (
|
{(text || owner || tags) && (
|
||||||
<SearchBar initialValue={(text || owner) as string} />
|
<SearchBar initialValue={(text || owner) as string} />
|
||||||
)}
|
)}
|
||||||
<div className={styles.row}>
|
<div className={styles.row}>
|
||||||
|
@ -11,7 +11,10 @@ import classNames from 'classnames/bind'
|
|||||||
|
|
||||||
const cx = classNames.bind(styles)
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
const sortItems = [{ display: 'Published', value: SortTermOptions.Created }]
|
const sortItems = [
|
||||||
|
// { display: 'Relevance', value: SortTermOptions.Relevance },
|
||||||
|
{ display: 'Published', value: SortTermOptions.Created }
|
||||||
|
]
|
||||||
|
|
||||||
export default function Sort({
|
export default function Sort({
|
||||||
sortType,
|
sortType,
|
||||||
@ -31,10 +34,11 @@ export default function Sort({
|
|||||||
async function sortResults(sortBy?: string, direction?: string) {
|
async function sortResults(sortBy?: string, direction?: string) {
|
||||||
let urlLocation: string
|
let urlLocation: string
|
||||||
if (sortBy) {
|
if (sortBy) {
|
||||||
|
urlLocation = await addExistingParamsToUrl(location, ['sort'])
|
||||||
urlLocation = `${urlLocation}&sort=${sortBy}`
|
urlLocation = `${urlLocation}&sort=${sortBy}`
|
||||||
setSortType(sortBy)
|
setSortType(sortBy)
|
||||||
} else if (direction) {
|
} else if (direction) {
|
||||||
urlLocation = await addExistingParamsToUrl(location, 'sortOrder')
|
urlLocation = await addExistingParamsToUrl(location, ['sortOrder'])
|
||||||
urlLocation = `${urlLocation}&sortOrder=${direction}`
|
urlLocation = `${urlLocation}&sortOrder=${direction}`
|
||||||
setSortDirection(direction)
|
setSortDirection(direction)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
import {
|
import { QueryResult } from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
|
||||||
SearchQuery,
|
|
||||||
QueryResult
|
|
||||||
} from '@oceanprotocol/lib/dist/node/metadatacache/MetadataCache'
|
|
||||||
import { MetadataCache, Logger } from '@oceanprotocol/lib'
|
import { MetadataCache, Logger } from '@oceanprotocol/lib'
|
||||||
import queryString from 'query-string'
|
import queryString from 'query-string'
|
||||||
|
|
||||||
export const SortTermOptions = {
|
export const SortTermOptions = {
|
||||||
Created: 'created'
|
Created: 'created',
|
||||||
|
Relevance: '_score'
|
||||||
} as const
|
} as const
|
||||||
type SortTermOptions = typeof SortTermOptions[keyof typeof SortTermOptions]
|
type SortTermOptions = typeof SortTermOptions[keyof typeof SortTermOptions]
|
||||||
|
|
||||||
@ -39,8 +37,11 @@ function addTypeFilterToQuery(sortTerm: string, typeFilter: string): string {
|
|||||||
return sortTerm
|
return sortTerm
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSortType(): string {
|
function getSortType(sortParam: string): string {
|
||||||
const sortTerm = SortTermOptions.Created
|
const sortTerm =
|
||||||
|
sortParam === SortTermOptions.Created
|
||||||
|
? SortTermOptions.Created
|
||||||
|
: SortTermOptions.Relevance
|
||||||
return sortTerm
|
return sortTerm
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,9 +55,11 @@ export function getSearchQuery(
|
|||||||
sort?: string,
|
sort?: string,
|
||||||
sortOrder?: string,
|
sortOrder?: string,
|
||||||
serviceType?: string
|
serviceType?: string
|
||||||
): SearchQuery {
|
): any {
|
||||||
const sortTerm = getSortType()
|
const sortTerm = getSortType(sort)
|
||||||
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
|
const sortValue = sortOrder === SortValueOptions.Ascending ? 1 : -1
|
||||||
|
const emptySearchTerm = text === undefined || text === ''
|
||||||
|
|
||||||
let searchTerm = owner
|
let searchTerm = owner
|
||||||
? `(publicKey.owner:${owner})`
|
? `(publicKey.owner:${owner})`
|
||||||
: tags
|
: tags
|
||||||
@ -67,41 +70,84 @@ export function getSearchQuery(
|
|||||||
`(service.attributes.additionalInformation.categories:\"${categories}\")`
|
`(service.attributes.additionalInformation.categories:\"${categories}\")`
|
||||||
: text || ''
|
: text || ''
|
||||||
|
|
||||||
// HACK: resolves the case sensitivity related to dataTokenInfo.symbol
|
searchTerm = searchTerm.trim()
|
||||||
searchTerm = '*' + searchTerm.toUpperCase() + '*'
|
let modifiedSearchTerm = searchTerm.split(' ').join(' OR ').trim()
|
||||||
|
modifiedSearchTerm = addTypeFilterToQuery(modifiedSearchTerm, serviceType)
|
||||||
searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
|
searchTerm = addTypeFilterToQuery(searchTerm, serviceType)
|
||||||
|
const prefixedSearchTerm =
|
||||||
|
emptySearchTerm && searchTerm
|
||||||
|
? searchTerm
|
||||||
|
: !emptySearchTerm && searchTerm
|
||||||
|
? '*' + searchTerm + '*'
|
||||||
|
: '**'
|
||||||
|
|
||||||
return {
|
return {
|
||||||
page: Number(page) || 1,
|
page: Number(page) || 1,
|
||||||
offset: Number(offset) || 21,
|
offset: Number(offset) || 21,
|
||||||
query: {
|
query: {
|
||||||
|
bool: {
|
||||||
|
must: [
|
||||||
|
{
|
||||||
|
bool: {
|
||||||
|
should: [
|
||||||
|
{
|
||||||
query_string: {
|
query_string: {
|
||||||
query: `${searchTerm} -isInPurgatory:true`,
|
query: `${modifiedSearchTerm}`,
|
||||||
fields: [
|
fields: [
|
||||||
|
'id',
|
||||||
|
'publicKey.owner',
|
||||||
|
'dataToken',
|
||||||
|
'dataTokenInfo.name',
|
||||||
|
'dataTokenInfo.symbol',
|
||||||
|
'service.attributes.main.name^10',
|
||||||
|
'service.attributes.main.author',
|
||||||
|
'service.attributes.additionalInformation.description',
|
||||||
|
'service.attributes.additionalInformation.tags'
|
||||||
|
],
|
||||||
|
minimum_should_match: '2<75%',
|
||||||
|
phrase_slop: 2,
|
||||||
|
boost: 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
match_phrase: {
|
||||||
|
content: {
|
||||||
|
query: `${searchTerm}`,
|
||||||
|
boost: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query_string: {
|
||||||
|
query: `${prefixedSearchTerm}`,
|
||||||
|
fields: [
|
||||||
|
'id',
|
||||||
|
'publicKey.owner',
|
||||||
|
'dataToken',
|
||||||
'dataTokenInfo.name',
|
'dataTokenInfo.name',
|
||||||
'dataTokenInfo.symbol',
|
'dataTokenInfo.symbol',
|
||||||
'service.attributes.main.name',
|
'service.attributes.main.name',
|
||||||
'service.attributes.main.author',
|
'service.attributes.main.author',
|
||||||
'service.attributes.additionalInformation.description'
|
'service.attributes.additionalInformation.description',
|
||||||
|
'service.attributes.additionalInformation.tags'
|
||||||
],
|
],
|
||||||
default_operator: 'AND'
|
default_operator: 'AND'
|
||||||
}
|
}
|
||||||
// ...(owner && { 'publicKey.owner': [owner] }),
|
}
|
||||||
// ...(tags && { tags: [tags] }),
|
]
|
||||||
// ...(categories && { categories: [categories] })
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
term: {
|
||||||
|
isInPurgatory: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
sort: {
|
sort: {
|
||||||
[sortTerm]: sortValue
|
[sortTerm]: sortValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Something in ocean.js is weird when using 'tags: [tag]'
|
|
||||||
// which is the only way the query actually returns desired results.
|
|
||||||
// But it doesn't follow 'SearchQuery' interface so we have to assign
|
|
||||||
// it here.
|
|
||||||
// } as SearchQuery
|
|
||||||
|
|
||||||
// And the next hack,
|
|
||||||
// nativeSearch is not implmeneted on ocean.js typings
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,9 +169,9 @@ export async function getResults(
|
|||||||
text,
|
text,
|
||||||
owner,
|
owner,
|
||||||
tags,
|
tags,
|
||||||
|
categories,
|
||||||
page,
|
page,
|
||||||
offset,
|
offset,
|
||||||
categories,
|
|
||||||
sort,
|
sort,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
serviceType
|
serviceType
|
||||||
@ -143,25 +189,20 @@ export async function getResults(
|
|||||||
sortOrder,
|
sortOrder,
|
||||||
serviceType
|
serviceType
|
||||||
)
|
)
|
||||||
|
|
||||||
const queryResult = await metadataCache.queryMetadata(searchQuery)
|
const queryResult = await metadataCache.queryMetadata(searchQuery)
|
||||||
return queryResult
|
return queryResult
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function addExistingParamsToUrl(
|
export async function addExistingParamsToUrl(
|
||||||
location: Location,
|
location: Location,
|
||||||
excludedParam: string,
|
excludedParams: string[]
|
||||||
secondExcludedParam?: string
|
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const parsed = queryString.parse(location.search)
|
const parsed = queryString.parse(location.search)
|
||||||
let urlLocation = '/search?'
|
let urlLocation = '/search?'
|
||||||
if (Object.keys(parsed).length > 0) {
|
if (Object.keys(parsed).length > 0) {
|
||||||
for (const querryParam in parsed) {
|
for (const querryParam in parsed) {
|
||||||
if (
|
if (!excludedParams.includes(querryParam)) {
|
||||||
querryParam !== excludedParam &&
|
if (querryParam === 'page' && excludedParams.includes('text')) {
|
||||||
querryParam !== secondExcludedParam
|
|
||||||
) {
|
|
||||||
if (querryParam === 'page' && excludedParam === 'text') {
|
|
||||||
Logger.log('remove page when starting a new search')
|
Logger.log('remove page when starting a new search')
|
||||||
} else {
|
} else {
|
||||||
const value = parsed[querryParam]
|
const value = parsed[querryParam]
|
||||||
@ -170,7 +211,10 @@ export async function addExistingParamsToUrl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
urlLocation = `${urlLocation}sort=${SortTermOptions.Created}&sortOrder=${SortValueOptions.Descending}&`
|
// sort should be relevance when fixed in aqua
|
||||||
|
urlLocation = `${urlLocation}sort=${encodeURIComponent(
|
||||||
|
SortTermOptions.Created
|
||||||
|
)}&sortOrder=${SortValueOptions.Descending}&`
|
||||||
}
|
}
|
||||||
urlLocation = urlLocation.slice(0, -1)
|
urlLocation = urlLocation.slice(0, -1)
|
||||||
return urlLocation
|
return urlLocation
|
||||||
|
@ -5,7 +5,9 @@ import { Decimal } from 'decimal.js'
|
|||||||
import {
|
import {
|
||||||
getCreatePricingPoolFeedback,
|
getCreatePricingPoolFeedback,
|
||||||
getCreatePricingExchangeFeedback,
|
getCreatePricingExchangeFeedback,
|
||||||
getBuyDTFeedback
|
getBuyDTFeedback,
|
||||||
|
getCreateFreePricingFeedback,
|
||||||
|
getDispenseFeedback
|
||||||
} from '../utils/feedback'
|
} from '../utils/feedback'
|
||||||
import { sleep } from '../utils'
|
import { sleep } from '../utils'
|
||||||
|
|
||||||
@ -16,7 +18,7 @@ interface PriceOptions {
|
|||||||
price: number
|
price: number
|
||||||
dtAmount: number
|
dtAmount: number
|
||||||
oceanAmount: number
|
oceanAmount: number
|
||||||
type: 'fixed' | 'dynamic' | string
|
type: 'fixed' | 'dynamic' | 'free' | string
|
||||||
weightOnDataToken: string
|
weightOnDataToken: string
|
||||||
swapFee: string
|
swapFee: string
|
||||||
}
|
}
|
||||||
@ -68,7 +70,7 @@ function usePricing(): UsePricing {
|
|||||||
// Helper for setting steps & feedback for all flows
|
// Helper for setting steps & feedback for all flows
|
||||||
async function setStep(
|
async function setStep(
|
||||||
index: number,
|
index: number,
|
||||||
type: 'pool' | 'exchange' | 'buy',
|
type: 'pool' | 'exchange' | 'free' | 'buy' | 'dispense',
|
||||||
ddo: DDO
|
ddo: DDO
|
||||||
) {
|
) {
|
||||||
const dtSymbol = await getDTSymbol(ddo)
|
const dtSymbol = await getDTSymbol(ddo)
|
||||||
@ -84,9 +86,15 @@ function usePricing(): UsePricing {
|
|||||||
case 'exchange':
|
case 'exchange':
|
||||||
messages = getCreatePricingExchangeFeedback(dtSymbol)
|
messages = getCreatePricingExchangeFeedback(dtSymbol)
|
||||||
break
|
break
|
||||||
|
case 'free':
|
||||||
|
messages = getCreateFreePricingFeedback(dtSymbol)
|
||||||
|
break
|
||||||
case 'buy':
|
case 'buy':
|
||||||
messages = getBuyDTFeedback(dtSymbol)
|
messages = getBuyDTFeedback(dtSymbol)
|
||||||
break
|
break
|
||||||
|
case 'dispense':
|
||||||
|
messages = getDispenseFeedback(dtSymbol)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
setPricingStepText(messages[index])
|
setPricingStepText(messages[index])
|
||||||
@ -180,6 +188,28 @@ function usePricing(): UsePricing {
|
|||||||
Logger.log('DT exchange buy response', tx)
|
Logger.log('DT exchange buy response', tx)
|
||||||
break
|
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) {
|
} catch (error) {
|
||||||
setPricingError(error.message)
|
setPricingError(error.message)
|
||||||
@ -219,9 +249,14 @@ function usePricing(): UsePricing {
|
|||||||
setStep(99, 'pool', ddo)
|
setStep(99, 'pool', ddo)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (type === 'free') {
|
||||||
|
setStep(99, 'free', ddo)
|
||||||
|
await ocean.OceanDispenser.activate(dataToken, '1', '1', accountId)
|
||||||
|
} else {
|
||||||
// if fixedPrice set dt to max amount
|
// if fixedPrice set dt to max amount
|
||||||
if (!isPool) dtAmount = 1000
|
if (!isPool) dtAmount = 1000
|
||||||
await mint(`${dtAmount}`, ddo)
|
await mint(`${dtAmount}`, ddo)
|
||||||
|
}
|
||||||
|
|
||||||
// dtAmount for fixed price is set to max
|
// dtAmount for fixed price is set to max
|
||||||
const tx = isPool
|
const tx = isPool
|
||||||
@ -235,9 +270,13 @@ function usePricing(): UsePricing {
|
|||||||
swapFee
|
swapFee
|
||||||
)
|
)
|
||||||
.next((step: number) => setStep(step, 'pool', ddo))
|
.next((step: number) => setStep(step, 'pool', ddo))
|
||||||
: await ocean.fixedRateExchange
|
: type === 'fixed'
|
||||||
|
? await ocean.fixedRateExchange
|
||||||
.create(dataToken, `${price}`, accountId, `${dtAmount}`)
|
.create(dataToken, `${price}`, accountId, `${dtAmount}`)
|
||||||
.next((step: number) => setStep(step, 'exchange', ddo))
|
.next((step: number) => setStep(step, 'exchange', ddo))
|
||||||
|
: await ocean.OceanDispenser.makeMinter(dataToken, accountId).next(
|
||||||
|
(step: number) => setStep(step, 'free', ddo)
|
||||||
|
)
|
||||||
await sleep(20000)
|
await sleep(20000)
|
||||||
return tx
|
return tx
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -29,6 +29,7 @@ interface UseSiteMetadata {
|
|||||||
portisId: string
|
portisId: string
|
||||||
allowFixedPricing: string
|
allowFixedPricing: string
|
||||||
allowDynamicPricing: string
|
allowDynamicPricing: string
|
||||||
|
allowFreePricing: string
|
||||||
allowAdvancedSettings: string
|
allowAdvancedSettings: string
|
||||||
credentialType: string
|
credentialType: string
|
||||||
}
|
}
|
||||||
@ -65,6 +66,7 @@ const query = graphql`
|
|||||||
portisId
|
portisId
|
||||||
allowFixedPricing
|
allowFixedPricing
|
||||||
allowDynamicPricing
|
allowDynamicPricing
|
||||||
|
allowFreePricing
|
||||||
allowAdvancedSettings
|
allowAdvancedSettings
|
||||||
credentialType
|
credentialType
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,9 @@ function getCredentialList(
|
|||||||
const credentialByType = credential.find(
|
const credentialByType = credential.find(
|
||||||
(credential) => credential.type === credentialType
|
(credential) => credential.type === credentialType
|
||||||
)
|
)
|
||||||
return credentialByType.value && credentialByType.value.length > 0
|
return credentialByType &&
|
||||||
|
credentialByType.value &&
|
||||||
|
credentialByType.value.length > 0
|
||||||
? credentialByType.value
|
? credentialByType.value
|
||||||
: []
|
: []
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ export const validationSchema: Yup.SchemaOf<PriceOptionsMarket> =
|
|||||||
.min(21, (param) => `Must be more or equal to ${param.min}`)
|
.min(21, (param) => `Must be more or equal to ${param.min}`)
|
||||||
.required('Required'),
|
.required('Required'),
|
||||||
type: Yup.string()
|
type: Yup.string()
|
||||||
.matches(/fixed|dynamic/g, { excludeEmptyString: true })
|
.matches(/fixed|dynamic|free/g, { excludeEmptyString: true })
|
||||||
.required('Required'),
|
.required('Required'),
|
||||||
weightOnDataToken: Yup.string().required('Required'),
|
weightOnDataToken: Yup.string().required('Required'),
|
||||||
weightOnOcean: Yup.string().required('Required'),
|
weightOnOcean: Yup.string().required('Required'),
|
||||||
|
@ -121,6 +121,7 @@ export async function getAssetsNames(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function transformDDOToAssetSelection(
|
export async function transformDDOToAssetSelection(
|
||||||
|
datasetProviderEndpoint: string,
|
||||||
ddoList: DDO[],
|
ddoList: DDO[],
|
||||||
metadataCacheUri: string,
|
metadataCacheUri: string,
|
||||||
selectedAlgorithms?: PublisherTrustedAlgorithm[]
|
selectedAlgorithms?: PublisherTrustedAlgorithm[]
|
||||||
@ -129,14 +130,22 @@ export async function transformDDOToAssetSelection(
|
|||||||
const didList: string[] = []
|
const didList: string[] = []
|
||||||
const priceList: PriceList = await getAssetsPriceList(ddoList)
|
const priceList: PriceList = await getAssetsPriceList(ddoList)
|
||||||
const symbolList: any = {}
|
const symbolList: any = {}
|
||||||
|
const didProviderEndpointMap: any = {}
|
||||||
for (const ddo of ddoList) {
|
for (const ddo of ddoList) {
|
||||||
didList.push(ddo.id)
|
didList.push(ddo.id)
|
||||||
symbolList[ddo.id] = ddo.dataTokenInfo.symbol
|
symbolList[ddo.id] = ddo.dataTokenInfo.symbol
|
||||||
|
const algoComputeService = ddo.findServiceByType('compute')
|
||||||
|
algoComputeService?.serviceEndpoint &&
|
||||||
|
(didProviderEndpointMap[ddo.id] = algoComputeService?.serviceEndpoint)
|
||||||
}
|
}
|
||||||
const ddoNames = await getAssetsNames(didList, metadataCacheUri, source.token)
|
const ddoNames = await getAssetsNames(didList, metadataCacheUri, source.token)
|
||||||
const algorithmList: AssetSelectionAsset[] = []
|
const algorithmList: AssetSelectionAsset[] = []
|
||||||
didList?.forEach((did: string) => {
|
didList?.forEach((did: string) => {
|
||||||
if (priceList[did]) {
|
if (
|
||||||
|
priceList[did] &&
|
||||||
|
(!didProviderEndpointMap[did] ||
|
||||||
|
didProviderEndpointMap[did] === datasetProviderEndpoint)
|
||||||
|
) {
|
||||||
let selected = false
|
let selected = false
|
||||||
selectedAlgorithms?.forEach((algorithm: PublisherTrustedAlgorithm) => {
|
selectedAlgorithms?.forEach((algorithm: PublisherTrustedAlgorithm) => {
|
||||||
if (algorithm.did === did) {
|
if (algorithm.did === did) {
|
||||||
@ -165,6 +174,7 @@ export async function transformDDOToAssetSelection(
|
|||||||
|
|
||||||
export async function getAlgorithmDatasetsForCompute(
|
export async function getAlgorithmDatasetsForCompute(
|
||||||
algorithmId: string,
|
algorithmId: string,
|
||||||
|
datasetProviderUri: string,
|
||||||
metadataCacheUri: string
|
metadataCacheUri: string
|
||||||
): Promise<AssetSelectionAsset[]> {
|
): Promise<AssetSelectionAsset[]> {
|
||||||
const source = axios.CancelToken.source()
|
const source = axios.CancelToken.source()
|
||||||
@ -186,6 +196,7 @@ export async function getAlgorithmDatasetsForCompute(
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const datasets = await transformDDOToAssetSelection(
|
const datasets = await transformDDOToAssetSelection(
|
||||||
|
datasetProviderUri,
|
||||||
computeDatasetsForCurrentAlgorithm,
|
computeDatasetsForCurrentAlgorithm,
|
||||||
metadataCacheUri,
|
metadataCacheUri,
|
||||||
[]
|
[]
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
const cleanupContentType = (contentType: string): string => {
|
const cleanupContentType = (contentType: string): string => {
|
||||||
|
// strip away the `charset=utf-8`
|
||||||
|
const contentSplit = contentType.split(';')[0]
|
||||||
// strip away the 'application/' part
|
// strip away the 'application/' part
|
||||||
const contentTypeSplit = contentType.split('/')[1]
|
const contentTypeSplit = contentSplit.split('/')[1]
|
||||||
|
|
||||||
if (!contentTypeSplit) return contentType
|
if (!contentTypeSplit) return contentType
|
||||||
|
|
||||||
|
@ -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 } {
|
export function getBuyDTFeedback(dtSymbol: string): { [key: number]: string } {
|
||||||
return {
|
return {
|
||||||
1: '1/3 Approving OCEAN ...',
|
1: '1/3 Approving OCEAN ...',
|
||||||
@ -67,3 +78,12 @@ export function getSellDTFeedback(dtSymbol: string): { [key: number]: string } {
|
|||||||
3: `3/3 ${dtSymbol} sold.`
|
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
|
||||||
|
}
|
@ -1,23 +1,18 @@
|
|||||||
import {
|
import { ConfigHelper, ConfigHelperConfig, Logger } from '@oceanprotocol/lib'
|
||||||
ConfigHelper,
|
|
||||||
ConfigHelperConfig,
|
|
||||||
ConfigHelperNetworkId,
|
|
||||||
ConfigHelperNetworkName,
|
|
||||||
Logger
|
|
||||||
} from '@oceanprotocol/lib'
|
|
||||||
import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
|
import contractAddresses from '@oceanprotocol/contracts/artifacts/address.json'
|
||||||
import { AbiItem } from 'web3-utils/types'
|
import { AbiItem } from 'web3-utils/types'
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
|
|
||||||
export function getOceanConfig(
|
export function getOceanConfig(network: string | number): ConfigHelperConfig {
|
||||||
network: ConfigHelperNetworkName | ConfigHelperNetworkId
|
|
||||||
): ConfigHelperConfig {
|
|
||||||
const config = new ConfigHelper().getConfig(
|
const config = new ConfigHelper().getConfig(
|
||||||
network,
|
network,
|
||||||
network === 'polygon' ||
|
network === 'polygon' ||
|
||||||
network === 137 ||
|
|
||||||
network === 'moonbeamalpha' ||
|
network === 'moonbeamalpha' ||
|
||||||
network === 1287
|
network === 1287 ||
|
||||||
|
network === 'bsc' ||
|
||||||
|
network === 56 ||
|
||||||
|
network === 'gaiaxtestnet' ||
|
||||||
|
network === 2021000
|
||||||
? undefined
|
? undefined
|
||||||
: process.env.GATSBY_INFURA_PROJECT_ID
|
: process.env.GATSBY_INFURA_PROJECT_ID
|
||||||
)
|
)
|
||||||
|
@ -4,6 +4,7 @@ import { getUrqlClientInstance } from '../providers/UrqlProvider'
|
|||||||
import { getOceanConfig } from './ocean'
|
import { getOceanConfig } from './ocean'
|
||||||
import web3 from 'web3'
|
import web3 from 'web3'
|
||||||
import schema from '../../src/@types/schema.json'
|
import schema from '../../src/@types/schema.json'
|
||||||
|
import { AssetsFreePrice } from '../@types/apollo/AssetsFreePrice'
|
||||||
|
|
||||||
export interface PriceList {
|
export interface PriceList {
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
@ -18,6 +19,36 @@ interface DidAndDatatokenMap {
|
|||||||
[name: string]: string
|
[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`
|
const FreQuery = gql`
|
||||||
query AssetsFrePrice($datatoken_in: [String!]) {
|
query AssetsFrePrice($datatoken_in: [String!]) {
|
||||||
fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) {
|
fixedRateExchanges(orderBy: id, where: { datatoken_in: $datatoken_in }) {
|
||||||
@ -141,7 +172,8 @@ export async function getPreviousOrders(
|
|||||||
|
|
||||||
function transformPriceToBestPrice(
|
function transformPriceToBestPrice(
|
||||||
frePrice: AssetsFrePriceFixedRateExchanges[],
|
frePrice: AssetsFrePriceFixedRateExchanges[],
|
||||||
poolPrice: AssetsPoolPricePools[]
|
poolPrice: AssetsPoolPricePools[],
|
||||||
|
freePrice: AssetFreePriceDispenser[]
|
||||||
) {
|
) {
|
||||||
if (poolPrice?.length > 0) {
|
if (poolPrice?.length > 0) {
|
||||||
const price: BestPrice = {
|
const price: BestPrice = {
|
||||||
@ -171,6 +203,18 @@ function transformPriceToBestPrice(
|
|||||||
isConsumable: 'true'
|
isConsumable: 'true'
|
||||||
}
|
}
|
||||||
return price
|
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 {
|
} else {
|
||||||
const price: BestPrice = {
|
const price: BestPrice = {
|
||||||
type: '',
|
type: '',
|
||||||
@ -190,8 +234,9 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
|||||||
assets: DDO[]
|
assets: DDO[]
|
||||||
): Promise<
|
): Promise<
|
||||||
[
|
[
|
||||||
AssetsPoolPricePools[],
|
ApolloQueryResult<AssetsPoolPrice>,
|
||||||
AssetsFrePriceFixedRateExchanges[],
|
ApolloQueryResult<AssetsFrePrice>,
|
||||||
|
ApolloQueryResult<AssetsFreePrice>,
|
||||||
DidAndDatatokenMap
|
DidAndDatatokenMap
|
||||||
]
|
]
|
||||||
> {
|
> {
|
||||||
@ -210,6 +255,7 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
|||||||
}
|
}
|
||||||
let poolPriceResponse: AssetsPoolPricePools[] = []
|
let poolPriceResponse: AssetsPoolPricePools[] = []
|
||||||
let frePriceResponse: AssetsFrePriceFixedRateExchanges[] = []
|
let frePriceResponse: AssetsFrePriceFixedRateExchanges[] = []
|
||||||
|
let freePriceResponse: AssetFreePriceDispenser[] = []
|
||||||
|
|
||||||
for (const chainKey in chainAssetLists) {
|
for (const chainKey in chainAssetLists) {
|
||||||
const freVariables = {
|
const freVariables = {
|
||||||
@ -218,7 +264,9 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
|||||||
const poolVariables = {
|
const poolVariables = {
|
||||||
datatokenAddress_in: chainAssetLists[chainKey]
|
datatokenAddress_in: chainAssetLists[chainKey]
|
||||||
}
|
}
|
||||||
|
const freeVariables = {
|
||||||
|
datatoken_in: chainAssetLists[chainKey]
|
||||||
|
}
|
||||||
// harcoded until we have chainId on assets
|
// harcoded until we have chainId on assets
|
||||||
const queryContext: OperationContext = {
|
const queryContext: OperationContext = {
|
||||||
url: `${getSubgrahUri(1)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
url: `${getSubgrahUri(1)}/subgraphs/name/oceanprotocol/ocean-subgraph`,
|
||||||
@ -236,22 +284,29 @@ async function getAssetsPoolsExchangesAndDatatokenMap(
|
|||||||
frePriceResponse = frePriceResponse.concat(
|
frePriceResponse = frePriceResponse.concat(
|
||||||
chainFrePriceResponse.data.fixedRateExchanges
|
chainFrePriceResponse.data.fixedRateExchanges
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
return [poolPriceResponse, frePriceResponse, didDTMap]
|
const chainFreePriceResponse: OperationResult<AssetsFreePrice> =
|
||||||
|
await fetchData(FreeQuery, freeVariables, queryContext)
|
||||||
|
freePriceResponse = freePriceResponse.concat(
|
||||||
|
chainFreePriceResponse.data.dispensers
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return [poolPriceResponse, frePriceResponse, freePriceResponse, didDTMap]
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAssetsPriceList(assets: DDO[]): Promise<PriceList> {
|
export async function getAssetsPriceList(assets: DDO[]): Promise<PriceList> {
|
||||||
const priceList: PriceList = {}
|
const priceList: PriceList = {}
|
||||||
|
|
||||||
const values: [
|
const values: [
|
||||||
AssetsPoolPricePools[],
|
ApolloQueryResult<AssetsPoolPrice>,
|
||||||
AssetsFrePriceFixedRateExchanges[],
|
ApolloQueryResult<AssetsFrePrice>,
|
||||||
|
ApolloQueryResult<AssetsFreePrice>,
|
||||||
DidAndDatatokenMap
|
DidAndDatatokenMap
|
||||||
] = await getAssetsPoolsExchangesAndDatatokenMap(assets)
|
] = await getAssetsPoolsExchangesAndDatatokenMap(assets)
|
||||||
const poolPriceResponse = values[0]
|
const poolPriceResponse = values[0]
|
||||||
const frePriceResponse = values[1]
|
const frePriceResponse = values[1]
|
||||||
const didDTMap: DidAndDatatokenMap = values[2]
|
const freePriceResponse = values[2]
|
||||||
|
const didDTMap: DidAndDatatokenMap = values[3]
|
||||||
|
|
||||||
for (const poolPrice of poolPriceResponse) {
|
for (const poolPrice of poolPriceResponse) {
|
||||||
priceList[didDTMap[poolPrice.datatokenAddress]] =
|
priceList[didDTMap[poolPrice.datatokenAddress]] =
|
||||||
@ -262,6 +317,9 @@ export async function getAssetsPriceList(assets: DDO[]): Promise<PriceList> {
|
|||||||
for (const frePrice of frePriceResponse) {
|
for (const frePrice of frePriceResponse) {
|
||||||
priceList[didDTMap[frePrice.datatoken?.address]] = frePrice.rate
|
priceList[didDTMap[frePrice.datatoken?.address]] = frePrice.rate
|
||||||
}
|
}
|
||||||
|
for (const freePrice of freePriceResponse.data?.dispensers) {
|
||||||
|
priceList[didDTMap[freePrice.datatoken?.address]] = '0'
|
||||||
|
}
|
||||||
return priceList
|
return priceList
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +327,9 @@ export async function getPrice(asset: DDO): Promise<BestPrice> {
|
|||||||
const freVariables = {
|
const freVariables = {
|
||||||
datatoken: asset?.dataToken.toLowerCase()
|
datatoken: asset?.dataToken.toLowerCase()
|
||||||
}
|
}
|
||||||
|
const freeVariables = {
|
||||||
|
datatoken: asset?.dataToken.toLowerCase()
|
||||||
|
}
|
||||||
const poolVariables = {
|
const poolVariables = {
|
||||||
datatokenAddress: asset?.dataToken.toLowerCase()
|
datatokenAddress: asset?.dataToken.toLowerCase()
|
||||||
}
|
}
|
||||||
@ -289,10 +349,16 @@ export async function getPrice(asset: DDO): Promise<BestPrice> {
|
|||||||
freVariables,
|
freVariables,
|
||||||
queryContext
|
queryContext
|
||||||
)
|
)
|
||||||
|
const freePriceResponse: ApolloQueryResult<AssetsFreePrice> = await fetchData(
|
||||||
|
AssetFreeQuery,
|
||||||
|
freeVariables,
|
||||||
|
queryContext
|
||||||
|
)
|
||||||
|
|
||||||
const bestPrice: BestPrice = transformPriceToBestPrice(
|
const bestPrice: BestPrice = transformPriceToBestPrice(
|
||||||
frePriceResponse.data.fixedRateExchanges,
|
frePriceResponse.data.fixedRateExchanges,
|
||||||
poolPriceResponse.data.pools
|
poolPriceResponse.data.pools,
|
||||||
|
freePriceResponse.data.dispensers
|
||||||
)
|
)
|
||||||
|
|
||||||
return bestPrice
|
return bestPrice
|
||||||
@ -304,26 +370,34 @@ export async function getAssetsBestPrices(
|
|||||||
const assetsWithPrice: AssetListPrices[] = []
|
const assetsWithPrice: AssetListPrices[] = []
|
||||||
|
|
||||||
const values: [
|
const values: [
|
||||||
AssetsPoolPricePools[],
|
ApolloQueryResult<AssetsPoolPrice>,
|
||||||
AssetsFrePriceFixedRateExchanges[],
|
ApolloQueryResult<AssetsFrePrice>,
|
||||||
|
ApolloQueryResult<AssetsFreePrice>,
|
||||||
DidAndDatatokenMap
|
DidAndDatatokenMap
|
||||||
] = await getAssetsPoolsExchangesAndDatatokenMap(assets)
|
] = await getAssetsPoolsExchangesAndDatatokenMap(assets)
|
||||||
const poolPriceResponse = values[0]
|
const poolPriceResponse = values[0]
|
||||||
const frePriceResponse = values[1]
|
const frePriceResponse = values[1]
|
||||||
|
const freePriceResponse = values[2]
|
||||||
|
|
||||||
for (const ddo of assets) {
|
for (const ddo of assets) {
|
||||||
const dataToken = ddo.dataToken.toLowerCase()
|
const dataToken = ddo.dataToken.toLowerCase()
|
||||||
const poolPrice: AssetsPoolPricePools[] = []
|
const poolPrice: AssetsPoolPricePools[] = []
|
||||||
const frePrice: AssetsFrePriceFixedRateExchanges[] = []
|
const frePrice: AssetsFrePriceFixedRateExchanges[] = []
|
||||||
const pool = poolPriceResponse.find(
|
const freePrice: AssetFreePriceDispenser[] = []
|
||||||
|
const pool = poolPriceResponse.data?.pools.find(
|
||||||
(pool: any) => pool.datatokenAddress === dataToken
|
(pool: any) => pool.datatokenAddress === dataToken
|
||||||
)
|
)
|
||||||
|
|
||||||
pool && poolPrice.push(pool)
|
pool && poolPrice.push(pool)
|
||||||
const fre = frePriceResponse.find(
|
const fre = frePriceResponse.find(
|
||||||
(fre: any) => fre.datatoken.address === dataToken
|
(fre: any) => fre.datatoken.address === dataToken
|
||||||
)
|
)
|
||||||
fre && frePrice.push(fre)
|
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({
|
assetsWithPrice.push({
|
||||||
ddo: ddo,
|
ddo: ddo,
|
||||||
price: bestPrice
|
price: bestPrice
|
||||||
|
@ -44,6 +44,9 @@ export function getNetworkDisplayName(
|
|||||||
case 8996:
|
case 8996:
|
||||||
displayName = 'Development'
|
displayName = 'Development'
|
||||||
break
|
break
|
||||||
|
case 2021000:
|
||||||
|
displayName = 'GAIA-X'
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
displayName = `${data.chain} ${
|
displayName = `${data.chain} ${
|
||||||
data.network === 'mainnet' ? '' : data.network
|
data.network === 'mainnet' ? '' : data.network
|
||||||
|
Loading…
Reference in New Issue
Block a user