diff --git a/content/pages/editMetadata.json b/content/pages/editMetadata.json index f58ada87c..ff17820ca 100644 --- a/content/pages/editMetadata.json +++ b/content/pages/editMetadata.json @@ -120,6 +120,20 @@ "placeholder": "e.g. 0X123ABC...", "help": "This address will receive the revenue from all sales. More info available in our [docs](https://docs.oceanprotocol.com/core-concepts/datanft-and-datatoken#revenue).", "required": false + }, + { + "name": "assetState", + "label": "Asset Status", + "help": "This asset will no longer be visible to other users and it won't be possible to purchase it. More info available in our [docs](https://docs.oceanprotocol.com/core-concepts/did-ddo#state).", + "type": "select", + "options": [ + "Active", + "Revoked by publisher", + "Ordering is temporary disabled", + "Asset unlisted" + ], + "sortOptions": false, + "required": false } ] } diff --git a/package-lock.json b/package-lock.json index c68c4a145..2c799da2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,7 +70,7 @@ "@types/loadable__component": "^5.13.4", "@types/node": "^18.8.5", "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.9", + "@types/react-dom": "^18.0.10", "@types/react-modal": "^3.13.1", "@types/react-paginate": "^7.1.1", "@types/remove-markdown": "^0.3.1", @@ -85,12 +85,12 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.31.11", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-testing-library": "^5.9.1", + "eslint-plugin-testing-library": "^5.10.0", "https-browserify": "^1.0.0", "husky": "^8.0.2", "jest": "^29.3.1", "jest-environment-jsdom": "^29.3.1", - "prettier": "^2.8.1", + "prettier": "^2.8.3", "pretty-quick": "^3.1.3", "process": "^0.11.10", "serve": "^14.1.2", @@ -17265,9 +17265,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.0.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.9.tgz", - "integrity": "sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg==", + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", + "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", "dev": true, "dependencies": { "@types/react": "*" @@ -22559,9 +22559,9 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, "node_modules/copy-concurrently": { "version": "1.0.5", @@ -25105,12 +25105,12 @@ } }, "node_modules/eslint-plugin-testing-library": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.9.1.tgz", - "integrity": "sha512-6BQp3tmb79jLLasPHJmy8DnxREe+2Pgf7L+7o09TSWPfdqqtQfRZmZNetr5mOs3yqZk/MRNxpN3RUpJe0wB4LQ==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.0.tgz", + "integrity": "sha512-aTOsCAEI9trrX3TLOnsskfhe57DmsjP/yMKLPqg4ftdRvfR4qut2PGWUa8TwP7whZbwMzJjh98tgAPcE8vdHow==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "^5.13.0" + "@typescript-eslint/utils": "^5.43.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0", @@ -38418,9 +38418,9 @@ } }, "node_modules/prettier": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", - "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -50195,6 +50195,7 @@ "cross-fetch": "^3.1.5", "crypto-js": "^4.1.1", "decimal.js": "^10.4.1", + "web3": "^1.8.1", "web3-core": "^1.8.1", "web3-eth-contract": "^1.8.1" } @@ -50255,6 +50256,7 @@ "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", @@ -60045,9 +60047,9 @@ } }, "@types/react-dom": { - "version": "18.0.9", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.9.tgz", - "integrity": "sha512-qnVvHxASt/H7i+XG1U1xMiY5t+IHcPGUK7TDMDzom08xa7e86eCeKOiLZezwCKVxJn6NEiiy2ekgX8aQssjIKg==", + "version": "18.0.10", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.10.tgz", + "integrity": "sha512-E42GW/JA4Qv15wQdqJq8DL4JhNpB3prJgjgapN3qJT9K2zO5IIAQh4VXvCEDupoqAwnz0cY4RlXeC/ajX5SFHg==", "dev": true, "requires": { "@types/react": "*" @@ -61272,7 +61274,7 @@ "git-url-parse": "11.6.0", "glob": "8.0.1", "global-agent": "3.0.0", - "graphql": "14.0.2 - 14.2.0 || ^14.3.1 || ^15.0.0", + "graphql": "15.8.0", "graphql-tag": "2.12.6", "listr": "0.14.3", "lodash.identity": "3.0.0", @@ -61513,7 +61515,7 @@ "cosmiconfig": "^7.0.1", "dotenv": "^16.0.0", "glob": "^8.0.0", - "graphql": "14.0.2 - 14.2.0 || ^14.3.1 || ^15.0.0", + "graphql": "15.8.0", "graphql-tag": "^2.10.1", "lodash.debounce": "^4.0.8", "lodash.merge": "^4.6.1", @@ -64318,9 +64320,9 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "cookiejar": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", - "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==" }, "copy-concurrently": { "version": "1.0.5", @@ -66384,12 +66386,12 @@ } }, "eslint-plugin-testing-library": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.9.1.tgz", - "integrity": "sha512-6BQp3tmb79jLLasPHJmy8DnxREe+2Pgf7L+7o09TSWPfdqqtQfRZmZNetr5mOs3yqZk/MRNxpN3RUpJe0wB4LQ==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.10.0.tgz", + "integrity": "sha512-aTOsCAEI9trrX3TLOnsskfhe57DmsjP/yMKLPqg4ftdRvfR4qut2PGWUa8TwP7whZbwMzJjh98tgAPcE8vdHow==", "dev": true, "requires": { - "@typescript-eslint/utils": "^5.13.0" + "@typescript-eslint/utils": "^5.43.0" } }, "eslint-scope": { @@ -74392,6 +74394,7 @@ "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", @@ -74446,6 +74449,7 @@ "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", @@ -76714,9 +76718,9 @@ "dev": true }, "prettier": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.1.tgz", - "integrity": "sha512-lqGoSJBQNJidqCHE80vqZJHWHRFoNYsSpP9AjFhlhi9ODCJA541svILes/+/1GM3VaL/abZi7cpFzOpdR9UPKg==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", + "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "dev": true }, "prettier-linter-helpers": { diff --git a/package.json b/package.json index 8d52e0ae6..75219bcf3 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "@types/loadable__component": "^5.13.4", "@types/node": "^18.8.5", "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.9", + "@types/react-dom": "^18.0.10", "@types/react-modal": "^3.13.1", "@types/react-paginate": "^7.1.1", "@types/remove-markdown": "^0.3.1", @@ -98,12 +98,12 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.31.11", "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-testing-library": "^5.9.1", + "eslint-plugin-testing-library": "^5.10.0", "https-browserify": "^1.0.0", "husky": "^8.0.2", "jest": "^29.3.1", "jest-environment-jsdom": "^29.3.1", - "prettier": "^2.8.1", + "prettier": "^2.8.3", "pretty-quick": "^3.1.3", "process": "^0.11.10", "serve": "^14.1.2", diff --git a/src/@context/Asset.tsx b/src/@context/Asset.tsx index 5c1b75367..d1ad226ec 100644 --- a/src/@context/Asset.tsx +++ b/src/@context/Asset.tsx @@ -16,6 +16,7 @@ import { getOceanConfig, getDevelopmentConfig } from '@utils/ocean' import { getAccessDetails } from '@utils/accessDetailsAndPricing' import { useIsMounted } from '@hooks/useIsMounted' import { useMarketMetadata } from './MarketMetadata' +import { assetStateToString } from '@utils/assetState' import { isValidDid } from '@utils/ddo' export interface AssetProviderValue { @@ -29,6 +30,7 @@ export interface AssetProviderValue { isOwner: boolean oceanConfig: Config loading: boolean + assetState: string fetchAsset: (token?: CancelToken) => Promise } @@ -54,6 +56,7 @@ function AssetProvider({ const [loading, setLoading] = useState(false) const [isAssetNetwork, setIsAssetNetwork] = useState() const [oceanConfig, setOceanConfig] = useState() + const [assetState, setAssetState] = useState() const newCancelToken = useCancelToken() const isMounted = useIsMounted() @@ -85,27 +88,16 @@ function AssetProvider({ return } - if ([1, 2, 3].includes(asset.nft.state)) { - // handle nft states as documented in https://docs.oceanprotocol.com/core-concepts/did-ddo/#state - let state - switch (asset.nft.state) { - case 1: - state = 'end-of-life' - break - case 2: - state = 'deprecated' - break - case 3: - state = 'revoked' - break - } - - setTitle(`This asset has been flagged as "${state}" by the publisher`) + if (asset.nft.state === (1 | 2 | 3)) { + setTitle( + `This asset has been set as "${assetStateToString( + asset.nft.state + )}" by the publisher` + ) setError(`\`${did}\`` + `\n\nPublisher Address: ${asset.nft.owner}`) LoggerInstance.error(`[asset] Failed getting asset for ${did}`, asset) return } - if (asset) { setError(undefined) setAsset((prevState) => ({ @@ -116,12 +108,13 @@ function AssetProvider({ setOwner(asset.nft?.owner) setIsInPurgatory(asset.purgatory?.state) setPurgatoryData(asset.purgatory) + setAssetState(assetStateToString(asset.nft.state)) LoggerInstance.log('[asset] Got asset', asset) } setLoading(false) }, - [did] + [did, accountId] ) // ----------------------------------- @@ -198,6 +191,14 @@ function AssetProvider({ setOceanConfig(oceanConfig) }, [asset?.chainId]) + // ----------------------------------- + // Set Asset State as a string + // ----------------------------------- + useEffect(() => { + if (!asset?.nft) return + setAssetState(assetStateToString(asset.nft.state)) + }, [asset]) + return ( diff --git a/src/@utils/aquarius/index.ts b/src/@utils/aquarius/index.ts index 480e5506f..452b34ac7 100644 --- a/src/@utils/aquarius/index.ts +++ b/src/@utils/aquarius/index.ts @@ -254,6 +254,7 @@ export async function getPublishedAssets( const filters: FilterTerm[] = [] + filters.push(getFilterTerm('nft.state', [0, 4, 5])) filters.push(getFilterTerm('nft.owner', accountId.toLowerCase())) accesType !== undefined && filters.push(getFilterTerm('services.type', accesType)) diff --git a/src/@utils/assetState.ts b/src/@utils/assetState.ts new file mode 100644 index 000000000..46010ab39 --- /dev/null +++ b/src/@utils/assetState.ts @@ -0,0 +1,39 @@ +export function assetStateToString(state: number): string { + switch (state) { + case 0: + return 'Active' + case 1: + return 'End-of-life' + case 2: + return 'Deprecated (by another asset)' + case 3: + return 'Revoked by publisher' + case 4: + return 'Ordering is temporary disabled' + case 5: + return 'Asset unlisted' + + default: + break + } +} + +export function assetStateToNumber(state: string): number { + switch (state) { + case 'Active': + return 0 + case 'End-of-life': + return 1 + case 'Deprecated (by another asset)': + return 2 + case 'Revoked by publisher': + return 3 + case 'Ordering is temporary disabled': + return 4 + case 'Asset unlisted': + return 5 + + default: + break + } +} diff --git a/src/@utils/provider.ts b/src/@utils/provider.ts index de87533f4..92e30d62b 100644 --- a/src/@utils/provider.ts +++ b/src/@utils/provider.ts @@ -147,3 +147,14 @@ export async function downloadFile( ) await downloadFileBrowser(downloadUrl) } + +export async function checkValidProvider( + providerUrl: string +): Promise { + try { + const response = await ProviderInstance.isValidProvider(providerUrl) + return response + } catch (error) { + LoggerInstance.error(error.message) + } +} diff --git a/src/@utils/url/index.ts b/src/@utils/url/index.ts index 1c58f881b..313ccdbbf 100644 --- a/src/@utils/url/index.ts +++ b/src/@utils/url/index.ts @@ -1,3 +1,5 @@ +import isUrl from 'is-url-superb' + export function sanitizeUrl(url: string) { const u = decodeURI(url).trim().toLowerCase() const isAllowedUrlScheme = u.startsWith('http://') || u.startsWith('https://') @@ -6,7 +8,7 @@ export function sanitizeUrl(url: string) { // check if the url is a google domain export const isGoogleUrl = (url: string): boolean => { - if (!url) return + if (!url || !isUrl(url)) return const googleUrl = new URL(url) return googleUrl.hostname.endsWith('google.com') } diff --git a/src/components/@shared/FormInput/InputElement/FilesInput/index.test.tsx b/src/components/@shared/FormInput/InputElement/FilesInput/index.test.tsx index 2084b5c5c..d9281e4a7 100644 --- a/src/components/@shared/FormInput/InputElement/FilesInput/index.test.tsx +++ b/src/components/@shared/FormInput/InputElement/FilesInput/index.test.tsx @@ -2,7 +2,7 @@ import { fireEvent, render, screen } from '@testing-library/react' import React from 'react' import FilesInput from './index' import { useField } from 'formik' -import { getFileInfo } from '@utils/provider' +import { getFileInfo, checkValidProvider } from '@utils/provider' jest.mock('formik') jest.mock('@utils/provider') @@ -48,6 +48,7 @@ const mockForm = { describe('@shared/FormInput/InputElement/FilesInput', () => { it('renders without crashing', async () => { ;(useField as jest.Mock).mockReturnValue([mockField, mockMeta, mockHelpers]) + ;(checkValidProvider as jest.Mock).mockReturnValue(true) ;(getFileInfo as jest.Mock).mockReturnValue([ { valid: true, diff --git a/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx b/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx index 5376c37d3..7d4094617 100644 --- a/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx +++ b/src/components/@shared/FormInput/InputElement/FilesInput/index.tsx @@ -3,7 +3,7 @@ import { useField } from 'formik' import FileInfo from './Info' import UrlInput from '../URLInput' import { InputProps } from '@shared/FormInput' -import { getFileInfo } from '@utils/provider' +import { getFileInfo, checkValidProvider } from '@utils/provider' import { LoggerInstance } from '@oceanprotocol/lib' import { useAsset } from '@context/Asset' import { isGoogleUrl } from '@utils/url/index' @@ -33,6 +33,13 @@ export default function FilesInput(props: InputProps): ReactElement { ) } + // Check if provider is a valid provider + const isValid = await checkValidProvider(providerUrl) + if (!isValid) + throw Error( + '✗ Provider cannot be reached, please check status.oceanprotocol.com and try again later.' + ) + const checkedFile = await getFileInfo(url, providerUrl, storageType) // error if something's not right from response diff --git a/src/components/@shared/Price/index.tsx b/src/components/@shared/Price/index.tsx index f555f484e..6dff88ec5 100644 --- a/src/components/@shared/Price/index.tsx +++ b/src/components/@shared/Price/index.tsx @@ -15,17 +15,18 @@ export default function Price({ size?: 'small' | 'mini' | 'large' }): ReactElement { const isSupported = - accessDetails?.type === 'fixed' || accessDetails?.type === 'free' + (accessDetails?.type === 'fixed' || accessDetails?.type === 'free') && + accessDetails?.baseToken?.symbol const price = `${orderPriceAndFees?.price || accessDetails?.price}` return isSupported ? ( ) : null } diff --git a/src/components/Asset/AssetActions/AssetStats/index.tsx b/src/components/Asset/AssetActions/AssetStats/index.tsx index 4d02d0352..cc414890c 100644 --- a/src/components/Asset/AssetActions/AssetStats/index.tsx +++ b/src/components/Asset/AssetActions/AssetStats/index.tsx @@ -39,9 +39,9 @@ export default function AssetStats() { ) : null} {!asset?.stats || asset?.stats?.orders < 0 ? ( - 'N/A' + N/A ) : asset?.stats?.orders === 0 ? ( - 'No sales yet' + No sales yet ) : ( {asset.stats.orders} sale diff --git a/src/components/Asset/AssetActions/Download.tsx b/src/components/Asset/AssetActions/Download.tsx index abaa35559..f47238d49 100644 --- a/src/components/Asset/AssetActions/Download.tsx +++ b/src/components/Asset/AssetActions/Download.tsx @@ -50,17 +50,20 @@ export default function Download({ useState() const [retry, setRetry] = useState(false) - const isUnsupportedPricing = asset?.accessDetails?.type === 'NOT_SUPPORTED' + const isUnsupportedPricing = + asset?.accessDetails?.type === 'NOT_SUPPORTED' || + (asset?.accessDetails?.type === 'fixed' && + !asset?.accessDetails?.baseToken?.symbol) useEffect(() => { Number(asset?.nft.state) === 4 && setIsOrderDisabled(true) }, [asset?.nft.state]) + useEffect(() => { if (!asset?.accessDetails || isUnsupportedPricing) return - asset.accessDetails.isOwned && setIsOwned(asset?.accessDetails?.isOwned) - asset.accessDetails.validOrderTx && - setValidOrderTx(asset?.accessDetails?.validOrderTx) + setIsOwned(asset?.accessDetails?.isOwned || false) + setValidOrderTx(asset?.accessDetails?.validOrderTx || '') // get full price and fees async function init() { diff --git a/src/components/Asset/AssetContent/MetaFull.test.tsx b/src/components/Asset/AssetContent/MetaFull.test.tsx index 56053d369..e7e0e8aba 100644 --- a/src/components/Asset/AssetContent/MetaFull.test.tsx +++ b/src/components/Asset/AssetContent/MetaFull.test.tsx @@ -13,5 +13,6 @@ describe('src/components/Asset/AssetContent/MetaFull.tsx', () => { it('renders metadata for an algorithm', () => { render() expect(screen.getByText('Docker Image')).toBeInTheDocument() + expect(screen.getByText('DID')).toBeInTheDocument() }) }) diff --git a/src/components/Asset/AssetContent/MetaFull.tsx b/src/components/Asset/AssetContent/MetaFull.tsx index 1e6f2ba1c..60d036ba6 100644 --- a/src/components/Asset/AssetContent/MetaFull.tsx +++ b/src/components/Asset/AssetContent/MetaFull.tsx @@ -3,14 +3,12 @@ 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 { 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 { isInPurgatory, assetState } = useAsset() useEffect(() => { async function getInitialPaymentCollector() { @@ -43,6 +41,9 @@ export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement { title="Owner" content={} /> + {assetState !== 'Active' && ( + + )} {paymentCollector && paymentCollector !== ddo?.nft?.owner && ( () @@ -157,6 +159,16 @@ export default function Edit({ newAbortController() ) + if (values.assetState !== assetState) { + const nft = new Nft(web3) + + await nft.setMetadataState( + asset?.nftAddress, + accountId, + assetStateToNumber(values.assetState) + ) + } + LoggerInstance.log('[edit] setMetadata result', setMetadataTx) if (!setMetadataTx) { @@ -177,7 +189,8 @@ export default function Edit({ asset?.metadata, asset?.services[0]?.timeout, asset?.accessDetails?.price || '0', - paymentCollector + paymentCollector, + assetState ) as unknown as FormEditMetadataValues return ( diff --git a/src/components/Asset/Edit/FormEditMetadata.tsx b/src/components/Asset/Edit/FormEditMetadata.tsx index 4bf9043c9..4d5237d06 100644 --- a/src/components/Asset/Edit/FormEditMetadata.tsx +++ b/src/components/Asset/Edit/FormEditMetadata.tsx @@ -199,7 +199,7 @@ export default function FormEditMetadata({ - + + + ) diff --git a/src/components/Asset/Edit/_constants.ts b/src/components/Asset/Edit/_constants.ts index 4092b89ed..a0af0809e 100644 --- a/src/components/Asset/Edit/_constants.ts +++ b/src/components/Asset/Edit/_constants.ts @@ -6,7 +6,8 @@ export function getInitialValues( metadata: Metadata, timeout: number, price: string, - paymentCollector: string + paymentCollector: string, + assetState: string ): Partial { return { name: metadata?.name, @@ -17,7 +18,8 @@ export function getInitialValues( timeout: secondsToString(timeout), author: metadata?.author, tags: metadata?.tags, - paymentCollector + paymentCollector, + assetState } } diff --git a/src/components/Asset/Edit/_types.ts b/src/components/Asset/Edit/_types.ts index 923aabb5c..2a8563c58 100644 --- a/src/components/Asset/Edit/_types.ts +++ b/src/components/Asset/Edit/_types.ts @@ -9,6 +9,7 @@ export interface MetadataEditForm { links?: FileInfo[] author?: string tags?: string[] + assetState?: string } export interface ComputeEditForm { diff --git a/src/components/Asset/Edit/_validation.ts b/src/components/Asset/Edit/_validation.ts index 1ec0b960b..bc29ca701 100644 --- a/src/components/Asset/Edit/_validation.ts +++ b/src/components/Asset/Edit/_validation.ts @@ -43,7 +43,8 @@ export const validationSchema = Yup.object().shape({ (value) => { return web3.utils.isAddress(value) } - ) + ), + retireAsset: Yup.string() }) export const computeSettingsValidationSchema = Yup.object().shape({ diff --git a/src/components/Publish/Pricing/index.tsx b/src/components/Publish/Pricing/index.tsx index 1f8678d21..eae2a2fa6 100644 --- a/src/components/Publish/Pricing/index.tsx +++ b/src/components/Publish/Pricing/index.tsx @@ -22,23 +22,6 @@ export default function PricingFields(): ReactElement { token.name.toLowerCase().includes('ocean') ) || approvedBaseTokens?.[0] - const isBaseTokenSet = !!approvedBaseTokens?.find( - (token) => token?.address === values?.pricing?.baseToken?.address - ) - - useEffect(() => { - if (!approvedBaseTokens?.length) return - if (isBaseTokenSet) return - setFieldValue('pricing.baseToken', defaultBaseToken) - }, [ - approvedBaseTokens, - chainId, - defaultBaseToken, - isBaseTokenSet, - setFieldValue, - values.pricing.baseToken - ]) - // Switch type value upon tab change function handleTabChange(tabName: string) { const type = tabName.toLowerCase() diff --git a/src/components/Publish/Steps.tsx b/src/components/Publish/Steps.tsx index 78a1b81c6..eb81ded36 100644 --- a/src/components/Publish/Steps.tsx +++ b/src/components/Publish/Steps.tsx @@ -10,7 +10,7 @@ export function Steps({ }: { feedback: PublishFeedback }): ReactElement { - const { chainId, accountId } = useWeb3() + const { chainId, accountId, approvedBaseTokens } = useWeb3() const { values, setFieldValue, touched, setTouched } = useFormikContext() @@ -24,6 +24,21 @@ export function Steps({ setFieldValue('user.accountId', accountId) }, [chainId, accountId, setFieldValue]) + useEffect(() => { + if (!approvedBaseTokens?.length) return + + const defaultBaseToken = + approvedBaseTokens?.find((token) => + token.name.toLowerCase().includes('ocean') + ) || approvedBaseTokens?.[0] + const isBaseTokenSet = !!approvedBaseTokens?.find( + (token) => token?.address === values?.pricing?.baseToken?.address + ) + if (isBaseTokenSet) return + + setFieldValue('pricing.baseToken', defaultBaseToken) + }, [approvedBaseTokens]) + // auto-sync publish feedback into form data values useEffect(() => { setFieldValue('feedback', feedback)