mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Fetching prices from Aquarius in AssetList component (#1774)
* Fetching prices from Aquarius in AssetList component * Removing unused imports * Removing fetching logic from AssetList * Using Asset Price from Aquarius * removing unused code for loader * Updating ocean.js * Updating price format in tests * removing console logs * Fixing build issues * Updating condition for showing free price * Fixing tests * Removing logs * Showing No pricing schema available on asset teaser * Showing No pricing schema available on asset detail page * Adding additional tests * Removing console logs * Avoiding getInitialPaymentCollector failure (#1816) * early return is no web3 or ddo * Creating test for MetaFull * adding test: src/components/Asset/AssetContent/MetaSecondary.test.tsx * Adding test for bookmarks * Adding test for displaying payment collector * Removing comments * Renaming assetAquarius * Renaming assetWithAccessDetails * Ensuring that the payment collector is shown even without a wallet connected * Removing broken test * Using getDummyWeb3 for fetching the payment collector address * google validation (#1835) * Updating validation to exclude any google link * Updating Yup validation * Checking if domain includes google.com * Updating isGoogleUrl function * Moving isGoogleUrl into @utils/url/index file * isGoogleUrl function * Updating tests * Adding additional tests for other google domains * Updating tests * Updating isGoogleUrl file path * Updating pricing message (#1842) * Bump @storybook/addon-essentials from 6.5.13 to 6.5.15 (#1841) Bumps [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/addons/essentials) from 6.5.13 to 6.5.15. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.15/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.5.15/addons/essentials) --- updated-dependencies: - dependency-name: "@storybook/addon-essentials" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump @types/jest from 29.2.3 to 29.2.5 (#1840) Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 29.2.3 to 29.2.5. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest) --- updated-dependencies: - dependency-name: "@types/jest" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump prettier from 2.8.0 to 2.8.1 (#1837) Bumps [prettier](https://github.com/prettier/prettier) from 2.8.0 to 2.8.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.8.0...2.8.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump react-select from 5.6.1 to 5.7.0 (#1839) Bumps [react-select](https://github.com/JedWatson/react-select) from 5.6.1 to 5.7.0. - [Release notes](https://github.com/JedWatson/react-select/releases) - [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/JedWatson/react-select/compare/react-select@5.6.1...react-select@5.7.0) --- updated-dependencies: - dependency-name: react-select dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump react-tabs from 5.1.0 to 6.0.0 (#1838) Bumps [react-tabs](https://github.com/reactjs/react-tabs) from 5.1.0 to 6.0.0. - [Release notes](https://github.com/reactjs/react-tabs/releases) - [Commits](https://github.com/reactjs/react-tabs/compare/v5.1.0...v6.0.0) --- updated-dependencies: - dependency-name: react-tabs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix asset route (#1836) * updating the buy button message for free assets * Updating pricing text for compute and algorithms * Updating tests * Adding a seperate sentence about paying gas fees for network charges with free assets * Fixing tests Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> * Showing hosting type in File Info (#1846) * Bump @storybook/addon-essentials from 6.5.13 to 6.5.15 (#1841) Bumps [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/addons/essentials) from 6.5.13 to 6.5.15. - [Release notes](https://github.com/storybookjs/storybook/releases) - [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.15/CHANGELOG.md) - [Commits](https://github.com/storybookjs/storybook/commits/v6.5.15/addons/essentials) --- updated-dependencies: - dependency-name: "@storybook/addon-essentials" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump @types/jest from 29.2.3 to 29.2.5 (#1840) Bumps [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest) from 29.2.3 to 29.2.5. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest) --- updated-dependencies: - dependency-name: "@types/jest" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump prettier from 2.8.0 to 2.8.1 (#1837) Bumps [prettier](https://github.com/prettier/prettier) from 2.8.0 to 2.8.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.8.0...2.8.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump react-select from 5.6.1 to 5.7.0 (#1839) Bumps [react-select](https://github.com/JedWatson/react-select) from 5.6.1 to 5.7.0. - [Release notes](https://github.com/JedWatson/react-select/releases) - [Changelog](https://github.com/JedWatson/react-select/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/JedWatson/react-select/compare/react-select@5.6.1...react-select@5.7.0) --- updated-dependencies: - dependency-name: react-select dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump react-tabs from 5.1.0 to 6.0.0 (#1838) Bumps [react-tabs](https://github.com/reactjs/react-tabs) from 5.1.0 to 6.0.0. - [Release notes](https://github.com/reactjs/react-tabs/releases) - [Commits](https://github.com/reactjs/react-tabs/compare/v5.1.0...v6.0.0) --- updated-dependencies: - dependency-name: react-tabs dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix asset route (#1836) * Adding hosting type to the file info component * Writting smart contract hosting type across two lines Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> * add initial price value for not supported price assets (#1851) * Updating test * Updating accessDetailsAndPricing * Adding orderPriceAndFees back in to show the price with fees on the asset detail page * Using price with fees for compute assets * Fixing conversions by ensuring that the symbol is always sent through * Removing unwanted changes in package-lock.json * Updating use of isUnsupportedPricing variable * Getting rid of getAccessDetailsForAssets completely * Removing unused imports and query * Fixing test * Removing unused import --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mihaisc <mihai.scarlat@smartcontrol.ro> Co-authored-by: Bogdan Fazakas <bogdan.fazakas@gmail.com>
This commit is contained in:
parent
5a935fcd48
commit
ed4645e13c
@ -1,3 +0,0 @@
|
|||||||
import { assets } from '../../__fixtures__/datasetsWithAccessDetails'
|
|
||||||
|
|
||||||
export const getAccessDetailsForAssets = jest.fn().mockResolvedValue(assets)
|
|
@ -5,11 +5,6 @@ import {
|
|||||||
TokenPriceQuery_token as TokenPrice
|
TokenPriceQuery_token as TokenPrice
|
||||||
} from '../@types/subgraph/TokenPriceQuery'
|
} from '../@types/subgraph/TokenPriceQuery'
|
||||||
import {
|
import {
|
||||||
TokensPriceQuery,
|
|
||||||
TokensPriceQuery_tokens as TokensPrice
|
|
||||||
} from '../@types/subgraph/TokensPriceQuery'
|
|
||||||
import {
|
|
||||||
Asset,
|
|
||||||
LoggerInstance,
|
LoggerInstance,
|
||||||
ProviderFees,
|
ProviderFees,
|
||||||
ProviderInstance
|
ProviderInstance
|
||||||
@ -21,64 +16,6 @@ import {
|
|||||||
publisherMarketOrderFee
|
publisherMarketOrderFee
|
||||||
} from '../../app.config'
|
} from '../../app.config'
|
||||||
|
|
||||||
const tokensPriceQuery = gql`
|
|
||||||
query TokensPriceQuery($datatokenIds: [ID!], $account: String) {
|
|
||||||
tokens(first: 1000, where: { id_in: $datatokenIds }) {
|
|
||||||
id
|
|
||||||
symbol
|
|
||||||
name
|
|
||||||
publishMarketFeeAddress
|
|
||||||
publishMarketFeeToken
|
|
||||||
publishMarketFeeAmount
|
|
||||||
templateId
|
|
||||||
orders(
|
|
||||||
where: { payer: $account }
|
|
||||||
orderBy: createdTimestamp
|
|
||||||
orderDirection: desc
|
|
||||||
) {
|
|
||||||
tx
|
|
||||||
serviceIndex
|
|
||||||
createdTimestamp
|
|
||||||
reuses(orderBy: createdTimestamp, orderDirection: desc) {
|
|
||||||
id
|
|
||||||
caller
|
|
||||||
createdTimestamp
|
|
||||||
tx
|
|
||||||
block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dispensers {
|
|
||||||
id
|
|
||||||
active
|
|
||||||
isMinter
|
|
||||||
maxBalance
|
|
||||||
token {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
symbol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fixedRateExchanges {
|
|
||||||
id
|
|
||||||
exchangeId
|
|
||||||
price
|
|
||||||
publishMarketSwapFee
|
|
||||||
baseToken {
|
|
||||||
symbol
|
|
||||||
name
|
|
||||||
address
|
|
||||||
decimals
|
|
||||||
}
|
|
||||||
datatoken {
|
|
||||||
symbol
|
|
||||||
name
|
|
||||||
address
|
|
||||||
}
|
|
||||||
active
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
const tokenPriceQuery = gql`
|
const tokenPriceQuery = gql`
|
||||||
query TokenPriceQuery($datatokenId: ID!, $account: String) {
|
query TokenPriceQuery($datatokenId: ID!, $account: String) {
|
||||||
token(id: $datatokenId) {
|
token(id: $datatokenId) {
|
||||||
@ -139,7 +76,7 @@ const tokenPriceQuery = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
function getAccessDetailsFromTokenPrice(
|
function getAccessDetailsFromTokenPrice(
|
||||||
tokenPrice: TokenPrice | TokensPrice,
|
tokenPrice: TokenPrice,
|
||||||
timeout?: number
|
timeout?: number
|
||||||
): AccessDetails {
|
): AccessDetails {
|
||||||
const accessDetails = {} as AccessDetails
|
const accessDetails = {} as AccessDetails
|
||||||
@ -216,7 +153,7 @@ export async function getOrderPriceAndFees(
|
|||||||
providerFees?: ProviderFees
|
providerFees?: ProviderFees
|
||||||
): Promise<OrderPriceAndFees> {
|
): Promise<OrderPriceAndFees> {
|
||||||
const orderPriceAndFee = {
|
const orderPriceAndFee = {
|
||||||
price: '0',
|
price: String(asset?.stats?.price?.value || '0'),
|
||||||
publisherMarketOrderFee: publisherMarketOrderFee || '0',
|
publisherMarketOrderFee: publisherMarketOrderFee || '0',
|
||||||
publisherMarketFixedSwapFee: '0',
|
publisherMarketFixedSwapFee: '0',
|
||||||
consumeMarketOrderFee: consumeMarketOrderFee || '0',
|
consumeMarketOrderFee: consumeMarketOrderFee || '0',
|
||||||
@ -291,56 +228,3 @@ export async function getAccessDetails(
|
|||||||
LoggerInstance.error('Error getting access details: ', error.message)
|
LoggerInstance.error('Error getting access details: ', error.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAccessDetailsForAssets(
|
|
||||||
assets: Asset[],
|
|
||||||
account = ''
|
|
||||||
): Promise<AssetExtended[]> {
|
|
||||||
const assetsExtended: AssetExtended[] = assets
|
|
||||||
const chainAssetLists: { [key: number]: string[] } = {}
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (const asset of assets) {
|
|
||||||
if (chainAssetLists[asset.chainId]) {
|
|
||||||
chainAssetLists[asset.chainId].push(
|
|
||||||
asset.services[0].datatokenAddress.toLowerCase()
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
chainAssetLists[asset.chainId] = []
|
|
||||||
chainAssetLists[asset.chainId].push(
|
|
||||||
asset.services[0].datatokenAddress.toLowerCase()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const chainKey in chainAssetLists) {
|
|
||||||
const queryContext = getQueryContext(Number(chainKey))
|
|
||||||
const tokenQueryResult: OperationResult<
|
|
||||||
TokensPriceQuery,
|
|
||||||
{ datatokenIds: [string]; account: string }
|
|
||||||
> = await fetchData(
|
|
||||||
tokensPriceQuery,
|
|
||||||
{
|
|
||||||
datatokenIds: chainAssetLists[chainKey],
|
|
||||||
account: account?.toLowerCase()
|
|
||||||
},
|
|
||||||
queryContext
|
|
||||||
)
|
|
||||||
tokenQueryResult?.data?.tokens?.forEach((token) => {
|
|
||||||
const currentAsset = assetsExtended.find(
|
|
||||||
(asset) =>
|
|
||||||
asset.services[0].datatokenAddress.toLowerCase() === token.id
|
|
||||||
)
|
|
||||||
const accessDetails = getAccessDetailsFromTokenPrice(
|
|
||||||
token,
|
|
||||||
currentAsset?.services[0]?.timeout
|
|
||||||
)
|
|
||||||
|
|
||||||
currentAsset.accessDetails = accessDetails
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return assetsExtended
|
|
||||||
} catch (error) {
|
|
||||||
LoggerInstance.error('Error getting access details: ', error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { getAccessDetailsForAssets } from './accessDetailsAndPricing'
|
|
||||||
import { PublisherTrustedAlgorithm, Asset } from '@oceanprotocol/lib'
|
import { PublisherTrustedAlgorithm, Asset } from '@oceanprotocol/lib'
|
||||||
import { AssetSelectionAsset } from '@shared/FormInput/InputElement/AssetSelection'
|
import { AssetSelectionAsset } from '@shared/FormInput/InputElement/AssetSelection'
|
||||||
import { getServiceByName } from './ddo'
|
import { getServiceByName } from './ddo'
|
||||||
@ -8,17 +7,14 @@ export async function transformAssetToAssetSelection(
|
|||||||
assets: Asset[],
|
assets: Asset[],
|
||||||
selectedAlgorithms?: PublisherTrustedAlgorithm[]
|
selectedAlgorithms?: PublisherTrustedAlgorithm[]
|
||||||
): Promise<AssetSelectionAsset[]> {
|
): Promise<AssetSelectionAsset[]> {
|
||||||
const extendedAssets: AssetExtended[] = await getAccessDetailsForAssets(
|
|
||||||
assets
|
|
||||||
)
|
|
||||||
const algorithmList: AssetSelectionAsset[] = []
|
const algorithmList: AssetSelectionAsset[] = []
|
||||||
|
|
||||||
for (const asset of extendedAssets) {
|
for (const asset of assets) {
|
||||||
const algoService =
|
const algoService =
|
||||||
getServiceByName(asset, 'compute') || getServiceByName(asset, 'access')
|
getServiceByName(asset, 'compute') || getServiceByName(asset, 'access')
|
||||||
|
|
||||||
if (
|
if (
|
||||||
asset?.accessDetails?.price &&
|
asset?.stats?.price?.value &&
|
||||||
algoService?.serviceEndpoint === datasetProviderEndpoint
|
algoService?.serviceEndpoint === datasetProviderEndpoint
|
||||||
) {
|
) {
|
||||||
let selected = false
|
let selected = false
|
||||||
@ -30,7 +26,7 @@ export async function transformAssetToAssetSelection(
|
|||||||
const algorithmAsset: AssetSelectionAsset = {
|
const algorithmAsset: AssetSelectionAsset = {
|
||||||
did: asset.id,
|
did: asset.id,
|
||||||
name: asset.metadata.name,
|
name: asset.metadata.name,
|
||||||
price: asset.accessDetails.price,
|
price: asset.stats.price.value,
|
||||||
checked: selected,
|
checked: selected,
|
||||||
symbol: asset.datatokens[0].symbol
|
symbol: asset.datatokens[0].symbol
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,7 @@
|
|||||||
import AssetTeaser from '@shared/AssetTeaser'
|
import AssetTeaser from '@shared/AssetTeaser'
|
||||||
import React, { ReactElement, useEffect, useState } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import Pagination from '@shared/Pagination'
|
import Pagination from '@shared/Pagination'
|
||||||
import styles from './index.module.css'
|
import styles from './index.module.css'
|
||||||
import Loader from '@shared/atoms/Loader'
|
|
||||||
import { useIsMounted } from '@hooks/useIsMounted'
|
|
||||||
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
|
||||||
|
|
||||||
function LoaderArea() {
|
|
||||||
return (
|
|
||||||
<div className={styles.loaderWrap}>
|
|
||||||
<Loader />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export declare type AssetListProps = {
|
export declare type AssetListProps = {
|
||||||
assets: AssetExtended[]
|
assets: AssetExtended[]
|
||||||
@ -33,52 +21,27 @@ export default function AssetList({
|
|||||||
showPagination,
|
showPagination,
|
||||||
page,
|
page,
|
||||||
totalPages,
|
totalPages,
|
||||||
isLoading,
|
|
||||||
onPageChange,
|
onPageChange,
|
||||||
className,
|
className,
|
||||||
noPublisher,
|
noPublisher,
|
||||||
noDescription,
|
noDescription,
|
||||||
noPrice
|
noPrice
|
||||||
}: AssetListProps): ReactElement {
|
}: AssetListProps): ReactElement {
|
||||||
const { accountId } = useWeb3()
|
// This changes the page field inside the query
|
||||||
const [assetsWithPrices, setAssetsWithPrices] =
|
|
||||||
useState<AssetExtended[]>(assets)
|
|
||||||
const [loading, setLoading] = useState<boolean>(isLoading)
|
|
||||||
const isMounted = useIsMounted()
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!assets || !assets.length) return
|
|
||||||
|
|
||||||
setAssetsWithPrices(assets as AssetExtended[])
|
|
||||||
setLoading(false)
|
|
||||||
async function fetchPrices() {
|
|
||||||
const assetsWithPrices = await getAccessDetailsForAssets(
|
|
||||||
assets,
|
|
||||||
accountId || ''
|
|
||||||
)
|
|
||||||
if (!isMounted() || !assetsWithPrices) return
|
|
||||||
setAssetsWithPrices([...assetsWithPrices])
|
|
||||||
}
|
|
||||||
fetchPrices()
|
|
||||||
}, [assets, isMounted, accountId])
|
|
||||||
|
|
||||||
// // This changes the page field inside the query
|
|
||||||
function handlePageChange(selected: number) {
|
function handlePageChange(selected: number) {
|
||||||
onPageChange(selected + 1)
|
onPageChange(selected + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleClasses = `${styles.assetList} ${className || ''}`
|
const styleClasses = `${styles.assetList} ${className || ''}`
|
||||||
|
|
||||||
return loading ? (
|
return (
|
||||||
<LoaderArea />
|
|
||||||
) : (
|
|
||||||
<>
|
<>
|
||||||
<div className={styleClasses}>
|
<div className={styleClasses}>
|
||||||
{assetsWithPrices?.length > 0 ? (
|
{assets?.length > 0 ? (
|
||||||
assetsWithPrices?.map((assetWithPrice) => (
|
assets?.map((asset) => (
|
||||||
<AssetTeaser
|
<AssetTeaser
|
||||||
asset={assetWithPrice}
|
asset={asset}
|
||||||
key={assetWithPrice.id}
|
key={asset.id}
|
||||||
noPublisher={noPublisher}
|
noPublisher={noPublisher}
|
||||||
noDescription={noDescription}
|
noDescription={noDescription}
|
||||||
noPrice={noPrice}
|
noPrice={noPrice}
|
||||||
|
@ -1,8 +1,23 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
import testRender from '../../../../.jest/testRender'
|
import testRender from '../../../../.jest/testRender'
|
||||||
import AssetTeaser from './index'
|
import AssetTeaser from './index'
|
||||||
import { asset } from '../../../../.jest/__fixtures__/datasetWithAccessDetails'
|
import { asset } from '../../../../.jest/__fixtures__/datasetWithAccessDetails'
|
||||||
|
|
||||||
describe('@shared/AssetTeaser', () => {
|
describe('@shared/AssetTeaser', () => {
|
||||||
testRender(<AssetTeaser asset={asset} />)
|
testRender(<AssetTeaser asset={asset} />)
|
||||||
|
|
||||||
|
it('renders no pricing schema available', () => {
|
||||||
|
asset.stats.price = null
|
||||||
|
render(<AssetTeaser asset={asset} />)
|
||||||
|
expect(screen.getByText('No pricing schema available')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('This is a test.')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
it('renders asset teaser with no description', () => {
|
||||||
|
asset.metadata.description = null
|
||||||
|
render(<AssetTeaser asset={asset} />)
|
||||||
|
expect(
|
||||||
|
screen.queryByText('This is a test description')
|
||||||
|
).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -21,16 +21,18 @@ export declare type AssetTeaserProps = {
|
|||||||
export default function AssetTeaser({
|
export default function AssetTeaser({
|
||||||
asset,
|
asset,
|
||||||
noPublisher,
|
noPublisher,
|
||||||
noDescription,
|
noDescription
|
||||||
noPrice
|
|
||||||
}: AssetTeaserProps): ReactElement {
|
}: AssetTeaserProps): ReactElement {
|
||||||
const { name, type, description } = asset.metadata
|
const { name, type, description } = asset.metadata
|
||||||
const { datatokens } = asset
|
const { datatokens } = asset
|
||||||
const isCompute = Boolean(getServiceByName(asset, 'compute'))
|
const isCompute = Boolean(getServiceByName(asset, 'compute'))
|
||||||
const accessType = isCompute ? 'compute' : 'access'
|
const accessType = isCompute ? 'compute' : 'access'
|
||||||
const { owner } = asset.nft
|
const { owner } = asset.nft
|
||||||
const { orders, allocated } = asset.stats
|
const { orders, allocated, price } = asset.stats
|
||||||
const isUnsupportedPricing = asset?.accessDetails?.type === 'NOT_SUPPORTED'
|
const isUnsupportedPricing =
|
||||||
|
!asset.services.length ||
|
||||||
|
asset?.stats?.price?.value === undefined ||
|
||||||
|
asset?.accessDetails?.type === 'NOT_SUPPORTED'
|
||||||
const { locale } = useUserPreferences()
|
const { locale } = useUserPreferences()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -60,15 +62,13 @@ export default function AssetTeaser({
|
|||||||
</Dotdotdot>
|
</Dotdotdot>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!noPrice && (
|
|
||||||
<div className={styles.price}>
|
<div className={styles.price}>
|
||||||
{isUnsupportedPricing || !asset.services.length ? (
|
{isUnsupportedPricing ? (
|
||||||
<strong>No pricing schema available</strong>
|
<strong>No pricing schema available</strong>
|
||||||
) : (
|
) : (
|
||||||
<Price accessDetails={asset.accessDetails} size="small" />
|
<Price price={price} assetId={asset.id} size="small" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
{allocated && allocated > 0 ? (
|
{allocated && allocated > 0 ? (
|
||||||
<span className={styles.typeLabel}>
|
<span className={styles.typeLabel}>
|
||||||
|
@ -7,21 +7,21 @@ describe('@shared/FormInput/InputElement/AssetSelection', () => {
|
|||||||
{
|
{
|
||||||
did: 'did:op:xxx',
|
did: 'did:op:xxx',
|
||||||
name: 'Asset',
|
name: 'Asset',
|
||||||
price: '10',
|
price: 10,
|
||||||
checked: false,
|
checked: false,
|
||||||
symbol: 'OCEAN'
|
symbol: 'OCEAN'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
did: 'did:op:yyy',
|
did: 'did:op:yyy',
|
||||||
name: 'Asset',
|
name: 'Asset',
|
||||||
price: '10',
|
price: 10,
|
||||||
checked: true,
|
checked: true,
|
||||||
symbol: 'OCEAN'
|
symbol: 'OCEAN'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
did: 'did:op:zzz',
|
did: 'did:op:zzz',
|
||||||
name: 'Asset',
|
name: 'Asset',
|
||||||
price: '0',
|
price: 0,
|
||||||
checked: false,
|
checked: false,
|
||||||
symbol: 'OCEAN'
|
symbol: 'OCEAN'
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import styles from './index.module.css'
|
|||||||
export interface AssetSelectionAsset {
|
export interface AssetSelectionAsset {
|
||||||
did: string
|
did: string
|
||||||
name: string
|
name: string
|
||||||
price: string
|
price: number
|
||||||
checked: boolean
|
checked: boolean
|
||||||
symbol: string
|
symbol: string
|
||||||
}
|
}
|
||||||
@ -106,8 +106,7 @@ export default function AssetSelection({
|
|||||||
</label>
|
</label>
|
||||||
|
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={Number(asset.price)}
|
price={asset.price}
|
||||||
type={asset.price === '0' ? 'free' : undefined}
|
|
||||||
size="small"
|
size="small"
|
||||||
className={styles.price}
|
className={styles.price}
|
||||||
/>
|
/>
|
||||||
|
@ -59,14 +59,14 @@ describe('@shared/FormInput', () => {
|
|||||||
{
|
{
|
||||||
did: 'did:op:xxx',
|
did: 'did:op:xxx',
|
||||||
name: 'Asset',
|
name: 'Asset',
|
||||||
price: '10',
|
price: 10,
|
||||||
checked: false,
|
checked: false,
|
||||||
symbol: 'OCEAN'
|
symbol: 'OCEAN'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
did: 'did:op:yyy',
|
did: 'did:op:yyy',
|
||||||
name: 'Asset',
|
name: 'Asset',
|
||||||
price: '10',
|
price: 10,
|
||||||
checked: true,
|
checked: true,
|
||||||
symbol: 'OCEAN'
|
symbol: 'OCEAN'
|
||||||
}
|
}
|
||||||
|
@ -10,11 +10,9 @@ export default function PriceUnit({
|
|||||||
size = 'small',
|
size = 'small',
|
||||||
conversion,
|
conversion,
|
||||||
symbol,
|
symbol,
|
||||||
type,
|
|
||||||
decimals
|
decimals
|
||||||
}: {
|
}: {
|
||||||
price: number
|
price: number
|
||||||
type?: string
|
|
||||||
className?: string
|
className?: string
|
||||||
size?: 'small' | 'mini' | 'large'
|
size?: 'small' | 'mini' | 'large'
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
@ -25,12 +23,14 @@ export default function PriceUnit({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.price} ${styles[size]} ${className}`}>
|
<div className={`${styles.price} ${styles[size]} ${className}`}>
|
||||||
{type === 'free' ? (
|
{price === 0 ? (
|
||||||
<div>Free</div>
|
<div>Free</div>
|
||||||
|
) : !price || Number.isNaN(price) ? (
|
||||||
|
<div>-</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div>
|
||||||
{Number.isNaN(price) ? '-' : formatNumber(price, locale, decimals)}{' '}
|
{formatNumber(price, locale, decimals)}
|
||||||
<span className={styles.symbol}>{symbol}</span>
|
<span className={styles.symbol}>{symbol}</span>
|
||||||
</div>
|
</div>
|
||||||
{conversion && <Conversion price={price} symbol={symbol} />}
|
{conversion && <Conversion price={price} symbol={symbol} />}
|
||||||
|
@ -13,39 +13,25 @@ describe('@shared/Price', () => {
|
|||||||
it('renders fixed price', () => {
|
it('renders fixed price', () => {
|
||||||
render(
|
render(
|
||||||
<Price
|
<Price
|
||||||
accessDetails={{ ...asset.accessDetails, type: 'fixed', price: '10' }}
|
price={{ value: 10, tokenSymbol: 'OCEAN', tokenAddress: '0x123' }}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
expect(screen.getByText('10')).toBeInTheDocument()
|
expect(screen.getByText('10')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders free price', () => {
|
it('renders free price', () => {
|
||||||
render(<Price accessDetails={{ ...asset.accessDetails, type: 'free' }} />)
|
render(<Price price={{ value: 0 }} />)
|
||||||
expect(screen.getByText('Free')).toBeInTheDocument()
|
expect(screen.getByText('Free')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders null price', () => {
|
it('renders null price', () => {
|
||||||
render(<Price accessDetails={{ ...asset.accessDetails, price: null }} />)
|
render(<Price price={{ value: null }} />)
|
||||||
expect(screen.getByText('-')).toBeInTheDocument()
|
expect(screen.getByText('-')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders conversion', async () => {
|
it('renders conversion', async () => {
|
||||||
render(
|
render(<Price price={asset.stats.price} conversion />)
|
||||||
<Price
|
|
||||||
accessDetails={{ ...asset.accessDetails, price: '10' }}
|
|
||||||
conversion
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
expect(await screen.findByText('≈')).toBeInTheDocument()
|
expect(await screen.findByText('≈')).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders no conversion when no price defined', async () => {
|
it('renders no conversion when no price defined', async () => {
|
||||||
render(
|
render(<Price price={{ value: null, tokenSymbol: 'TEST' }} conversion />)
|
||||||
<Price
|
|
||||||
accessDetails={{ ...asset.accessDetails, price: null }}
|
|
||||||
conversion
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
expect(screen.queryByText('≈')).not.toBeInTheDocument()
|
expect(screen.queryByText('≈')).not.toBeInTheDocument()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,32 +1,30 @@
|
|||||||
import React, { ReactElement } from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
|
import { AssetPrice } from '@oceanprotocol/lib'
|
||||||
import PriceUnit from './PriceUnit'
|
import PriceUnit from './PriceUnit'
|
||||||
|
|
||||||
export default function Price({
|
export default function Price({
|
||||||
accessDetails,
|
price,
|
||||||
orderPriceAndFees,
|
orderPriceAndFees,
|
||||||
className,
|
className,
|
||||||
size,
|
size,
|
||||||
conversion
|
conversion
|
||||||
}: {
|
}: {
|
||||||
accessDetails: AccessDetails
|
price: AssetPrice
|
||||||
orderPriceAndFees?: OrderPriceAndFees
|
orderPriceAndFees?: OrderPriceAndFees
|
||||||
|
assetId?: string
|
||||||
className?: string
|
className?: string
|
||||||
conversion?: boolean
|
conversion?: boolean
|
||||||
size?: 'small' | 'mini' | 'large'
|
size?: 'small' | 'mini' | 'large'
|
||||||
}): ReactElement {
|
}): ReactElement {
|
||||||
const isSupported =
|
if (!price && !orderPriceAndFees) return
|
||||||
accessDetails?.type === 'free' ||
|
|
||||||
(accessDetails?.type === 'fixed' && accessDetails?.baseToken?.symbol)
|
|
||||||
const price = `${orderPriceAndFees?.price || accessDetails?.price}`
|
|
||||||
|
|
||||||
return isSupported ? (
|
return (
|
||||||
<PriceUnit
|
<PriceUnit
|
||||||
price={Number(price)}
|
price={Number(orderPriceAndFees?.price) || price?.value}
|
||||||
symbol={accessDetails?.baseToken?.symbol}
|
symbol={price?.tokenSymbol}
|
||||||
className={className}
|
className={className}
|
||||||
size={size}
|
size={size}
|
||||||
conversion={conversion}
|
conversion={conversion}
|
||||||
type={accessDetails?.type}
|
|
||||||
/>
|
/>
|
||||||
) : null
|
)
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,7 @@ export default function Compute({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Price
|
<Price
|
||||||
accessDetails={asset?.accessDetails}
|
price={asset.stats?.price}
|
||||||
orderPriceAndFees={datasetOrderPriceAndFees}
|
orderPriceAndFees={datasetOrderPriceAndFees}
|
||||||
conversion
|
conversion
|
||||||
size="large"
|
size="large"
|
||||||
|
@ -51,6 +51,9 @@ export default function Download({
|
|||||||
const [retry, setRetry] = useState<boolean>(false)
|
const [retry, setRetry] = useState<boolean>(false)
|
||||||
|
|
||||||
const isUnsupportedPricing =
|
const isUnsupportedPricing =
|
||||||
|
!asset?.accessDetails ||
|
||||||
|
!asset.services.length ||
|
||||||
|
asset?.stats?.price?.value === undefined ||
|
||||||
asset?.accessDetails?.type === 'NOT_SUPPORTED' ||
|
asset?.accessDetails?.type === 'NOT_SUPPORTED' ||
|
||||||
(asset?.accessDetails?.type === 'fixed' &&
|
(asset?.accessDetails?.type === 'fixed' &&
|
||||||
!asset?.accessDetails?.baseToken?.symbol)
|
!asset?.accessDetails?.baseToken?.symbol)
|
||||||
@ -60,7 +63,7 @@ export default function Download({
|
|||||||
}, [asset?.nft.state])
|
}, [asset?.nft.state])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!asset?.accessDetails || isUnsupportedPricing) return
|
if (isUnsupportedPricing) return
|
||||||
|
|
||||||
setIsOwned(asset?.accessDetails?.isOwned || false)
|
setIsOwned(asset?.accessDetails?.isOwned || false)
|
||||||
setValidOrderTx(asset?.accessDetails?.validOrderTx || '')
|
setValidOrderTx(asset?.accessDetails?.validOrderTx || '')
|
||||||
@ -100,7 +103,6 @@ export default function Download({
|
|||||||
(asset?.accessDetails?.type === 'fixed' && !orderPriceAndFees) ||
|
(asset?.accessDetails?.type === 'fixed' && !orderPriceAndFees) ||
|
||||||
!isMounted ||
|
!isMounted ||
|
||||||
!accountId ||
|
!accountId ||
|
||||||
!asset?.accessDetails ||
|
|
||||||
isUnsupportedPricing
|
isUnsupportedPricing
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@ -202,7 +204,7 @@ export default function Download({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{isUnsupportedPricing || !asset.services.length ? (
|
{isUnsupportedPricing ? (
|
||||||
<Alert
|
<Alert
|
||||||
className={styles.fieldWarning}
|
className={styles.fieldWarning}
|
||||||
state="info"
|
state="info"
|
||||||
@ -214,7 +216,7 @@ export default function Download({
|
|||||||
<Loader message="Calculating full price (including fees)" />
|
<Loader message="Calculating full price (including fees)" />
|
||||||
) : (
|
) : (
|
||||||
<Price
|
<Price
|
||||||
accessDetails={asset.accessDetails}
|
price={asset.stats?.price}
|
||||||
orderPriceAndFees={orderPriceAndFees}
|
orderPriceAndFees={orderPriceAndFees}
|
||||||
conversion
|
conversion
|
||||||
size="large"
|
size="large"
|
||||||
|
@ -7,7 +7,6 @@ import Tooltip from '@shared/atoms/Tooltip'
|
|||||||
import AssetTitle from '@shared/AssetListTitle'
|
import AssetTitle from '@shared/AssetListTitle'
|
||||||
import { getAssetsFromDids } from '@utils/aquarius'
|
import { getAssetsFromDids } from '@utils/aquarius'
|
||||||
import { useCancelToken } from '@hooks/useCancelToken'
|
import { useCancelToken } from '@hooks/useCancelToken'
|
||||||
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
|
||||||
import { useWeb3 } from '@context/Web3'
|
import { useWeb3 } from '@context/Web3'
|
||||||
import { useMarketMetadata } from '@context/MarketMetadata'
|
import { useMarketMetadata } from '@context/MarketMetadata'
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ const columns: TableOceanColumn<AssetExtended>[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Price',
|
name: 'Price',
|
||||||
selector: (row) => <Price accessDetails={row.accessDetails} size="small" />,
|
selector: (row) => <Price price={row.stats.price} size="small" />,
|
||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -66,11 +65,7 @@ export default function Bookmarks(): ReactElement {
|
|||||||
)
|
)
|
||||||
if (!result?.length) return
|
if (!result?.length) return
|
||||||
|
|
||||||
const pinnedAssets: AssetExtended[] = await getAccessDetailsForAssets(
|
setPinned(result)
|
||||||
result,
|
|
||||||
accountId
|
|
||||||
)
|
|
||||||
setPinned(pinnedAssets)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LoggerInstance.error(`Bookmarks error:`, error.message)
|
LoggerInstance.error(`Bookmarks error:`, error.message)
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -5,7 +5,6 @@ import Conversion from '@shared/Price/Conversion'
|
|||||||
import NumberUnit from './NumberUnit'
|
import NumberUnit from './NumberUnit'
|
||||||
import styles from './Stats.module.css'
|
import styles from './Stats.module.css'
|
||||||
import { useProfile } from '@context/Profile'
|
import { useProfile } from '@context/Profile'
|
||||||
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
|
|
||||||
import { getLocked } from '@utils/veAllocation'
|
import { getLocked } from '@utils/veAllocation'
|
||||||
import PriceUnit from '@shared/Price/PriceUnit'
|
import PriceUnit from '@shared/Price/PriceUnit'
|
||||||
import Button from '@shared/atoms/Button'
|
import Button from '@shared/atoms/Button'
|
||||||
@ -37,12 +36,10 @@ export default function Stats({
|
|||||||
|
|
||||||
async function getPublisherTotalSales() {
|
async function getPublisherTotalSales() {
|
||||||
try {
|
try {
|
||||||
const assetsPrices = await getAccessDetailsForAssets(assets)
|
|
||||||
let count = 0
|
let count = 0
|
||||||
for (const priceInfo of assetsPrices) {
|
for (const priceInfo of assets) {
|
||||||
if (priceInfo?.accessDetails?.price && priceInfo.stats.orders > 0) {
|
if (priceInfo?.stats?.price?.value && priceInfo.stats.orders > 0) {
|
||||||
count +=
|
count += priceInfo.stats.price.value * priceInfo.stats.orders
|
||||||
parseInt(priceInfo.accessDetails.price) * priceInfo.stats.orders
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTotalSales(count)
|
setTotalSales(count)
|
||||||
|
Loading…
Reference in New Issue
Block a user