mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge branch main into issue-1787-multichain-provider
This commit is contained in:
commit
359ff0b488
91
.jest/__fixtures__/algorithmAquarius.ts
Normal file
91
.jest/__fixtures__/algorithmAquarius.ts
Normal file
@ -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: ''
|
||||
}
|
||||
}
|
@ -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: {
|
@ -1,7 +1,7 @@
|
||||
import { assetAquarius } from './assetAquarius'
|
||||
import { datasetAquarius } from './datasetAquarius'
|
||||
|
||||
export const asset: AssetExtended = {
|
||||
...assetAquarius,
|
||||
...datasetAquarius,
|
||||
accessDetails: {
|
||||
templateId: 1,
|
||||
publisherMarketOrderFee: '0',
|
@ -5,6 +5,5 @@ export default {
|
||||
chainIds: [5, 1, 137, 56, 1285, 246],
|
||||
bookmarks: [],
|
||||
privacyPolicySlug: '/privacy/en',
|
||||
showPPC: true,
|
||||
infiniteApproval: false
|
||||
showPPC: true
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
import { assets } from '../../__fixtures__/assetsWithAccessDetails'
|
||||
import { assets } from '../../__fixtures__/datasetsWithAccessDetails'
|
||||
|
||||
export const getAccessDetailsForAssets = jest.fn().mockResolvedValue(assets)
|
||||
|
@ -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
|
||||
|
@ -32,7 +32,8 @@
|
||||
"label": "File",
|
||||
"prominentHelp": false,
|
||||
"type": "tabs",
|
||||
"fields": [{
|
||||
"fields": [
|
||||
{
|
||||
"value": "ipfs",
|
||||
"title": "IPFS",
|
||||
"label": "CID",
|
||||
@ -64,10 +65,12 @@
|
||||
"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
|
||||
},
|
||||
|
||||
@ -116,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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -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."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +106,8 @@
|
||||
"label": "File",
|
||||
"prominentHelp": false,
|
||||
"type": "tabs",
|
||||
"fields": [{
|
||||
"fields": [
|
||||
{
|
||||
"value": "ipfs",
|
||||
"title": "IPFS",
|
||||
"label": "CID",
|
||||
@ -138,10 +139,12 @@
|
||||
"prominentHelp": true,
|
||||
"type": "files",
|
||||
"required": true
|
||||
}],
|
||||
}
|
||||
],
|
||||
"sortOptions": false,
|
||||
"required": true
|
||||
},{
|
||||
},
|
||||
{
|
||||
"name": "links",
|
||||
"label": "Sample file",
|
||||
"prominentHelp": false,
|
||||
@ -157,7 +160,8 @@
|
||||
"prominentHelp": true,
|
||||
"type": "files",
|
||||
"required": false
|
||||
}],
|
||||
}
|
||||
],
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
|
8017
package-lock.json
generated
8017
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
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",
|
||||
@ -55,9 +55,9 @@
|
||||
"react-dotdotdot": "^1.3.1",
|
||||
"react-modal": "^3.16.1",
|
||||
"react-paginate": "^8.1.4",
|
||||
"react-select": "^5.6.1",
|
||||
"react-select": "^5.7.0",
|
||||
"react-spring": "^9.5.5",
|
||||
"react-tabs": "^5.1.0",
|
||||
"react-tabs": "^6.0.0",
|
||||
"react-toastify": "^9.1.1",
|
||||
"remark": "^14.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
@ -71,19 +71,19 @@
|
||||
"yup": "^0.32.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-essentials": "^6.5.13",
|
||||
"@storybook/addon-essentials": "^6.5.15",
|
||||
"@storybook/builder-webpack5": "^6.5.13",
|
||||
"@storybook/manager-webpack5": "^6.5.13",
|
||||
"@storybook/react": "^6.5.13",
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@types/jest": "^29.2.3",
|
||||
"@types/jest": "^29.2.5",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@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.0",
|
||||
"prettier": "^2.8.3",
|
||||
"pretty-quick": "^3.1.3",
|
||||
"process": "^0.11.10",
|
||||
"serve": "^14.1.2",
|
||||
|
@ -16,6 +16,8 @@ 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 {
|
||||
isInPurgatory: boolean
|
||||
@ -28,6 +30,7 @@ export interface AssetProviderValue {
|
||||
isOwner: boolean
|
||||
oceanConfig: Config
|
||||
loading: boolean
|
||||
assetState: string
|
||||
fetchAsset: (token?: CancelToken) => Promise<void>
|
||||
}
|
||||
|
||||
@ -53,6 +56,7 @@ function AssetProvider({
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [isAssetNetwork, setIsAssetNetwork] = useState<boolean>()
|
||||
const [oceanConfig, setOceanConfig] = useState<Config>()
|
||||
const [assetState, setAssetState] = useState<string>()
|
||||
|
||||
const newCancelToken = useCancelToken()
|
||||
const isMounted = useIsMounted()
|
||||
@ -63,6 +67,13 @@ function AssetProvider({
|
||||
const fetchAsset = useCallback(
|
||||
async (token?: CancelToken) => {
|
||||
if (!did) return
|
||||
const isDid = isValidDid(did)
|
||||
|
||||
if (!isDid) {
|
||||
setError(`The url is not for a valid DID`)
|
||||
LoggerInstance.error(`[asset] Not a valid DID`)
|
||||
return
|
||||
}
|
||||
|
||||
LoggerInstance.log('[asset] Fetching asset...')
|
||||
setLoading(true)
|
||||
@ -77,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) => ({
|
||||
@ -108,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]
|
||||
)
|
||||
|
||||
// -----------------------------------
|
||||
@ -190,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 (
|
||||
<AssetContext.Provider
|
||||
value={
|
||||
@ -205,7 +214,8 @@ function AssetProvider({
|
||||
fetchAsset,
|
||||
isAssetNetwork,
|
||||
isOwner,
|
||||
oceanConfig
|
||||
oceanConfig,
|
||||
assetState
|
||||
} as AssetProviderValue
|
||||
}
|
||||
>
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -46,6 +46,7 @@ declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
query: any
|
||||
sort?: { [jsonPath: string]: SortDirectionOptions }
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
aggs?: any
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ const defaultBaseQueryReturn = {
|
||||
query: {
|
||||
bool: {
|
||||
filter: [
|
||||
{ terms: { chainId: [1, 3] } },
|
||||
{ term: { _index: 'aquarius' } },
|
||||
{ terms: { chainId: [1, 3] } },
|
||||
{ term: { 'purgatory.state': false } },
|
||||
{ bool: { must_not: [{ term: { 'nft.state': 5 } }] } }
|
||||
]
|
||||
|
@ -42,28 +42,14 @@ export function getFilterTerm(
|
||||
export function generateBaseQuery(
|
||||
baseQueryParams: BaseQueryParams
|
||||
): SearchQuery {
|
||||
const generatedQuery = {
|
||||
from: baseQueryParams.esPaginationOptions?.from || 0,
|
||||
size:
|
||||
baseQueryParams.esPaginationOptions?.size >= 0
|
||||
? baseQueryParams.esPaginationOptions?.size
|
||||
: 1000,
|
||||
query: {
|
||||
bool: {
|
||||
...baseQueryParams.nestedQuery,
|
||||
filter: [
|
||||
...(baseQueryParams.filters || []),
|
||||
baseQueryParams.chainIds
|
||||
? getFilterTerm('chainId', baseQueryParams.chainIds)
|
||||
: [],
|
||||
getFilterTerm('_index', 'aquarius'),
|
||||
...(baseQueryParams.ignorePurgatory
|
||||
? []
|
||||
: [getFilterTerm('purgatory.state', false)]),
|
||||
...(baseQueryParams.ignoreState
|
||||
? []
|
||||
: [
|
||||
{
|
||||
const filters: unknown[] = [getFilterTerm('_index', 'aquarius')]
|
||||
baseQueryParams.filters && filters.push(...baseQueryParams.filters)
|
||||
baseQueryParams.chainIds &&
|
||||
filters.push(getFilterTerm('chainId', baseQueryParams.chainIds))
|
||||
!baseQueryParams.ignorePurgatory &&
|
||||
filters.push(getFilterTerm('purgatory.state', false))
|
||||
!baseQueryParams.ignoreState &&
|
||||
filters.push({
|
||||
bool: {
|
||||
must_not: [
|
||||
{
|
||||
@ -73,9 +59,17 @@ export function generateBaseQuery(
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
])
|
||||
]
|
||||
})
|
||||
const generatedQuery = {
|
||||
from: baseQueryParams.esPaginationOptions?.from || 0,
|
||||
size:
|
||||
baseQueryParams.esPaginationOptions?.size >= 0
|
||||
? baseQueryParams.esPaginationOptions?.size
|
||||
: 1000,
|
||||
query: {
|
||||
bool: {
|
||||
...baseQueryParams.nestedQuery,
|
||||
filter: filters
|
||||
}
|
||||
}
|
||||
} as SearchQuery
|
||||
@ -90,7 +84,6 @@ export function generateBaseQuery(
|
||||
baseQueryParams.sortOptions.sortDirection ||
|
||||
SortDirectionOptions.Descending
|
||||
}
|
||||
|
||||
return generatedQuery
|
||||
}
|
||||
|
||||
@ -260,6 +253,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))
|
||||
|
39
src/@utils/assetState.ts
Normal file
39
src/@utils/assetState.ts
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -1,5 +1,10 @@
|
||||
import { Asset, DDO, Service } from '@oceanprotocol/lib'
|
||||
|
||||
export function isValidDid(did: string): boolean {
|
||||
const regex = /did:op:[A-Za-z0-9]{64}/
|
||||
return regex.test(did)
|
||||
}
|
||||
|
||||
export function getServiceByName(
|
||||
ddo: Asset | DDO,
|
||||
name: 'access' | 'compute'
|
||||
|
@ -147,3 +147,14 @@ export async function downloadFile(
|
||||
)
|
||||
await downloadFileBrowser(downloadUrl)
|
||||
}
|
||||
|
||||
export async function checkValidProvider(
|
||||
providerUrl: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const response = await ProviderInstance.isValidProvider(providerUrl)
|
||||
return response
|
||||
} catch (error) {
|
||||
LoggerInstance.error(error.message)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,14 @@
|
||||
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://')
|
||||
return isAllowedUrlScheme ? url : 'about:blank'
|
||||
}
|
||||
|
||||
// check if the url is a google domain
|
||||
export const isGoogleUrl = (url: string): boolean => {
|
||||
if (!url || !isUrl(url)) return
|
||||
const googleUrl = new URL(url)
|
||||
return googleUrl.hostname.endsWith('google.com')
|
||||
}
|
||||
|
@ -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.'
|
||||
|
@ -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',
|
||||
|
@ -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(
|
||||
<AssetList
|
||||
assets={[assetAquarius]}
|
||||
assets={[datasetAquarius]}
|
||||
showPagination
|
||||
page={1}
|
||||
totalPages={10}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import testRender from '../../../../.jest/testRender'
|
||||
import AssetTeaser from './index'
|
||||
import { asset } from '../../../../.jest/__fixtures__/assetWithAccessDetails'
|
||||
import { asset } from '../../../../.jest/__fixtures__/datasetWithAccessDetails'
|
||||
|
||||
describe('@shared/AssetTeaser', () => {
|
||||
testRender(<AssetTeaser asset={asset} />)
|
||||
|
@ -40,6 +40,9 @@ export default function FileIcon({
|
||||
? filesize(Number(file.contentLength)).toString()
|
||||
: ''}
|
||||
</li>
|
||||
<li>
|
||||
{file.type === 'smartcontract' ? 'smart\ncontract' : file.type}
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
<li className={styles.empty}>No file info available</li>
|
||||
|
@ -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,
|
||||
|
@ -3,9 +3,10 @@ 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'
|
||||
|
||||
export default function FilesInput(props: InputProps): ReactElement {
|
||||
const [field, meta, helpers] = useField(props.name)
|
||||
@ -26,12 +27,19 @@ 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.'
|
||||
)
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -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', () => ({
|
||||
|
@ -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 ? (
|
||||
<PriceUnit
|
||||
price={Number(price)}
|
||||
symbol={accessDetails.baseToken?.symbol}
|
||||
symbol={accessDetails?.baseToken?.symbol}
|
||||
className={className}
|
||||
size={size}
|
||||
conversion={conversion}
|
||||
type={accessDetails.type}
|
||||
type={accessDetails?.type}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ export default function Tooltip(props: TippyProps): ReactElement {
|
||||
<Tippy
|
||||
interactive
|
||||
interactiveBorder={5}
|
||||
zIndex={1}
|
||||
zIndex={3}
|
||||
trigger={trigger || 'mouseenter focus'}
|
||||
disabled={disabled || null}
|
||||
placement={placement || 'auto'}
|
||||
|
@ -39,9 +39,9 @@ export default function AssetStats() {
|
||||
</span>
|
||||
) : null}
|
||||
{!asset?.stats || asset?.stats?.orders < 0 ? (
|
||||
'N/A'
|
||||
<span className={styles.stat}>N/A</span>
|
||||
) : asset?.stats?.orders === 0 ? (
|
||||
'No sales yet'
|
||||
<span className={styles.stat}>No sales yet</span>
|
||||
) : (
|
||||
<span className={styles.stat}>
|
||||
<span className={styles.number}>{asset.stats.orders}</span> sale
|
||||
|
@ -23,14 +23,14 @@ const computeProps: ButtonBuyProps = {
|
||||
action: 'compute',
|
||||
disabled: false,
|
||||
hasPreviousOrder: false,
|
||||
hasDatatoken: true,
|
||||
hasDatatoken: false,
|
||||
btSymbol: 'btSymbol',
|
||||
dtSymbol: 'dtSymbol',
|
||||
dtBalance: '100000000000',
|
||||
assetTimeout: '1 day',
|
||||
assetType: 'algorithm',
|
||||
hasPreviousOrderSelectedComputeAsset: false,
|
||||
hasDatatokenSelectedComputeAsset: true,
|
||||
hasDatatokenSelectedComputeAsset: false,
|
||||
dtSymbolSelectedComputeAsset: 'dtSymbol',
|
||||
dtBalanceSelectedComputeAsset: 'dtBalance',
|
||||
selectedComputeAssetType: 'selectedComputeAssetType',
|
||||
@ -78,6 +78,11 @@ describe('Asset/AssetActions/ButtonBuy', () => {
|
||||
render(<ButtonBuy {...downloadProps} priceType="free" hasPreviousOrder />)
|
||||
const button = screen.getByText('Download')
|
||||
expect(button).toContainHTML('<button')
|
||||
expect(
|
||||
screen.getByText(
|
||||
'This Dataset is free to use. Please note that network gas fees still apply, even when using free assets.'
|
||||
)
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('Renders "Get" button for free assets without crashing', () => {
|
||||
@ -105,6 +110,33 @@ describe('Asset/AssetActions/ButtonBuy', () => {
|
||||
expect(button).toContainHTML('<button')
|
||||
})
|
||||
|
||||
it('Renders correct message for fixed-priced compute asset with free algorithm', () => {
|
||||
render(<ButtonBuy {...computeProps} />)
|
||||
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(<ButtonBuy {...computeProps} priceType="free" />)
|
||||
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(<ButtonBuy {...computeProps} algorithmPriceType="fixed" />)
|
||||
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(<ButtonBuy {...computeProps} hasDatatokenSelectedComputeAsset />)
|
||||
const button = screen.getByText('Buy Compute Job')
|
||||
|
@ -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,16 @@ 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+/, '')
|
||||
return computeHelpText
|
||||
}
|
||||
|
||||
@ -190,6 +202,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 (
|
||||
<div className={styles.actions}>
|
||||
{isLoading ? (
|
||||
@ -205,42 +264,7 @@ export default function ButtonBuy({
|
||||
>
|
||||
{buttonText}
|
||||
</Button>
|
||||
<div className={styles.help}>
|
||||
{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
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.help}>{message()}</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
@ -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}
|
||||
/>
|
||||
|
@ -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({
|
||||
<Row
|
||||
price={providerFeeAmount} // initializeCompute.provider fee amount
|
||||
timeout={`${validUntil} seconds`} // valid until value
|
||||
symbol={'OCEAN'} // we assume that provider fees will always be in OCEAN token
|
||||
symbol={providerFeesSymbol} // we assume that provider fees will always be in OCEAN token
|
||||
sign="+"
|
||||
type="C2D RESOURCES"
|
||||
/>
|
||||
|
@ -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<ProviderComputeInitializeResults>()
|
||||
const [providerFeeAmount, setProviderFeeAmount] = useState<string>('0')
|
||||
const [providerFeesSymbol, setProviderFeesSymbol] = useState<string>('OCEAN')
|
||||
const [computeValidUntil, setComputeValidUntil] = useState<string>('0')
|
||||
const [datasetOrderPriceAndFees, setDatasetOrderPriceAndFees] =
|
||||
useState<OrderPriceAndFees>()
|
||||
@ -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)
|
||||
@ -467,11 +481,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
|
||||
}
|
||||
|
@ -50,17 +50,20 @@ export default function Download({
|
||||
useState<OrderPriceAndFees>()
|
||||
const [retry, setRetry] = useState<boolean>(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() {
|
||||
|
11
src/components/Asset/AssetContent/Bookmark.test.tsx
Normal file
11
src/components/Asset/AssetContent/Bookmark.test.tsx
Normal file
@ -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(<Bookmark did={datasetAquarius.id} />)
|
||||
expect(screen.getByTitle('Add Bookmark')).toBeInTheDocument()
|
||||
})
|
||||
})
|
18
src/components/Asset/AssetContent/MetaFull.test.tsx
Normal file
18
src/components/Asset/AssetContent/MetaFull.test.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
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(<MetaFull ddo={datasetAquarius} />)
|
||||
expect(screen.getByText('Owner')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders metadata for an algorithm', () => {
|
||||
render(<MetaFull ddo={algorithmAquarius} />)
|
||||
expect(screen.getByText('Docker Image')).toBeInTheDocument()
|
||||
expect(screen.getByText('DID')).toBeInTheDocument()
|
||||
})
|
||||
})
|
@ -3,17 +3,18 @@ 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<string>()
|
||||
const { isInPurgatory } = useAsset()
|
||||
const { web3 } = useWeb3()
|
||||
const { isInPurgatory, assetState } = useAsset()
|
||||
|
||||
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 +24,7 @@ export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement {
|
||||
}
|
||||
}
|
||||
getInitialPaymentCollector()
|
||||
}, [ddo, web3])
|
||||
}, [ddo])
|
||||
|
||||
function DockerImage() {
|
||||
const containerInfo = ddo?.metadata?.algorithm?.container
|
||||
@ -40,6 +41,9 @@ export default function MetaFull({ ddo }: { ddo: Asset }): ReactElement {
|
||||
title="Owner"
|
||||
content={<Publisher account={ddo?.nft?.owner} />}
|
||||
/>
|
||||
{assetState !== 'Active' && (
|
||||
<MetaItem title="Asset State" content={assetState} />
|
||||
)}
|
||||
{paymentCollector && paymentCollector !== ddo?.nft?.owner && (
|
||||
<MetaItem
|
||||
title="Revenue Sent To"
|
||||
|
18
src/components/Asset/AssetContent/MetaSecondary.test.tsx
Normal file
18
src/components/Asset/AssetContent/MetaSecondary.test.tsx
Normal file
@ -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(<MetaSecondary ddo={datasetAquarius} />)
|
||||
expect(
|
||||
screen.getByText(datasetAquarius.metadata.tags[0])
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
it('renders download sample button', () => {
|
||||
render(<MetaSecondary ddo={algorithmAquarius} />)
|
||||
expect(screen.getByText('Sample Data')).toBeInTheDocument()
|
||||
})
|
||||
})
|
@ -6,7 +6,8 @@ import {
|
||||
FixedRateExchange,
|
||||
Asset,
|
||||
Service,
|
||||
Datatoken
|
||||
Datatoken,
|
||||
Nft
|
||||
} from '@oceanprotocol/lib'
|
||||
import { validationSchema } from './_validation'
|
||||
import { getInitialValues } from './_constants'
|
||||
@ -26,6 +27,7 @@ import { useAsset } from '@context/Asset'
|
||||
import { setNftMetadata } from '@utils/nft'
|
||||
import { sanitizeUrl } from '@utils/url'
|
||||
import { getEncryptedFiles } from '@utils/provider'
|
||||
import { assetStateToNumber } from '@utils/assetState'
|
||||
|
||||
export default function Edit({
|
||||
asset
|
||||
@ -33,7 +35,7 @@ export default function Edit({
|
||||
asset: AssetExtended
|
||||
}): ReactElement {
|
||||
const { debug } = useUserPreferences()
|
||||
const { fetchAsset, isAssetNetwork } = useAsset()
|
||||
const { fetchAsset, isAssetNetwork, assetState } = useAsset()
|
||||
const { accountId, web3 } = useWeb3()
|
||||
const newAbortController = useAbortController()
|
||||
const [success, setSuccess] = useState<string>()
|
||||
@ -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) {
|
||||
@ -179,8 +191,9 @@ export default function Edit({
|
||||
initialValues={getInitialValues(
|
||||
asset?.metadata,
|
||||
asset?.services[0]?.timeout,
|
||||
asset?.accessDetails?.price,
|
||||
paymentCollector
|
||||
asset?.accessDetails?.price || '0',
|
||||
paymentCollector,
|
||||
assetState
|
||||
)}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={async (values, { resetForm }) => {
|
||||
|
@ -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],
|
||||
@ -134,6 +135,11 @@ export default function FormEditMetadata({
|
||||
component={Input}
|
||||
name="paymentCollector"
|
||||
/>
|
||||
<Field
|
||||
{...getFieldContent('assetState', data)}
|
||||
component={Input}
|
||||
name="assetState"
|
||||
/>
|
||||
|
||||
<FormActions />
|
||||
</Form>
|
||||
|
@ -6,7 +6,8 @@ export function getInitialValues(
|
||||
metadata: Metadata,
|
||||
timeout: number,
|
||||
price: string,
|
||||
paymentCollector: string
|
||||
paymentCollector: string,
|
||||
assetState: string
|
||||
): Partial<MetadataEditForm> {
|
||||
return {
|
||||
name: metadata?.name,
|
||||
@ -17,7 +18,8 @@ export function getInitialValues(
|
||||
timeout: secondsToString(timeout),
|
||||
author: metadata?.author,
|
||||
tags: metadata?.tags,
|
||||
paymentCollector
|
||||
paymentCollector,
|
||||
assetState
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ export interface MetadataEditForm {
|
||||
links?: FileInfo[]
|
||||
author?: string
|
||||
tags?: string[]
|
||||
assetState?: string
|
||||
}
|
||||
|
||||
export interface ComputeEditForm {
|
||||
|
@ -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({
|
||||
|
@ -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'
|
||||
|
||||
|
@ -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 (
|
||||
<li>
|
||||
<Input
|
||||
label="Token Approvals"
|
||||
help="Use infinite amount when approving tokens in _Use_."
|
||||
name="infiniteApproval"
|
||||
type="checkbox"
|
||||
options={['Allow infinite amount']}
|
||||
defaultChecked={infiniteApproval === true}
|
||||
onChange={() => setInfiniteApproval(!infiniteApproval)}
|
||||
/>
|
||||
</li>
|
||||
)
|
||||
}
|
@ -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={
|
||||
<ul className={styles.preferencesDetails}>
|
||||
<Currency />
|
||||
<TokenApproval />
|
||||
<Appearance darkMode={darkMode} />
|
||||
<Debug />
|
||||
</ul>
|
||||
|
@ -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<typeof axios>
|
||||
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)
|
||||
|
@ -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()
|
||||
|
@ -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<FormPublishData>()
|
||||
|
||||
@ -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)
|
||||
|
@ -14,25 +14,9 @@ export default function Page404(): ReactElement {
|
||||
<>
|
||||
<Head>
|
||||
<style type="text/css">{`
|
||||
body {
|
||||
background: transparent url(${fishfail}) center bottom no-repeat !important;
|
||||
background-size: cover !important;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
header *,
|
||||
footer *,
|
||||
main * {
|
||||
color: var(--brand-white) !important;
|
||||
}
|
||||
|
||||
header svg path {
|
||||
fill: var(--brand-white) !important;
|
||||
}
|
||||
`}</style>
|
||||
</Head>
|
||||
<Page
|
||||
|
Loading…
Reference in New Issue
Block a user