From d86c45f6bd3f32991034939e4ee3a00fff038c78 Mon Sep 17 00:00:00 2001 From: Jamie Hewitt Date: Wed, 18 Jan 2023 13:35:14 +0300 Subject: [PATCH] Release candidate 09-01-2023 (#1843) * 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mihaisc * 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Signed-off-by: dependabot[bot] 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] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mihaisc * add initial price value for not supported price assets (#1851) * Fix compute basetoken issue (#1829) * fix lint * add dynamic provider fees * fixes * cleanup and more fixes * bump oceanlib to 2.6.0 * fix 404 styling (#1850) * Fixing the z-index for the tippy component (#1858) * Removing infinite approval (#1857) * Removing infinite approvals * Removing infinite approval content message * Removing infinite approval from default user preferences Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: mihaisc Co-authored-by: Bogdan Fazakas Co-authored-by: EnzoVezzaro --- .jest/__fixtures__/algorithmAquarius.ts | 91 ++++++++++++++ .../{assetAquarius.ts => datasetAquarius.ts} | 13 +- ...Details.ts => datasetWithAccessDetails.ts} | 4 +- ...etails.ts => datasetsWithAccessDetails.ts} | 2 +- .jest/__fixtures__/userPreferences.ts | 3 +- .../@utils/accessDetailsAndPricing.ts | 2 +- .jest/__mocks__/hooksMocks.ts | 2 +- content/pages/editMetadata.json | 76 ++++++------ content/price.json | 3 +- content/publish/form.json | 94 ++++++++------- package-lock.json | 32 +++-- package.json | 2 +- src/@context/UserPreferences.tsx | 21 +--- src/@hooks/useNetworkMetadata/utils.ts | 1 + src/@utils/url/index.test.ts | 19 ++- src/@utils/url/index.ts | 7 ++ src/@utils/yup.ts | 3 +- .../@shared/AssetList/index.stories.tsx | 2 +- .../@shared/AssetList/index.test.tsx | 4 +- .../@shared/AssetTeaser/index.test.tsx | 2 +- src/components/@shared/FileIcon/index.tsx | 3 + .../InputElement/FilesInput/index.tsx | 3 +- src/components/@shared/Price/index.test.tsx | 2 +- .../@shared/atoms/Tooltip/index.tsx | 2 +- .../AssetActions/ButtonBuy/index.test.tsx | 36 +++++- .../Asset/AssetActions/ButtonBuy/index.tsx | 113 +++++++++++------- .../Compute/FormComputeDataset.tsx | 14 ++- .../AssetActions/Compute/PriceOutput.tsx | 4 +- .../Asset/AssetActions/Compute/index.tsx | 26 +++- .../Asset/AssetContent/Bookmark.test.tsx | 11 ++ .../Asset/AssetContent/MetaFull.test.tsx | 17 +++ .../Asset/AssetContent/MetaFull.tsx | 9 +- .../Asset/AssetContent/MetaSecondary.test.tsx | 18 +++ src/components/Asset/Edit/EditMetadata.tsx | 2 +- .../Asset/Edit/FormEditMetadata.tsx | 3 +- .../Asset/RelatedAssets/index.test.tsx | 2 +- .../Header/UserPreferences/TokenApproval.tsx | 21 ---- .../Header/UserPreferences/index.tsx | 2 - src/components/Home/MostViews/index.test.tsx | 6 +- src/pages/404.tsx | 16 --- 40 files changed, 450 insertions(+), 243 deletions(-) create mode 100644 .jest/__fixtures__/algorithmAquarius.ts rename .jest/__fixtures__/{assetAquarius.ts => datasetAquarius.ts} (94%) rename .jest/__fixtures__/{assetWithAccessDetails.ts => datasetWithAccessDetails.ts} (89%) rename .jest/__fixtures__/{assetsWithAccessDetails.ts => datasetsWithAccessDetails.ts} (99%) create mode 100644 src/components/Asset/AssetContent/Bookmark.test.tsx create mode 100644 src/components/Asset/AssetContent/MetaFull.test.tsx create mode 100644 src/components/Asset/AssetContent/MetaSecondary.test.tsx delete mode 100644 src/components/Header/UserPreferences/TokenApproval.tsx diff --git a/.jest/__fixtures__/algorithmAquarius.ts b/.jest/__fixtures__/algorithmAquarius.ts new file mode 100644 index 000000000..f784cacd0 --- /dev/null +++ b/.jest/__fixtures__/algorithmAquarius.ts @@ -0,0 +1,91 @@ +import { Asset } from '@oceanprotocol/lib' + +export const algorithmAquarius: Asset = { + '@context': ['https://w3id.org/did/v1'], + id: 'did:op:6654b0793765b269696cec8d2f0d077d9bbcdd3c4f033d941ab9684e8ad06630', + nftAddress: '0xbA5BA7B09e2FA1eb0258f647503F81D2Af5cb07d', + version: '4.1.0', + chainId: 1, + metadata: { + created: '2022-09-29T11:30:26Z', + updated: '2022-09-29T11:30:26Z', + type: 'algorithm', + name: 'algorithmTestitest', + description: 'This is an algorithm test.', + links: ['https://www.oceanprotocol.com/sample'], + tags: [ + 'trading', + 'defi', + 'algorithm', + 'algorithmic-crypto-trading', + 'algo-trading', + 'trading-strategy', + 'cryptocurrency', + 'crypto' + ], + author: 'Test User', + license: 'https://market.oceanprotocol.com/terms', + additionalInformation: { + termsAndConditions: true + }, + algorithm: { + language: 'json', + version: '0.1', + container: { + entrypoint: 'python $algo', + tag: 'latest', + image: 'https://docker.com/test.img', + checksum: '' + } + } + }, + services: [ + { + id: 'dbc42f4c62d2452f8731fd023eacfae74e9c7a42fbd12ce84310f13342e4aab1', + type: 'access', + files: + '0x04022ef1afafe340f41b261ef721b8dd55dee094975cc70330803d760beef38871948ce572ff1c533d56cda2665749ed2eb8283e243ec5ee19011f510b6b263b2da0af537e3f1fdff7ddd90fa26c7a4761a6d26928bc1348a302634012aac7998e92c84456ab73e9a847120c44ebda15781787e8c382391b2eaefc8b8d36998f3998d1c4647f4f7bb28f4278093c1d231f66e78f81452049443b9e540aeb42ebbdc1b748c024eb10218532814736e241efa1c2a687685b4e2ea7a877685aa0ea325d1a8cf765d1b423b32d81ec3c3e22fc9c15c6b9b71f2862edaec4e4cf7c3a638ffc0ecb88ede3cabb511d4780543a53c001a95f42de1877796e13c997b57bc671507e92198934b4ea7c2e6554993388421253e8c2f10458dec872a7ebfa71b6e77ed359222c93261ba252028c5da06ccf8defcd529885b2125816325a47e23728b513', + datatokenAddress: '0x067e1E6ec580F3F0f6781679A4A5AB07A6464b08', + serviceEndpoint: 'https://v4.provider.goerli.oceanprotocol.com', + timeout: 604800 + } + ], + event: { + tx: '0x3e07a75c1cc5d4146222a93ab4319144e60ecca3ebfb8b15f1ff339d6f479dc9', + block: 7680195, + from: '0x903322C7E45A60d7c8C3EA236c5beA9Af86310c7', + contract: '0xbA5BA7B09e2FA1eb0258f647503F81D2Af5cb07d', + datetime: '2022-09-29T11:31:12' + }, + nft: { + address: '0xbA5BA7B09e2FA1eb0258f647503F81D2Af5cb07d', + name: 'Ocean Data NFT', + symbol: 'OCEAN-NFT', + state: 0, + tokenURI: + 'data:application/json;base64,eyJuYW1lIjoiT2NlYW4gRGF0YSBORlQiLCJzeW1ib2wiOiJPQ0VBTi1ORlQiLCJkZXNjcmlwdGlvbiI6IlRoaXMgTkZUIHJlcHJlc2VudHMgYW4gYXNzZXQgaW4gdGhlIE9jZWFuIFByb3RvY29sIHY0IGVjb3N5c3RlbS5cblxuVmlldyBvbiBPY2VhbiBNYXJrZXQ6IGh0dHBzOi8vbWFya2V0Lm9jZWFucHJvdG9jb2wuY29tL2Fzc2V0L2RpZDpvcDo2NjU0YjA3OTM3NjViMjY5Njk2Y2VjOGQyZjBkMDc3ZDliYmNkZDNjNGYwMzNkOTQxYWI5Njg0ZThhZDA2NjMwIiwiZXh0ZXJuYWxfdXJsIjoiaHR0cHM6Ly9tYXJrZXQub2NlYW5wcm90b2NvbC5jb20vYXNzZXQvZGlkOm9wOjY2NTRiMDc5Mzc2NWIyNjk2OTZjZWM4ZDJmMGQwNzdkOWJiY2RkM2M0ZjAzM2Q5NDFhYjk2ODRlOGFkMDY2MzAiLCJiYWNrZ3JvdW5kX2NvbG9yIjoiMTQxNDE0IiwiaW1hZ2VfZGF0YSI6ImRhdGE6aW1hZ2Uvc3ZnK3htbCwlM0Nzdmcgdmlld0JveD0nMCAwIDk5IDk5JyBmaWxsPSd1bmRlZmluZWQnIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyclM0UlM0NwYXRoIGZpbGw9JyUyM2ZmNDA5Mjc3JyBkPSdNMCw5OUwwLDI5QzksMjUgMTksMjIgMjksMjFDMzgsMTkgNDksMTkgNjEsMjFDNzIsMjIgODUsMjUgOTksMjlMOTksOTlaJy8lM0UlM0NwYXRoIGZpbGw9JyUyM2ZmNDA5MmJiJyBkPSdNMCw5OUwwLDU1QzgsNDkgMTcsNDQgMjgsNDNDMzgsNDEgNTAsNDIgNjMsNDNDNzUsNDMgODcsNDIgOTksNDJMOTksOTlaJyUzRSUzQy9wYXRoJTNFJTNDcGF0aCBmaWxsPSclMjNmZjQwOTJmZicgZD0nTTAsOTlMMCw2OEMxMSw2NiAyMiw2NSAzMiw2N0M0MSw2OCA1MCw3MyA2MSw3NkM3MSw3OCA4NSw3OCA5OSw3OUw5OSw5OVonJTNFJTNDL3BhdGglM0UlM0Mvc3ZnJTNFIn0=', + owner: '0x99840Df5Cb42faBE0Feb8811Aaa4BC99cA6C84e0', + created: '2022-09-29T11:31:12' + }, + datatokens: [ + { + address: '0x067e1E6ec580F3F0f6781679A4A5AB07A6464b08', + name: 'Stupendous Orca Token', + symbol: 'STUORC-59', + serviceId: + 'dbc42f4c62d2452f8731fd023eacfae74e9c7a42fbd12ce84310f13342e4aab1' + } + ], + stats: { + orders: 22, + price: { + value: 3231343254, + tokenAddress: '0xCfDdA22C9837aE76E0faA845354f33C62E03653a', + tokenSymbol: 'OCEAN' + } + }, + purgatory: { + state: false, + reason: '' + } +} diff --git a/.jest/__fixtures__/assetAquarius.ts b/.jest/__fixtures__/datasetAquarius.ts similarity index 94% rename from .jest/__fixtures__/assetAquarius.ts rename to .jest/__fixtures__/datasetAquarius.ts index ef07db86b..c581c3261 100644 --- a/.jest/__fixtures__/assetAquarius.ts +++ b/.jest/__fixtures__/datasetAquarius.ts @@ -1,6 +1,6 @@ import { Asset } from '@oceanprotocol/lib' -export const assetAquarius: Asset = { +export const datasetAquarius: Asset = { '@context': ['https://w3id.org/did/v1'], id: 'did:op:6654b0793765b269696cec8d2f0d077d9bbcdd3c4f033d941ab9684e8ad06630', nftAddress: '0xbA5BA7B09e2FA1eb0258f647503F81D2Af5cb07d', @@ -12,7 +12,16 @@ export const assetAquarius: Asset = { type: 'dataset', name: 'Testitest', description: 'This is a test.', - tags: [], + tags: [ + 'trading', + 'defi', + 'algorithm', + 'algorithmic-crypto-trading', + 'algo-trading', + 'trading-strategy', + 'cryptocurrency', + 'crypto' + ], author: 'Test User', license: 'https://market.oceanprotocol.com/terms', additionalInformation: { diff --git a/.jest/__fixtures__/assetWithAccessDetails.ts b/.jest/__fixtures__/datasetWithAccessDetails.ts similarity index 89% rename from .jest/__fixtures__/assetWithAccessDetails.ts rename to .jest/__fixtures__/datasetWithAccessDetails.ts index 4a1751ddb..af527ba5d 100644 --- a/.jest/__fixtures__/assetWithAccessDetails.ts +++ b/.jest/__fixtures__/datasetWithAccessDetails.ts @@ -1,7 +1,7 @@ -import { assetAquarius } from './assetAquarius' +import { datasetAquarius } from './datasetAquarius' export const asset: AssetExtended = { - ...assetAquarius, + ...datasetAquarius, accessDetails: { templateId: 1, publisherMarketOrderFee: '0', diff --git a/.jest/__fixtures__/assetsWithAccessDetails.ts b/.jest/__fixtures__/datasetsWithAccessDetails.ts similarity index 99% rename from .jest/__fixtures__/assetsWithAccessDetails.ts rename to .jest/__fixtures__/datasetsWithAccessDetails.ts index 18c726fc5..1891734e7 100644 --- a/.jest/__fixtures__/assetsWithAccessDetails.ts +++ b/.jest/__fixtures__/datasetsWithAccessDetails.ts @@ -1574,4 +1574,4 @@ export const assets: AssetExtended[] = [ validOrderTx: null } } -] \ No newline at end of file +] diff --git a/.jest/__fixtures__/userPreferences.ts b/.jest/__fixtures__/userPreferences.ts index 4c7d251e2..0c104adaa 100644 --- a/.jest/__fixtures__/userPreferences.ts +++ b/.jest/__fixtures__/userPreferences.ts @@ -5,6 +5,5 @@ export default { chainIds: [5, 1, 137, 56, 1285, 246], bookmarks: [], privacyPolicySlug: '/privacy/en', - showPPC: true, - infiniteApproval: false + showPPC: true } diff --git a/.jest/__mocks__/@utils/accessDetailsAndPricing.ts b/.jest/__mocks__/@utils/accessDetailsAndPricing.ts index 57faaf2cd..7a162fc69 100644 --- a/.jest/__mocks__/@utils/accessDetailsAndPricing.ts +++ b/.jest/__mocks__/@utils/accessDetailsAndPricing.ts @@ -1,3 +1,3 @@ -import { assets } from '../../__fixtures__/assetsWithAccessDetails' +import { assets } from '../../__fixtures__/datasetsWithAccessDetails' export const getAccessDetailsForAssets = jest.fn().mockResolvedValue(assets) diff --git a/.jest/__mocks__/hooksMocks.ts b/.jest/__mocks__/hooksMocks.ts index bf8d5c09c..6646a7335 100644 --- a/.jest/__mocks__/hooksMocks.ts +++ b/.jest/__mocks__/hooksMocks.ts @@ -1,7 +1,7 @@ import marketMetadata from '../__fixtures__/marketMetadata' import userPreferences from '../__fixtures__/userPreferences' import web3 from '../__fixtures__/web3' -import { asset } from '../__fixtures__/assetWithAccessDetails' +import { asset } from '../__fixtures__/datasetWithAccessDetails' jest.mock('../../src/@context/MarketMetadata', () => ({ useMarketMetadata: () => marketMetadata diff --git a/content/pages/editMetadata.json b/content/pages/editMetadata.json index e071852e7..f58ada87c 100644 --- a/content/pages/editMetadata.json +++ b/content/pages/editMetadata.json @@ -30,44 +30,47 @@ { "name": "files", "label": "File", - "prominentHelp": false, + "prominentHelp": false, "type": "tabs", - "fields": [{ - "value": "ipfs", - "title": "IPFS", - "label": "CID", - "placeholder": "e.g. bafkreidgvpkjawlxz6sffxzwgooowe5yt7i6wsyg236mfoks77nywkptdq", - "help": "This CID will be stored encrypted after publishing.", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": true - }, - { - "value": "arweave", - "title": "Arweave", - "label": "Transaction ID", - "placeholder": "e.g. DBRCL94j3QqdPaUtt4VWRen8rZfJZBb7Ey40iMpXfhtd", - "help": "This Transaction ID will be stored encrypted after publishing.", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": true - }, - { - "value": "url", - "title": "URL", - "label": "File", - "placeholder": "e.g. https://file.com/file.json", - "help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.**", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": true - }], + "fields": [ + { + "value": "ipfs", + "title": "IPFS", + "label": "CID", + "placeholder": "e.g. bafkreidgvpkjawlxz6sffxzwgooowe5yt7i6wsyg236mfoks77nywkptdq", + "help": "This CID will be stored encrypted after publishing.", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": true + }, + { + "value": "arweave", + "title": "Arweave", + "label": "Transaction ID", + "placeholder": "e.g. DBRCL94j3QqdPaUtt4VWRen8rZfJZBb7Ey40iMpXfhtd", + "help": "This Transaction ID will be stored encrypted after publishing.", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": true + }, + { + "value": "url", + "title": "URL", + "label": "File", + "placeholder": "e.g. https://file.com/file.json", + "help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.**", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": true + } + ], "sortOptions": false, "required": true - },{ + }, + { "name": "links", "label": "Sample file", "prominentHelp": false, @@ -83,7 +86,8 @@ "prominentHelp": true, "type": "files", "required": false - }], + } + ], "required": false }, diff --git a/content/price.json b/content/price.json index 91778c8bd..1c741b62c 100644 --- a/content/price.json +++ b/content/price.json @@ -24,8 +24,7 @@ }, "approval": { "tooltips": { - "approveSpecific": "Give the smart contract permission to spend your COIN which has to be done for each transaction. You can optionally set this to infinite in your user preferences.", - "approveInfinite": "Give the smart contract permission to spend infinte amounts of your COIN so you have to do this only once. You can disable allowing infinite amounts in your user preferences." + "approveSpecific": "Give the smart contract permission to spend your COIN which has to be done for each transaction. You can optionally set this to infinite in your user preferences." } } } diff --git a/content/publish/form.json b/content/publish/form.json index afd1c0849..463ef8e16 100644 --- a/content/publish/form.json +++ b/content/publish/form.json @@ -104,60 +104,64 @@ { "name": "files", "label": "File", - "prominentHelp": false, + "prominentHelp": false, "type": "tabs", - "fields": [{ - "value": "ipfs", - "title": "IPFS", - "label": "CID", - "placeholder": "e.g. bafkreidgvpkjawlxz6sffxzwgooowe5yt7i6wsyg236mfoks77nywkptdq", - "help": "This CID will be stored encrypted after publishing.", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": true - }, - { - "value": "arweave", - "title": "Arweave", - "label": "Transaction ID", - "placeholder": "e.g. DBRCL94j3QqdPaUtt4VWRen8rZfJZBb7Ey40iMpXfhtd", - "help": "This Transaction ID will be stored encrypted after publishing.", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": true - }, - { - "value": "url", - "title": "URL", - "label": "File", - "placeholder": "e.g. https://file.com/file.json", - "help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.**", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": true - }], + "fields": [ + { + "value": "ipfs", + "title": "IPFS", + "label": "CID", + "placeholder": "e.g. bafkreidgvpkjawlxz6sffxzwgooowe5yt7i6wsyg236mfoks77nywkptdq", + "help": "This CID will be stored encrypted after publishing.", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": true + }, + { + "value": "arweave", + "title": "Arweave", + "label": "Transaction ID", + "placeholder": "e.g. DBRCL94j3QqdPaUtt4VWRen8rZfJZBb7Ey40iMpXfhtd", + "help": "This Transaction ID will be stored encrypted after publishing.", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": true + }, + { + "value": "url", + "title": "URL", + "label": "File", + "placeholder": "e.g. https://file.com/file.json", + "help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.**", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": true + } + ], "sortOptions": false, "required": true - },{ + }, + { "name": "links", "label": "Sample file", "prominentHelp": false, "type": "tabs", "fields": [ { - "value": "url", - "title": "URL", - "label": "File", - "placeholder": "e.g. https://file.com/file.json", - "help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.**", - "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", - "prominentHelp": true, - "type": "files", - "required": false - }], + "value": "url", + "title": "URL", + "label": "File", + "placeholder": "e.g. https://file.com/file.json", + "help": "This URL will be stored encrypted after publishing. **Please make sure that the endpoint is accessible over the internet and is not protected by a firewall or by credentials.**", + "computeHelp": "For a compute dataset, your file should match the file type required by the algorithm, and should not exceed 1 GB in file size. ", + "prominentHelp": true, + "type": "files", + "required": false + } + ], "required": false }, { diff --git a/package-lock.json b/package-lock.json index 4a0d017bf..c68c4a145 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@coingecko/cryptoformat": "^0.5.4", "@loadable/component": "^5.15.2", "@oceanprotocol/art": "^3.2.0", - "@oceanprotocol/lib": "^2.5.2", + "@oceanprotocol/lib": "^2.6.0", "@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/use-dark-mode": "^2.4.3", "@tippyjs/react": "^4.2.6", @@ -4591,18 +4591,18 @@ "integrity": "sha512-I6xoADZpP/8EyN3VWZ+dLYv24DbJj3xzmSDcYv0FolXeAUF3FluzminL5AgQtAaoyUtlHl1D3ij1B++KupWcQQ==" }, "node_modules/@oceanprotocol/lib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-2.5.2.tgz", - "integrity": "sha512-hLNTS6go1GhpSJt7un1VPb/6XNNYSwGpYPX/O1E5q2XCRWjaWYodzqwxBcgQKw2ihSQmaH9JsDsFLZiIKqKRLA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-2.6.0.tgz", + "integrity": "sha512-UMWOdJksJO43wzsmyidOjTyGtARw9OKGde6xbunNuRJDLmeYui4OZ0KTwA5yWBSibsqWk4TVAJgXrxW096NJ5g==", "dependencies": { "@oceanprotocol/contracts": "^1.1.8", "bignumber.js": "^9.1.0", "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", "decimal.js": "^10.4.1", - "web3": "^1.8.0", - "web3-core": "^1.8.0", - "web3-eth-contract": "^1.8.0" + "web3": "^1.8.1", + "web3-core": "^1.8.1", + "web3-eth-contract": "^1.8.1" }, "peerDependencies": { "web3": "^1.8.0" @@ -50186,18 +50186,17 @@ "integrity": "sha512-I6xoADZpP/8EyN3VWZ+dLYv24DbJj3xzmSDcYv0FolXeAUF3FluzminL5AgQtAaoyUtlHl1D3ij1B++KupWcQQ==" }, "@oceanprotocol/lib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-2.5.2.tgz", - "integrity": "sha512-hLNTS6go1GhpSJt7un1VPb/6XNNYSwGpYPX/O1E5q2XCRWjaWYodzqwxBcgQKw2ihSQmaH9JsDsFLZiIKqKRLA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-2.6.0.tgz", + "integrity": "sha512-UMWOdJksJO43wzsmyidOjTyGtARw9OKGde6xbunNuRJDLmeYui4OZ0KTwA5yWBSibsqWk4TVAJgXrxW096NJ5g==", "requires": { "@oceanprotocol/contracts": "^1.1.8", "bignumber.js": "^9.1.0", "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", "decimal.js": "^10.4.1", - "web3": "^1.8.0", - "web3-core": "^1.8.0", - "web3-eth-contract": "^1.8.0" + "web3-core": "^1.8.1", + "web3-eth-contract": "^1.8.1" } }, "@oceanprotocol/typographies": { @@ -50256,7 +50255,6 @@ "integrity": "sha512-rmVKYEsKzurfRU0xJz+iHelbi1LGlihIWZ7Qvmb/CBz1EkhL7nOkW4SVXmG2dA5Ce0si2gr88i6q4eBOMRNJ1w==", "dev": true, "requires": { - "@oclif/config": "^1.18.2", "@oclif/errors": "^1.3.5", "@oclif/help": "^1.0.1", "@oclif/parser": "^3.8.6", @@ -61274,7 +61272,7 @@ "git-url-parse": "11.6.0", "glob": "8.0.1", "global-agent": "3.0.0", - "graphql": "15.8.0", + "graphql": "14.0.2 - 14.2.0 || ^14.3.1 || ^15.0.0", "graphql-tag": "2.12.6", "listr": "0.14.3", "lodash.identity": "3.0.0", @@ -61515,7 +61513,7 @@ "cosmiconfig": "^7.0.1", "dotenv": "^16.0.0", "glob": "^8.0.0", - "graphql": "15.8.0", + "graphql": "14.0.2 - 14.2.0 || ^14.3.1 || ^15.0.0", "graphql-tag": "^2.10.1", "lodash.debounce": "^4.0.8", "lodash.merge": "^4.6.1", @@ -74394,7 +74392,6 @@ "integrity": "sha512-uJx9y/1NIqoYTp6ZW1osJ7U5ZrXGAJbOQ/Qzl05BdGYvN1S7Qmbzid6xOirgK0EIT0pJKEEh1s8qbassYZe4cw==", "peer": true, "requires": { - "@babel/core": "^7.14.0", "@babel/plugin-proposal-async-generator-functions": "^7.0.0", "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-export-default-from": "^7.0.0", @@ -74449,7 +74446,6 @@ "integrity": "sha512-Ogst/M6ujYrl/+9mpEWqE3zF7l2mTuftDTy3L8wZYwX1pWUQWQpfU1aJBeWiLxt1XlIq+uriRjKzKoRoIK57EA==", "peer": true, "requires": { - "@babel/core": "^7.14.0", "babel-preset-fbjs": "^3.4.0", "hermes-parser": "0.8.0", "metro-babel-transformer": "0.72.3", diff --git a/package.json b/package.json index 2b48676ad..8d52e0ae6 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@coingecko/cryptoformat": "^0.5.4", "@loadable/component": "^5.15.2", "@oceanprotocol/art": "^3.2.0", - "@oceanprotocol/lib": "^2.5.2", + "@oceanprotocol/lib": "^2.6.0", "@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/use-dark-mode": "^2.4.3", "@tippyjs/react": "^4.2.6", diff --git a/src/@context/UserPreferences.tsx b/src/@context/UserPreferences.tsx index 20416cf4b..c55c56f66 100644 --- a/src/@context/UserPreferences.tsx +++ b/src/@context/UserPreferences.tsx @@ -24,8 +24,6 @@ interface UserPreferencesValue { removeBookmark: (did: string) => void setPrivacyPolicySlug: (slug: string) => void setShowPPC: (value: boolean) => void - infiniteApproval: boolean - setInfiniteApproval: (value: boolean) => void locale: string } @@ -73,10 +71,6 @@ function UserPreferencesProvider({ localStorage?.showPPC !== false ) - const [infiniteApproval, setInfiniteApproval] = useState( - localStorage?.infiniteApproval || false - ) - // Write values to localStorage on change useEffect(() => { setLocalStorage({ @@ -85,18 +79,9 @@ function UserPreferencesProvider({ currency, bookmarks, privacyPolicySlug, - showPPC, - infiniteApproval + showPPC }) - }, [ - chainIds, - debug, - currency, - bookmarks, - privacyPolicySlug, - showPPC, - infiniteApproval - ]) + }, [chainIds, debug, currency, bookmarks, privacyPolicySlug, showPPC]) // Set ocean.js log levels, default: Error useEffect(() => { @@ -152,8 +137,6 @@ function UserPreferencesProvider({ bookmarks, privacyPolicySlug, showPPC, - infiniteApproval, - setInfiniteApproval, setChainIds, setDebug, setCurrency, diff --git a/src/@hooks/useNetworkMetadata/utils.ts b/src/@hooks/useNetworkMetadata/utils.ts index c9f894e42..75de53a53 100644 --- a/src/@hooks/useNetworkMetadata/utils.ts +++ b/src/@hooks/useNetworkMetadata/utils.ts @@ -22,6 +22,7 @@ export function getNetworkType(network: EthereumListsChain): string { export function getNetworkDisplayName(data: EthereumListsChain): string { let displayName + if (!data) return 'Unknown' switch (data.chainId) { case 137: diff --git a/src/@utils/url/index.test.ts b/src/@utils/url/index.test.ts index 22f2af86a..a8e6d7bcd 100644 --- a/src/@utils/url/index.test.ts +++ b/src/@utils/url/index.test.ts @@ -1,4 +1,4 @@ -import { sanitizeUrl } from '.' +import { sanitizeUrl, isGoogleUrl } from '.' describe('@utils/url', () => { test('sanitizeUrl', () => { @@ -7,3 +7,20 @@ describe('@utils/url', () => { expect(sanitizeUrl('ftp://example.com')).toBe('about:blank') }) }) + +describe('isGoogleUrl', () => { + it('should return true if the url is a google domain', () => { + expect(isGoogleUrl('https://google.com')).toBe(true) + expect(isGoogleUrl('https://drive.google.com')).toBe(true) + expect(isGoogleUrl('https://docs.google.com')).toBe(true) + expect(isGoogleUrl('https://sheets.google.com')).toBe(true) + expect(isGoogleUrl('https://meet.google.com')).toBe(true) + expect(isGoogleUrl('https://calendar.google.com')).toBe(true) + }) + it('should return false if the url is not a google domain', () => { + expect(isGoogleUrl('https://google.test.com')).toBe(false) + expect(isGoogleUrl('https://drive.gloogle.com')).toBe(false) + expect(isGoogleUrl('https://drive.google.test.com')).toBe(false) + expect(isGoogleUrl('https://google.com.test.com')).toBe(false) + }) +}) diff --git a/src/@utils/url/index.ts b/src/@utils/url/index.ts index 0ef9ea781..1c58f881b 100644 --- a/src/@utils/url/index.ts +++ b/src/@utils/url/index.ts @@ -3,3 +3,10 @@ export function sanitizeUrl(url: string) { const isAllowedUrlScheme = u.startsWith('http://') || u.startsWith('https://') return isAllowedUrlScheme ? url : 'about:blank' } + +// check if the url is a google domain +export const isGoogleUrl = (url: string): boolean => { + if (!url) return + const googleUrl = new URL(url) + return googleUrl.hostname.endsWith('google.com') +} diff --git a/src/@utils/yup.ts b/src/@utils/yup.ts index 1e0f7f994..6848e235a 100644 --- a/src/@utils/yup.ts +++ b/src/@utils/yup.ts @@ -1,6 +1,7 @@ import { isCID } from '@utils/ipfs' import isUrl from 'is-url-superb' import * as Yup from 'yup' +import { isGoogleUrl } from './url/index' export function testLinks(isEdit?: boolean) { return Yup.string().test((value, context) => { @@ -28,7 +29,7 @@ export function testLinks(isEdit?: boolean) { validField = true } // if the url has google drive, we need to block the user from submit - if (value?.toString().includes('drive.google')) { + if (isGoogleUrl(value?.toString())) { validField = false errorMessage = 'Google Drive is not a supported hosting service. Please use an alternative.' diff --git a/src/components/@shared/AssetList/index.stories.tsx b/src/components/@shared/AssetList/index.stories.tsx index aeba2ac98..c11cff5b3 100644 --- a/src/components/@shared/AssetList/index.stories.tsx +++ b/src/components/@shared/AssetList/index.stories.tsx @@ -3,7 +3,7 @@ import { ComponentStory, ComponentMeta } from '@storybook/react' import MarketMetadataProvider from '@context/MarketMetadata' import { UserPreferencesProvider } from '@context/UserPreferences' import AssetList, { AssetListProps } from '.' -import { assets } from '../../../../.jest/__fixtures__/assetsWithAccessDetails' +import { assets } from '../../../../.jest/__fixtures__/datasetsWithAccessDetails' export default { title: 'Component/@shared/AssetList', diff --git a/src/components/@shared/AssetList/index.test.tsx b/src/components/@shared/AssetList/index.test.tsx index b7fe4e4b3..cfe498505 100644 --- a/src/components/@shared/AssetList/index.test.tsx +++ b/src/components/@shared/AssetList/index.test.tsx @@ -1,7 +1,7 @@ import { render, screen, fireEvent } from '@testing-library/react' import React from 'react' import AssetList from './index' -import { assetAquarius } from '../../../../.jest/__fixtures__/assetAquarius' +import { datasetAquarius } from '../../../../.jest/__fixtures__/datasetAquarius' describe('@shared/AssetList', () => { it('renders without crashing', async () => { @@ -9,7 +9,7 @@ describe('@shared/AssetList', () => { render( { testRender() diff --git a/src/components/@shared/FileIcon/index.tsx b/src/components/@shared/FileIcon/index.tsx index 562f39a43..84dafea8e 100644 --- a/src/components/@shared/FileIcon/index.tsx +++ b/src/components/@shared/FileIcon/index.tsx @@ -40,6 +40,9 @@ export default function FileIcon({ ? filesize(Number(file.contentLength)).toString() : ''} +
  • + {file.type === 'smartcontract' ? 'smart\ncontract' : file.type} +
  • ) : (
  • No file info available
  • diff --git a/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx b/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx index 6f159280e..5376c37d3 100644 --- a/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx +++ b/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx @@ -6,6 +6,7 @@ import { InputProps } from '@shared/FormInput' import { getFileInfo } from '@utils/provider' import { LoggerInstance } from '@oceanprotocol/lib' import { useAsset } from '@context/Asset' +import { isGoogleUrl } from '@utils/url/index' export default function FilesInput(props: InputProps): ReactElement { const [field, meta, helpers] = useField(props.name) @@ -26,7 +27,7 @@ export default function FilesInput(props: InputProps): ReactElement { setIsLoading(true) // TODO: handled on provider - if (url.includes('drive.google')) { + if (isGoogleUrl(url)) { throw Error( 'Google Drive is not a supported hosting service. Please use an alternative.' ) diff --git a/src/components/@shared/Price/index.test.tsx b/src/components/@shared/Price/index.test.tsx index 86d6328b9..84ff52e78 100644 --- a/src/components/@shared/Price/index.test.tsx +++ b/src/components/@shared/Price/index.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react' import React from 'react' import Price from './index' -import { asset } from '../../../../.jest/__fixtures__/assetWithAccessDetails' +import { asset } from '../../../../.jest/__fixtures__/datasetWithAccessDetails' import prices from '../../../../.jest/__fixtures__/prices' jest.mock('../../../@context/Prices', () => ({ diff --git a/src/components/@shared/atoms/Tooltip/index.tsx b/src/components/@shared/atoms/Tooltip/index.tsx index 7d5e98835..38c12ade2 100644 --- a/src/components/@shared/atoms/Tooltip/index.tsx +++ b/src/components/@shared/atoms/Tooltip/index.tsx @@ -43,7 +43,7 @@ export default function Tooltip(props: TippyProps): ReactElement { { render() const button = screen.getByText('Download') expect(button).toContainHTML(' { @@ -105,6 +110,33 @@ describe('Asset/AssetActions/ButtonBuy', () => { expect(button).toContainHTML(' { + render() + expect( + screen.getByText( + 'To use this algorithm, you will buy 1 dtSymbol and immediately send it back to the publisher. Connect to the correct network to interact with this asset. The C2D resources required to start the job are available, no payment is required for them. Please note that network gas fees still apply, even when using free assets.' + ) + ).toBeInTheDocument() + }) + + it('Renders correct message for free compute asset with free algorithm', () => { + render() + expect( + screen.getByText( + 'This algorithm is free to use. Connect to the correct network to interact with this asset. The C2D resources required to start the job are available, no payment is required for them. Please note that network gas fees still apply, even when using free assets.' + ) + ).toBeInTheDocument() + }) + + it('Renders correct message for free compute asset with free algorithm', () => { + render() + expect( + screen.getByText( + 'To use this algorithm, you will buy 1 dtSymbol and immediately send it back to the publisher. Connect to the correct network to interact with this asset. The C2D resources required to start the job are available, no payment is required for them.' + ) + ).toBeInTheDocument() + }) + it('Renders "Buy Compute Job" button for compute without crashing', () => { render() const button = screen.getByText('Buy Compute Job') diff --git a/src/components/Asset/AssetActions/ButtonBuy/index.tsx b/src/components/Asset/AssetActions/ButtonBuy/index.tsx index 520da859f..50d1b0935 100644 --- a/src/components/Asset/AssetActions/ButtonBuy/index.tsx +++ b/src/components/Asset/AssetActions/ButtonBuy/index.tsx @@ -46,7 +46,8 @@ function getConsumeHelpText( isBalanceSufficient: boolean, consumableFeedback: string, isSupportedOceanNetwork: boolean, - web3: Web3 + web3: Web3, + priceType: string ) { const text = isConsumable === false @@ -57,7 +58,9 @@ function getConsumeHelpText( ? `You own ${dtBalance} ${dtSymbol} allowing you to use this dataset by spending 1 ${dtSymbol}, but without paying ${btSymbol} again.` : isBalanceSufficient === false ? `You do not have enough ${btSymbol} in your wallet to purchase this asset.` - : `For using this ${assetType}, you will buy 1 ${dtSymbol} and immediately spend it back to the publisher.` + : priceType === 'free' + ? `This ${assetType} is free to use.` + : `To use this ${assetType}, you will buy 1 ${dtSymbol} and immediately send it back to the publisher.` return text } @@ -71,7 +74,8 @@ function getAlgoHelpText( hasDatatokenSelectedComputeAsset: boolean, isBalanceSufficient: boolean, isSupportedOceanNetwork: boolean, - web3: Web3 + web3: Web3, + algorithmPriceType: string ) { const text = (!dtSymbolSelectedComputeAsset && !dtBalanceSelectedComputeAsset) || @@ -86,7 +90,9 @@ function getAlgoHelpText( ? `Connect to the correct network to interact with this asset.` : isBalanceSufficient === false ? '' - : `Additionally, you will buy 1 ${dtSymbolSelectedComputeAsset} for the ${selectedComputeAssetType} and spend it back to its publisher and pool.` + : algorithmPriceType === 'free' + ? `Additionally, the selected ${selectedComputeAssetType} is free to use.` + : `Additionally, you will buy 1 ${dtSymbolSelectedComputeAsset} for the ${selectedComputeAssetType} and send it back to the publisher.` return text } @@ -99,6 +105,8 @@ function getComputeAssetHelpText( isConsumable: boolean, consumableFeedback: string, isBalanceSufficient: boolean, + algorithmPriceType: string, + priceType: string, hasPreviousOrderSelectedComputeAsset?: boolean, hasDatatokenSelectedComputeAsset?: boolean, assetType?: string, @@ -121,7 +129,8 @@ function getComputeAssetHelpText( isBalanceSufficient, consumableFeedback, isSupportedOceanNetwork, - web3 + web3, + priceType ) const computeAlgoHelpText = getAlgoHelpText( @@ -134,13 +143,17 @@ function getComputeAssetHelpText( hasDatatokenSelectedComputeAsset, isBalanceSufficient, isSupportedOceanNetwork, - web3 + web3, + algorithmPriceType ) const providerFeeHelpText = hasProviderFee ? 'In order to start the job you also need to pay the fees for renting the c2d resources.' - : 'C2D resources required to start the job are available, no payment required for those fees.' - const computeHelpText = `${computeAssetHelpText} ${computeAlgoHelpText} ${providerFeeHelpText}` + : 'The C2D resources required to start the job are available, no payment is required for them.' + let computeHelpText = `${computeAssetHelpText} ${computeAlgoHelpText} ${providerFeeHelpText}` + + computeHelpText = computeHelpText.replace(/^\s+/, '') + console.log('computeHelpText', computeHelpText) return computeHelpText } @@ -190,6 +203,53 @@ export default function ButtonBuy({ ? 'Order Compute Job' : `Buy Compute Job` + function message(): string { + let message = '' + if (action === 'download') { + message = getConsumeHelpText( + btSymbol, + dtBalance, + dtSymbol, + hasDatatoken, + hasPreviousOrder, + assetType, + isConsumable, + isBalanceSufficient, + consumableFeedback, + isSupportedOceanNetwork, + web3, + priceType + ) + } else { + message = getComputeAssetHelpText( + hasPreviousOrder, + hasDatatoken, + btSymbol, + dtSymbol, + dtBalance, + isConsumable, + consumableFeedback, + isBalanceSufficient, + algorithmPriceType, + priceType, + hasPreviousOrderSelectedComputeAsset, + hasDatatokenSelectedComputeAsset, + assetType, + dtSymbolSelectedComputeAsset, + dtBalanceSelectedComputeAsset, + selectedComputeAssetType, + isAlgorithmConsumable, + isSupportedOceanNetwork, + web3, + hasProviderFee + ) + } + if (priceType === 'free' || algorithmPriceType === 'free') { + message += + ' Please note that network gas fees still apply, even when using free assets.' + } + return message + } return (
    {isLoading ? ( @@ -205,42 +265,7 @@ export default function ButtonBuy({ > {buttonText} -
    - {action === 'download' - ? getConsumeHelpText( - btSymbol, - dtBalance, - dtSymbol, - hasDatatoken, - hasPreviousOrder, - assetType, - isConsumable, - isBalanceSufficient, - consumableFeedback, - isSupportedOceanNetwork, - web3 - ) - : getComputeAssetHelpText( - hasPreviousOrder, - hasDatatoken, - btSymbol, - dtSymbol, - dtBalance, - isConsumable, - consumableFeedback, - isBalanceSufficient, - hasPreviousOrderSelectedComputeAsset, - hasDatatokenSelectedComputeAsset, - assetType, - dtSymbolSelectedComputeAsset, - dtBalanceSelectedComputeAsset, - selectedComputeAssetType, - isAlgorithmConsumable, - isSupportedOceanNetwork, - web3, - hasProviderFee - )} -
    +
    {message()}
    )}
    diff --git a/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx b/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx index b6dd83451..a84e7af13 100644 --- a/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx +++ b/src/components/Asset/AssetActions/Compute/FormComputeDataset.tsx @@ -33,6 +33,7 @@ export default function FormStartCompute({ hasDatatokenSelectedComputeAsset, datasetSymbol, algorithmSymbol, + providerFeesSymbol, dtSymbolSelectedComputeAsset, dtBalanceSelectedComputeAsset, selectedComputeAssetType, @@ -61,6 +62,7 @@ export default function FormStartCompute({ hasDatatokenSelectedComputeAsset?: boolean datasetSymbol?: string algorithmSymbol?: string + providerFeesSymbol?: string dtSymbolSelectedComputeAsset?: string dtBalanceSelectedComputeAsset?: string selectedComputeAssetType?: string @@ -145,7 +147,7 @@ export default function FormStartCompute({ ? new Decimal(providerFeeAmount).toDecimalPlaces(MAX_DECIMALS) : new Decimal(0) - if (algorithmSymbol === 'OCEAN') { + if (algorithmSymbol === providerFeesSymbol) { let sum = providerFees.add(priceAlgo) totalPrices.push({ value: sum.toDecimalPlaces(MAX_DECIMALS).toString(), @@ -161,7 +163,7 @@ export default function FormStartCompute({ }) } } else { - if (datasetSymbol === 'OCEAN') { + if (datasetSymbol === providerFeesSymbol) { const sum = providerFees.add(priceDataset) totalPrices.push({ value: sum.toDecimalPlaces(MAX_DECIMALS).toString(), @@ -179,7 +181,7 @@ export default function FormStartCompute({ }) totalPrices.push({ value: providerFees.toDecimalPlaces(MAX_DECIMALS).toString(), - symbol: 'OCEAN' + symbol: providerFeesSymbol }) } else { totalPrices.push({ @@ -188,7 +190,7 @@ export default function FormStartCompute({ }) totalPrices.push({ value: providerFees.toDecimalPlaces(MAX_DECIMALS).toString(), - symbol: 'OCEAN' + symbol: providerFeesSymbol }) totalPrices.push({ value: priceAlgo.toDecimalPlaces(MAX_DECIMALS).toString(), @@ -211,7 +213,8 @@ export default function FormStartCompute({ datasetOrderPrice, algoOrderPrice, algorithmSymbol, - datasetSymbol + datasetSymbol, + providerFeesSymbol ]) useEffect(() => { @@ -263,6 +266,7 @@ export default function FormStartCompute({ datasetOrderPrice={datasetOrderPrice} algoOrderPrice={algoOrderPrice} providerFeeAmount={providerFeeAmount} + providerFeesSymbol={providerFeesSymbol} validUntil={validUntil} totalPrices={totalPrices} /> diff --git a/src/components/Asset/AssetActions/Compute/PriceOutput.tsx b/src/components/Asset/AssetActions/Compute/PriceOutput.tsx index 39df72837..52069e975 100644 --- a/src/components/Asset/AssetActions/Compute/PriceOutput.tsx +++ b/src/components/Asset/AssetActions/Compute/PriceOutput.tsx @@ -20,6 +20,7 @@ interface PriceOutputProps { datasetOrderPrice?: string algoOrderPrice?: string providerFeeAmount?: string + providerFeesSymbol?: string validUntil?: string totalPrices?: totalPriceMap[] } @@ -84,6 +85,7 @@ export default function PriceOutput({ datasetOrderPrice, algoOrderPrice, providerFeeAmount, + providerFeesSymbol, validUntil, totalPrices }: PriceOutputProps): ReactElement { @@ -134,7 +136,7 @@ export default function PriceOutput({ diff --git a/src/components/Asset/AssetActions/Compute/index.tsx b/src/components/Asset/AssetActions/Compute/index.tsx index 2f3795197..2718bc221 100644 --- a/src/components/Asset/AssetActions/Compute/index.tsx +++ b/src/components/Asset/AssetActions/Compute/index.tsx @@ -12,7 +12,8 @@ import { ComputeAlgorithm, ComputeOutput, ProviderComputeInitializeResults, - unitsToAmount + unitsToAmount, + minAbi } from '@oceanprotocol/lib' import { toast } from 'react-toastify' import Price from '@shared/Price' @@ -61,7 +62,7 @@ export default function Compute({ fileIsLoading?: boolean consumableFeedback?: string }): ReactElement { - const { accountId, web3, isSupportedOceanNetwork } = useWeb3() + const { accountId, web3, isSupportedOceanNetwork, networkId } = useWeb3() const { chainIds } = useUserPreferences() const { isAssetNetwork } = useAsset() @@ -90,6 +91,7 @@ export default function Compute({ const [initializedProviderResponse, setInitializedProviderResponse] = useState() const [providerFeeAmount, setProviderFeeAmount] = useState('0') + const [providerFeesSymbol, setProviderFeesSymbol] = useState('OCEAN') const [computeValidUntil, setComputeValidUntil] = useState('0') const [datasetOrderPriceAndFees, setDatasetOrderPriceAndFees] = useState() @@ -160,6 +162,18 @@ export default function Compute({ setProviderFeeAmount(feeAmount) + const datatoken = new Datatoken( + await getDummyWeb3(asset?.chainId), + null, + null, + minAbi + ) + setProviderFeesSymbol( + await datatoken.getSymbol( + initializedProvider?.datasets?.[0]?.providerFee?.providerFeeToken + ) + ) + const computeDuration = ( parseInt(initializedProvider?.datasets?.[0]?.providerFee?.validUntil) - Math.floor(Date.now() / 1000) @@ -466,11 +480,15 @@ export default function Compute({ assetTimeout={secondsToString(asset?.services[0].timeout)} hasPreviousOrderSelectedComputeAsset={!!validAlgorithmOrderTx} hasDatatokenSelectedComputeAsset={hasAlgoAssetDatatoken} - datasetSymbol={asset?.accessDetails?.baseToken?.symbol || 'OCEAN'} + datasetSymbol={ + asset?.accessDetails?.baseToken?.symbol || + (asset?.chainId === 137 ? 'mOCEAN' : 'OCEAN') + } algorithmSymbol={ selectedAlgorithmAsset?.accessDetails?.baseToken?.symbol || - 'OCEAN' + (selectedAlgorithmAsset?.chainId === 137 ? 'mOCEAN' : 'OCEAN') } + providerFeesSymbol={providerFeesSymbol} dtSymbolSelectedComputeAsset={ selectedAlgorithmAsset?.datatokens[0]?.symbol } diff --git a/src/components/Asset/AssetContent/Bookmark.test.tsx b/src/components/Asset/AssetContent/Bookmark.test.tsx new file mode 100644 index 000000000..adfe7fea8 --- /dev/null +++ b/src/components/Asset/AssetContent/Bookmark.test.tsx @@ -0,0 +1,11 @@ +import { render, screen } from '@testing-library/react' +import React from 'react' +import Bookmark from './Bookmark' +import { datasetAquarius } from '../../../../.jest/__fixtures__/datasetAquarius' + +describe('src/components/Asset/AssetContent/Bookmark.tsx', () => { + it('renders Add Bookmark button', () => { + render() + expect(screen.getByTitle('Add Bookmark')).toBeInTheDocument() + }) +}) diff --git a/src/components/Asset/AssetContent/MetaFull.test.tsx b/src/components/Asset/AssetContent/MetaFull.test.tsx new file mode 100644 index 000000000..56053d369 --- /dev/null +++ b/src/components/Asset/AssetContent/MetaFull.test.tsx @@ -0,0 +1,17 @@ +import { render, screen } from '@testing-library/react' +import React from 'react' +import MetaFull from './MetaFull' +import { datasetAquarius } from '../../../../.jest/__fixtures__/datasetAquarius' +import { algorithmAquarius } from '../../../../.jest/__fixtures__/algorithmAquarius' + +describe('src/components/Asset/AssetContent/MetaFull.tsx', () => { + it('renders metadata', () => { + render() + expect(screen.getByText('Owner')).toBeInTheDocument() + }) + + it('renders metadata for an algorithm', () => { + render() + expect(screen.getByText('Docker Image')).toBeInTheDocument() + }) +}) diff --git a/src/components/Asset/AssetContent/MetaFull.tsx b/src/components/Asset/AssetContent/MetaFull.tsx index f01d71915..1e6f2ba1c 100644 --- a/src/components/Asset/AssetContent/MetaFull.tsx +++ b/src/components/Asset/AssetContent/MetaFull.tsx @@ -3,17 +3,20 @@ import MetaItem from './MetaItem' import styles from './MetaFull.module.css' import Publisher from '@shared/Publisher' import { useAsset } from '@context/Asset' -import { useWeb3 } from '@context/Web3' +// import { useWeb3 } from '@context/Web3' +import { getDummyWeb3 } from '@utils/web3' import { Asset, Datatoken, LoggerInstance } from '@oceanprotocol/lib' export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement { const [paymentCollector, setPaymentCollector] = useState() const { isInPurgatory } = useAsset() - const { web3 } = useWeb3() + // const { web3 } = useWeb3() useEffect(() => { async function getInitialPaymentCollector() { try { + if (!ddo) return + const web3 = await getDummyWeb3(ddo.chainId) const datatoken = new Datatoken(web3) setPaymentCollector( await datatoken.getPaymentCollector(ddo.datatokens[0].address) @@ -23,7 +26,7 @@ export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement { } } getInitialPaymentCollector() - }, [ddo, web3]) + }, [ddo]) function DockerImage() { const containerInfo = ddo?.metadata?.algorithm?.container diff --git a/src/components/Asset/AssetContent/MetaSecondary.test.tsx b/src/components/Asset/AssetContent/MetaSecondary.test.tsx new file mode 100644 index 000000000..5c39f10e0 --- /dev/null +++ b/src/components/Asset/AssetContent/MetaSecondary.test.tsx @@ -0,0 +1,18 @@ +import { render, screen } from '@testing-library/react' +import React from 'react' +import MetaSecondary from './MetaSecondary' +import { datasetAquarius } from '../../../../.jest/__fixtures__/datasetAquarius' +import { algorithmAquarius } from '../../../../.jest/__fixtures__/algorithmAquarius' + +describe('src/components/Asset/AssetContent/MetaSecondary.tsx', () => { + it('renders tags', () => { + render() + expect( + screen.getByText(datasetAquarius.metadata.tags[0]) + ).toBeInTheDocument() + }) + it('renders download sample button', () => { + render() + expect(screen.getByText('Sample Data')).toBeInTheDocument() + }) +}) diff --git a/src/components/Asset/Edit/EditMetadata.tsx b/src/components/Asset/Edit/EditMetadata.tsx index d7de68248..539ad1804 100644 --- a/src/components/Asset/Edit/EditMetadata.tsx +++ b/src/components/Asset/Edit/EditMetadata.tsx @@ -179,7 +179,7 @@ export default function Edit({ initialValues={getInitialValues( asset?.metadata, asset?.services[0]?.timeout, - asset?.accessDetails?.price, + asset?.accessDetails?.price || '0', paymentCollector )} validationSchema={validationSchema} diff --git a/src/components/Asset/Edit/FormEditMetadata.tsx b/src/components/Asset/Edit/FormEditMetadata.tsx index 7d9b84130..191629b46 100644 --- a/src/components/Asset/Edit/FormEditMetadata.tsx +++ b/src/components/Asset/Edit/FormEditMetadata.tsx @@ -6,6 +6,7 @@ import { useAsset } from '@context/Asset' import { FormPublishData } from '@components/Publish/_types' import { getFileInfo } from '@utils/provider' import { getFieldContent } from '@utils/form' +import { isGoogleUrl } from '@utils/url' export function checkIfTimeoutInPredefinedValues( timeout: string, @@ -65,7 +66,7 @@ export default function FormEditMetadata({ getFileInfo(asset.metadata.links[0], providerUrl, 'url').then( (checkedFile) => { // set valid false if url is using google drive - if (asset.metadata.links[0].includes('drive.google')) { + if (isGoogleUrl(asset.metadata.links[0])) { setFieldValue('links', [ { url: asset.metadata.links[0], diff --git a/src/components/Asset/RelatedAssets/index.test.tsx b/src/components/Asset/RelatedAssets/index.test.tsx index 3b2ff15b6..ec5d5feb7 100644 --- a/src/components/Asset/RelatedAssets/index.test.tsx +++ b/src/components/Asset/RelatedAssets/index.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/react' import React from 'react' import RelatedAssets from '.' -import { assets } from '../../../../.jest/__fixtures__/assetsWithAccessDetails' +import { assets } from '../../../../.jest/__fixtures__/datasetsWithAccessDetails' import { queryMetadata } from '../../../@utils/aquarius' // import * as userPreferencesMock from '../../../@context/UserPreferences' diff --git a/src/components/Header/UserPreferences/TokenApproval.tsx b/src/components/Header/UserPreferences/TokenApproval.tsx deleted file mode 100644 index e0c49ae0c..000000000 --- a/src/components/Header/UserPreferences/TokenApproval.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React, { ReactElement } from 'react' -import { useUserPreferences } from '@context/UserPreferences' -import Input from '@shared/FormInput' - -export default function TokenApproval(): ReactElement { - const { infiniteApproval, setInfiniteApproval } = useUserPreferences() - - return ( -
  • - setInfiniteApproval(!infiniteApproval)} - /> -
  • - ) -} diff --git a/src/components/Header/UserPreferences/index.tsx b/src/components/Header/UserPreferences/index.tsx index 0e3d397ad..dac4dc9a3 100644 --- a/src/components/Header/UserPreferences/index.tsx +++ b/src/components/Header/UserPreferences/index.tsx @@ -7,7 +7,6 @@ import Debug from './Debug' import Caret from '@images/caret.svg' import useDarkMode from '@oceanprotocol/use-dark-mode' import Appearance from './Appearance' -import TokenApproval from './TokenApproval' import { useMarketMetadata } from '@context/MarketMetadata' export default function UserPreferences(): ReactElement { @@ -20,7 +19,6 @@ export default function UserPreferences(): ReactElement { content={
      -
    diff --git a/src/components/Home/MostViews/index.test.tsx b/src/components/Home/MostViews/index.test.tsx index dbdb91cb8..87efe5bcc 100644 --- a/src/components/Home/MostViews/index.test.tsx +++ b/src/components/Home/MostViews/index.test.tsx @@ -3,7 +3,7 @@ import React from 'react' import MostViews from '.' import axios from 'axios' import { queryMetadata } from '@utils/aquarius' -import { assetAquarius } from '../../../../.jest/__fixtures__/assetAquarius' +import { datasetAquarius } from '../../../../.jest/__fixtures__/datasetAquarius' jest.mock('axios') jest.mock('@utils/aquarius') @@ -12,7 +12,7 @@ const axiosMock = axios as jest.Mocked const queryMetadataMock = queryMetadata as jest.Mock const queryMetadataBaseReturn: PagedAssets = { - results: [assetAquarius], + results: [datasetAquarius], page: 1, totalPages: 1, totalResults: 1, @@ -27,7 +27,7 @@ describe('components/Home/MostViews', () => { it('renders without crashing', async () => { axiosMock.get.mockImplementation(() => Promise.resolve({ - data: [{ count: 666, did: assetAquarius.id }] + data: [{ count: 666, did: datasetAquarius.id }] }) ) queryMetadataMock.mockResolvedValue(queryMetadataBaseReturn) diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 61bce6884..684f4a8d3 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -14,25 +14,9 @@ export default function Page404(): ReactElement { <>