1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

package updates & technical debt cleanup (#1771)

* package updates

* bump Next.js

* update for Next.js v13 new `Link` behavior

* see https://nextjs.org/docs/upgrading#link-component

* test tweaks, simplify getNetworkDisplayName()

* modify codeclimate excludes

* test tweaks and cleanup

* more cleanup

* switch to Node.js v18

* back to Node.js v16

* temporarily run CI against Node.js v16 & v18

* update codeowners

* fixtures fixes for asset price

* switch to Node.js v18

* package updates

* remark updates, typescript and test fixes

* fix

* test run fixes

* yet another lockfileVersion update

* package updates

* test run fixes
This commit is contained in:
Matthias Kretschmann 2022-12-01 09:09:40 +00:00 committed by GitHub
parent b58cb36e00
commit 1b612e4194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 49121 additions and 2255 deletions

View File

@ -42,7 +42,7 @@ exclude_patterns:
- '**/*.d.ts' - '**/*.d.ts'
- '**/@types/' - '**/@types/'
- '**/_types.*' - '**/_types.*'
- '**/*.stories.tsx' - '**/*.stories.*'
- '**/*.test.tsx' - '**/*.test.*'
- '.storybook/' - '.storybook/'
- '.jest/' - '.jest/'

2
.github/CODEOWNERS vendored
View File

@ -1 +1 @@
* @mihaisc @kremalicious @claudiaHash @bogdanfazakas @EnzoVezzaro * @jamiehewitt15 @mihaisc @kremalicious @bogdanfazakas @EnzoVezzaro

View File

@ -4,7 +4,6 @@ on:
push: push:
branches: branches:
- main - main
- v4
- v3 - v3
tags: tags:
- '**' - '**'
@ -20,7 +19,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
node: ['16'] node: ['18']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -47,7 +46,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
node: ['16'] node: ['18']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -82,7 +81,7 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- uses: actions/setup-node@v3 - uses: actions/setup-node@v3
with: with:
node-version: '16' node-version: '18'
- name: Cache node_modules - name: Cache node_modules
uses: actions/cache@v3 uses: actions/cache@v3
env: env:
@ -110,7 +109,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
node: ['16'] node: ['18']
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ coverage
.next .next
.artifacts .artifacts
.vercel .vercel
.swc
repo-metadata.json repo-metadata.json
networks-metadata.json networks-metadata.json
src/@types/subgraph src/@types/subgraph

3
.jest/__mocks__/tar.ts Normal file
View File

@ -0,0 +1,3 @@
// mocked, as this module makes Jest go all
// "Uncaught SyntaxError: Octal escape sequences are not allowed in strict mode"
export default jest.fn().mockImplementation(() => 'hello')

View File

@ -9,13 +9,13 @@ const createJestConfig = nextJest({
const customJestConfig = { const customJestConfig = {
rootDir: '../', rootDir: '../',
// Add more setup options before each test is run // Add more setup options before each test is run
setupFilesAfterEnv: ['<rootDir>/.jest/jest.setup.js'], setupFilesAfterEnv: ['<rootDir>/.jest/jest.setup.tsx'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work // if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/src'], moduleDirectories: ['node_modules', '<rootDir>/src'],
testEnvironment: 'jest-environment-jsdom', testEnvironment: 'jsdom',
moduleNameMapper: { moduleNameMapper: {
'^.+\\.(svg)$': '<rootDir>/.jest/__mocks__/svgrMock.tsx', '^.+\\.(svg)$': '<rootDir>/.jest/__mocks__/svgrMock.tsx',
// '^@/components/(.*)$': '<rootDir>/components/$1', '@components/(.*)$': '<rootDir>/src/components/$1',
'@shared(.*)$': '<rootDir>/src/components/@shared/$1', '@shared(.*)$': '<rootDir>/src/components/@shared/$1',
'@hooks/(.*)$': '<rootDir>/src/@hooks/$1', '@hooks/(.*)$': '<rootDir>/src/@hooks/$1',
'@context/(.*)$': '<rootDir>/src/@context/$1', '@context/(.*)$': '<rootDir>/src/@context/$1',
@ -29,8 +29,25 @@ const customJestConfig = {
'!src/**/*.{stories,test}.{ts,tsx}', '!src/**/*.{stories,test}.{ts,tsx}',
'!src/@types/**/*.{ts,tsx}' '!src/@types/**/*.{ts,tsx}'
], ],
testPathIgnorePatterns: ['node_modules', '\\.cache', '.next', 'coverage'] // Add ignores so ESM packages are not transformed by Jest
// note: this does not work with Next.js, hence workaround further down
// see: https://github.com/vercel/next.js/issues/35634#issuecomment-1115250297
// transformIgnorePatterns: ['node_modules/(?!(uuid|remark)/)'],
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/.next/',
'<rootDir>/coverage'
]
} }
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async // https://github.com/vercel/next.js/issues/35634#issuecomment-1115250297
module.exports = createJestConfig(customJestConfig) async function jestConfig() {
const nextJestConfig = await createJestConfig(customJestConfig)()
// Add ignores for specific ESM packages so they are transformed by Jest
// /node_modules/ is the first pattern
nextJestConfig.transformIgnorePatterns[0] = '/node_modules/(?!uuid|remark)/'
return nextJestConfig
}
module.exports = jestConfig

View File

@ -1,3 +0,0 @@
import '@testing-library/jest-dom/extend-expect'
import './__mocks__/matchMedia'
import './__mocks__/hooksMocks'

20
.jest/jest.setup.tsx Normal file
View File

@ -0,0 +1,20 @@
import '@testing-library/jest-dom/extend-expect'
import { jest } from '@jest/globals'
import './__mocks__/matchMedia'
import './__mocks__/hooksMocks'
jest.mock('next/router', () => ({
useRouter: jest.fn().mockImplementation(() => ({
route: '/',
pathname: '/'
}))
}))
// jest.mock('next/head', () => {
// return {
// __esModule: true,
// default: ({ children }: { children: Array<React.ReactElement> }) => {
// return <>{children}</>
// }
// }
// })

2
.nvmrc
View File

@ -1 +1 @@
16 18

View File

@ -253,7 +253,7 @@ export default function NetworkName(): ReactElement {
const { networkId, isTestnet } = useWeb3() const { networkId, isTestnet } = useWeb3()
const { networksList } = useNetworkMetadata() const { networksList } = useNetworkMetadata()
const networkData = getNetworkDataById(networksList, networkId) const networkData = getNetworkDataById(networksList, networkId)
const networkName = getNetworkDisplayName(networkData, networkId) const networkName = getNetworkDisplayName(networkData)
return ( return (
<> <>

50519
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,12 +32,12 @@
"@tippyjs/react": "^4.2.6", "@tippyjs/react": "^4.2.6",
"@urql/exchange-refocus": "^1.0.0", "@urql/exchange-refocus": "^1.0.0",
"@walletconnect/web3-provider": "^1.8.0", "@walletconnect/web3-provider": "^1.8.0",
"axios": "^1.1.3", "axios": "^1.2.0",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"decimal.js": "^10.3.1", "decimal.js": "^10.4.2",
"dom-confetti": "^0.2.2", "dom-confetti": "^0.2.2",
"dotenv": "^16.0.1", "dotenv": "^16.0.3",
"filesize": "^10.0.5", "filesize": "^10.0.5",
"formik": "^2.2.9", "formik": "^2.2.9",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
@ -46,28 +46,28 @@
"js-cookie": "^3.0.1", "js-cookie": "^3.0.1",
"match-sorter": "^6.3.1", "match-sorter": "^6.3.1",
"myetherwallet-blockies": "^0.1.1", "myetherwallet-blockies": "^0.1.1",
"next": "12.3.1", "next": "13.0.5",
"query-string": "^7.1.1", "query-string": "^7.1.1",
"react": "^18.2.0", "react": "^18.2.0",
"react-clipboard.js": "^2.0.16", "react-clipboard.js": "^2.0.16",
"react-data-table-component": "^7.5.2", "react-data-table-component": "^7.5.3",
"react-dom": "^18.1.0", "react-dom": "^18.2.0",
"react-dotdotdot": "^1.3.1", "react-dotdotdot": "^1.3.1",
"react-modal": "^3.15.1", "react-modal": "^3.16.1",
"react-paginate": "^8.1.3", "react-paginate": "^8.1.4",
"react-select": "^5.4.0", "react-select": "^5.6.1",
"react-spring": "^9.5.2", "react-spring": "^9.5.5",
"react-tabs": "^5.1.0", "react-tabs": "^5.1.0",
"react-toastify": "^9.0.4", "react-toastify": "^9.1.1",
"remark": "^13.0.0", "remark": "^14.0.2",
"remark-gfm": "^1.0.0", "remark-gfm": "^3.0.1",
"remark-html": "^13.0.1", "remark-html": "^15.0.1",
"remove-markdown": "^0.5.0", "remove-markdown": "^0.5.0",
"slugify": "^1.6.5", "slugify": "^1.6.5",
"swr": "^1.3.0", "swr": "^1.3.0",
"urql": "^3.0.3", "urql": "^3.0.3",
"web3": "^1.8.0", "web3": "^1.8.1",
"web3modal": "^1.9.9", "web3modal": "^1.9.10",
"yup": "^0.32.11" "yup": "^0.32.11"
}, },
"devDependencies": { "devDependencies": {
@ -78,37 +78,38 @@
"@svgr/webpack": "^6.5.1", "@svgr/webpack": "^6.5.1",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@types/jest": "^29.2.3",
"@types/js-cookie": "^3.0.2", "@types/js-cookie": "^3.0.2",
"@types/loadable__component": "^5.13.4", "@types/loadable__component": "^5.13.4",
"@types/node": "^18.8.5", "@types/node": "^18.8.5",
"@types/react": "^18.0.21", "@types/react": "^18.0.25",
"@types/react-dom": "^18.0.5", "@types/react-dom": "^18.0.9",
"@types/react-modal": "^3.13.1", "@types/react-modal": "^3.13.1",
"@types/react-paginate": "^7.1.1", "@types/react-paginate": "^7.1.1",
"@types/remove-markdown": "^0.3.1", "@types/remove-markdown": "^0.3.1",
"@typescript-eslint/eslint-plugin": "^5.42.0", "@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.42.0", "@typescript-eslint/parser": "^5.43.0",
"apollo": "^2.34.0", "apollo": "^2.34.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^8.25.0", "eslint": "^8.28.0",
"eslint-config-oceanprotocol": "^2.0.4", "eslint-config-oceanprotocol": "^2.0.4",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest-dom": "^4.0.2", "eslint-plugin-jest-dom": "^4.0.3",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.10", "eslint-plugin-react": "^7.31.11",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-testing-library": "^5.7.2", "eslint-plugin-testing-library": "^5.9.1",
"https-browserify": "^1.0.0", "https-browserify": "^1.0.0",
"husky": "^8.0.1", "husky": "^8.0.2",
"jest": "^29.1.2", "jest": "^29.3.1",
"jest-environment-jsdom": "^29.2.2", "jest-environment-jsdom": "^29.3.1",
"prettier": "^2.7.1", "prettier": "^2.8.0",
"pretty-quick": "^3.1.3", "pretty-quick": "^3.1.3",
"process": "^0.11.10", "process": "^0.11.10",
"serve": "^14.0.1", "serve": "^14.1.2",
"stream-http": "^3.2.0", "stream-http": "^3.2.0",
"tsconfig-paths-webpack-plugin": "^4.0.0", "tsconfig-paths-webpack-plugin": "^4.0.0",
"typescript": "^4.8.4" "typescript": "^4.9.3"
}, },
"overrides": { "overrides": {
"graphql": "15.8.0" "graphql": "15.8.0"
@ -118,7 +119,7 @@
"url": "https://github.com/oceanprotocol/market" "url": "https://github.com/oceanprotocol/market"
}, },
"engines": { "engines": {
"node": "16" "node": "18"
}, },
"browserslist": [ "browserslist": [
">0.2%", ">0.2%",

View File

@ -9,7 +9,7 @@ import React, {
} from 'react' } from 'react'
import { Config, LoggerInstance, Purgatory } from '@oceanprotocol/lib' import { Config, LoggerInstance, Purgatory } from '@oceanprotocol/lib'
import { CancelToken } from 'axios' import { CancelToken } from 'axios'
import { retrieveAsset } from '@utils/aquarius' import { getAsset } from '@utils/aquarius'
import { useWeb3 } from './Web3' import { useWeb3 } from './Web3'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
import { getOceanConfig, getDevelopmentConfig } from '@utils/ocean' import { getOceanConfig, getDevelopmentConfig } from '@utils/ocean'
@ -66,7 +66,7 @@ function AssetProvider({
LoggerInstance.log('[asset] Fetching asset...') LoggerInstance.log('[asset] Fetching asset...')
setLoading(true) setLoading(true)
const asset = await retrieveAsset(did, token) const asset = await getAsset(did, token)
if (!asset) { if (!asset) {
setError( setError(

View File

@ -7,7 +7,7 @@ import React, {
useEffect, useEffect,
useState useState
} from 'react' } from 'react'
import { OpcQuery } from 'src/@types/subgraph/OpcQuery' import { OpcQuery } from '../../../src/@types/subgraph/OpcQuery'
import { OperationResult } from 'urql' import { OperationResult } from 'urql'
import { opcQuery } from './_queries' import { opcQuery } from './_queries'
import { MarketMetadataProviderValue, OpcFee } from './_types' import { MarketMetadataProviderValue, OpcFee } from './_types'

View File

@ -307,7 +307,7 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
) )
// Construct network display name // Construct network display name
const networkDisplayName = getNetworkDisplayName(networkData, networkId) const networkDisplayName = getNetworkDisplayName(networkData)
setNetworkDisplayName(networkDisplayName) setNetworkDisplayName(networkDisplayName)
setIsTestnet(getNetworkType(networkData) !== NetworkType.Mainnet) setIsTestnet(getNetworkType(networkData) !== NetworkType.Mainnet)

View File

@ -0,0 +1,43 @@
import { getNetworkType, getNetworkDisplayName } from './utils'
describe('useNetworkMetadata/utils', () => {
test('getNetworkType returns mainnet', () => {
const type = getNetworkType({
name: 'Eth',
title: 'Eth'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any)
expect(type).toBe('mainnet')
})
test('getNetworkType returns testnet if "Test" is in name', () => {
const type = getNetworkType({
name: 'Testnet',
title: 'Testnet'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any)
expect(type).toBe('testnet')
})
test('getNetworkDisplayName returns correct values', () => {
/* eslint-disable @typescript-eslint/no-explicit-any */
const type1 = getNetworkDisplayName({
chainId: 1,
chain: 'ETH',
name: 'Ethereum Mainnet'
} as any)
expect(type1).toBe('ETH')
const type2 = getNetworkDisplayName({ chainId: 80001 } as any)
expect(type2).toBe('Mumbai')
const type3 = getNetworkDisplayName({ chainId: 8996 } as any)
expect(type3).toBe('Development')
const type4 = getNetworkDisplayName({ chainId: 2021000 } as any)
expect(type4).toBe('GAIA-X')
/* eslint-enable @typescript-eslint/no-explicit-any */
})
})

View File

@ -11,9 +11,8 @@ export function getNetworkType(network: EthereumListsChain): string {
// We hack in mainnet detection for moonriver. // We hack in mainnet detection for moonriver.
if ( if (
network && network &&
!network.name.includes('Testnet') && !network.name?.includes('Testnet') &&
!network.title?.includes('Testnet') && !network.title?.includes('Testnet')
network.name !== 'Moonbase Alpha'
) { ) {
return NetworkType.Mainnet return NetworkType.Mainnet
} else { } else {
@ -21,19 +20,13 @@ export function getNetworkType(network: EthereumListsChain): string {
} }
} }
export function getNetworkDisplayName( export function getNetworkDisplayName(data: EthereumListsChain): string {
data: EthereumListsChain,
networkId: number
): string {
let displayName let displayName
switch (networkId) { switch (data.chainId) {
case 137: case 137:
displayName = 'Polygon' displayName = 'Polygon'
break break
case 1287:
displayName = 'Moonbase'
break
case 1285: case 1285:
displayName = 'Moonriver' displayName = 'Moonriver'
break break
@ -43,9 +36,6 @@ export function getNetworkDisplayName(
case 8996: case 8996:
displayName = 'Development' displayName = 'Development'
break break
case 3:
displayName = 'Ropsten'
break
case 5: case 5:
displayName = 'Görli' displayName = 'Görli'
break break
@ -54,7 +44,9 @@ export function getNetworkDisplayName(
break break
default: default:
displayName = data displayName = data
? `${data.chain} ${getNetworkType(data) === 'mainnet' ? '' : data.name}` ? `${data.chain}${
getNetworkType(data) === 'mainnet' ? '' : ` ${data.name}`
}`
: 'Unknown' : 'Unknown'
break break
} }

View File

@ -0,0 +1,70 @@
import {
SortDirectionOptions,
SortTermOptions
} from '../../@types/aquarius/SearchQuery'
import { escapeEsReservedCharacters, getFilterTerm, generateBaseQuery } from '.'
const defaultBaseQueryReturn = {
from: 0,
query: {
bool: {
filter: [
{ terms: { chainId: [1, 3] } },
{ term: { _index: 'aquarius' } },
{ term: { 'purgatory.state': false } },
{ bool: { must_not: [{ term: { 'nft.state': 5 } }] } }
]
}
},
size: 1000
}
describe('@utils/aquarius', () => {
test('escapeEsReservedCharacters', () => {
expect(escapeEsReservedCharacters('<')).toBe('\\<')
})
test('getFilterTerm with string value', () => {
expect(getFilterTerm('hello', 'world')).toStrictEqual({
term: { hello: 'world' }
})
})
test('getFilterTerm with array value', () => {
expect(getFilterTerm('hello', ['world', 'domination'])).toStrictEqual({
terms: { hello: ['world', 'domination'] }
})
})
test('generateBaseQuery', () => {
expect(generateBaseQuery({ chainIds: [1, 3] })).toStrictEqual(
defaultBaseQueryReturn
)
})
test('generateBaseQuery aggs are passed through', () => {
expect(
generateBaseQuery({ chainIds: [1, 3], aggs: 'hello world' })
).toStrictEqual({
...defaultBaseQueryReturn,
aggs: 'hello world'
})
})
test('generateBaseQuery sortOptions are passed through', () => {
expect(
generateBaseQuery({
chainIds: [1, 3],
sortOptions: {
sortBy: SortTermOptions.Created,
sortDirection: SortDirectionOptions.Ascending
}
})
).toStrictEqual({
...defaultBaseQueryReturn,
sort: {
'nft.created': 'asc'
}
})
})
})

View File

@ -1,13 +1,13 @@
import { Asset, LoggerInstance } from '@oceanprotocol/lib' import { Asset, LoggerInstance } from '@oceanprotocol/lib'
import { AssetSelectionAsset } from '@shared/FormInput/InputElement/AssetSelection' import { AssetSelectionAsset } from '@shared/FormInput/InputElement/AssetSelection'
import axios, { CancelToken, AxiosResponse } from 'axios' import axios, { CancelToken, AxiosResponse } from 'axios'
import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData' import { OrdersData_orders as OrdersData } from '../../@types/subgraph/OrdersData'
import { metadataCacheUri } from '../../app.config' import { metadataCacheUri } from '../../../app.config'
import { import {
SortDirectionOptions, SortDirectionOptions,
SortTermOptions SortTermOptions
} from '../@types/aquarius/SearchQuery' } from '../../@types/aquarius/SearchQuery'
import { transformAssetToAssetSelection } from './assetConvertor' import { transformAssetToAssetSelection } from '../assetConvertor'
export interface UserSales { export interface UserSales {
id: string id: string
@ -55,13 +55,13 @@ export function generateBaseQuery(
...(baseQueryParams.filters || []), ...(baseQueryParams.filters || []),
baseQueryParams.chainIds baseQueryParams.chainIds
? getFilterTerm('chainId', baseQueryParams.chainIds) ? getFilterTerm('chainId', baseQueryParams.chainIds)
: '', : [],
getFilterTerm('_index', 'aquarius'), getFilterTerm('_index', 'aquarius'),
...(baseQueryParams.ignorePurgatory ...(baseQueryParams.ignorePurgatory
? '' ? []
: [getFilterTerm('purgatory.state', false)]), : [getFilterTerm('purgatory.state', false)]),
...(baseQueryParams.ignoreState ...(baseQueryParams.ignoreState
? '' ? []
: [ : [
{ {
bool: { bool: {
@ -143,7 +143,7 @@ export async function queryMetadata(
} }
} }
export async function retrieveAsset( export async function getAsset(
did: string, did: string,
cancelToken: CancelToken cancelToken: CancelToken
): Promise<Asset> { ): Promise<Asset> {
@ -186,73 +186,7 @@ export async function getAssetsNames(
} }
} }
export async function getAssetsFromDidList( export async function getAssetsFromDids(
didList: string[],
chainIds: number[],
cancelToken: CancelToken
): Promise<PagedAssets> {
try {
if (!didList.length) return
const baseParams = {
chainIds,
filters: [getFilterTerm('_id', didList)],
ignorePurgatory: true
} as BaseQueryParams
const query = generateBaseQuery(baseParams)
const queryResult = await queryMetadata(query, cancelToken)
return queryResult
} catch (error) {
LoggerInstance.error(error.message)
}
}
export async function getAssetsFromDtList(
dtList: string[],
chainIds: number[],
cancelToken: CancelToken
): Promise<Asset[]> {
try {
if (!dtList.length) return
const baseParams = {
chainIds,
filters: [getFilterTerm('services.datatokenAddress', dtList)],
ignorePurgatory: true
} as BaseQueryParams
const query = generateBaseQuery(baseParams)
const queryResult = await queryMetadata(query, cancelToken)
return queryResult?.results
} catch (error) {
LoggerInstance.error(error.message)
}
}
export async function getAssetsFromNftList(
nftList: string[],
chainIds: number[],
cancelToken: CancelToken
): Promise<Asset[]> {
try {
if (!(nftList.length > 0)) return
const baseParams = {
chainIds,
filters: [getFilterTerm('nftAddress', nftList)],
ignorePurgatory: true
} as BaseQueryParams
const query = generateBaseQuery(baseParams)
const queryResult = await queryMetadata(query, cancelToken)
return queryResult?.results
} catch (error) {
LoggerInstance.error(error.message)
}
}
export async function retrieveDDOListByDIDs(
didList: string[], didList: string[],
chainIds: number[], chainIds: number[],
cancelToken: CancelToken cancelToken: CancelToken
@ -368,7 +302,7 @@ export async function getPublishedAssets(
} }
} }
export async function getTopPublishers( async function getTopPublishers(
chainIds: number[], chainIds: number[],
cancelToken: CancelToken, cancelToken: CancelToken,
page?: number, page?: number,

View File

@ -17,7 +17,7 @@ import {
queryMetadata, queryMetadata,
getFilterTerm, getFilterTerm,
generateBaseQuery, generateBaseQuery,
retrieveDDOListByDIDs getAssetsFromDids
} from './aquarius' } from './aquarius'
import { fetchDataForMultipleChains } from './subgraph' import { fetchDataForMultipleChains } from './subgraph'
import { getServiceById, getServiceByName } from './ddo' import { getServiceById, getServiceByName } from './ddo'
@ -338,7 +338,7 @@ export async function createTrustedAlgorithmList(
if (!selectedAlgorithms || selectedAlgorithms.length === 0) if (!selectedAlgorithms || selectedAlgorithms.length === 0)
return trustedAlgorithms return trustedAlgorithms
const selectedAssets = await retrieveDDOListByDIDs( const selectedAssets = await getAssetsFromDids(
selectedAlgorithms, selectedAlgorithms,
[assetChainId], [assetChainId],
cancelToken cancelToken
@ -393,31 +393,3 @@ export async function transformComputeFormToServiceComputeOptions(
return privacy return privacy
} }
export async function checkComputeResourcesValidity(
asset: Asset,
accountId: string,
computeEnvMaxJobDuration: number,
datasetTimeout?: number,
algorithmTimeout?: number,
cancelToken?: CancelToken
): Promise<boolean> {
const jobs = await getComputeJobs(
[asset?.chainId],
accountId,
asset,
cancelToken
)
if (jobs.computeJobs.length <= 0) return false
const inputValues = []
computeEnvMaxJobDuration && inputValues.push(computeEnvMaxJobDuration * 60)
datasetTimeout && inputValues.push(datasetTimeout)
algorithmTimeout && inputValues.push(algorithmTimeout)
const minValue = Math.min(...inputValues)
const jobStartDate = new Date(
parseInt(jobs.computeJobs[0].dateCreated) * 1000
)
jobStartDate.setMinutes(jobStartDate.getMinutes() + Math.floor(minValue / 60))
const currentTime = new Date().getTime() / 1000
return Math.floor(jobStartDate.getTime() / 1000) > currentTime
}

View File

@ -1,5 +1,7 @@
import { getEnsName, getEnsAddress, getEnsProfile } from './ens' import { getEnsName, getEnsAddress, getEnsProfile } from '.'
// TODO: this directly hits the ENS registry, which is not ideal
// so we need to rewrite this to mock responses instead for more reliable test runs.
describe('@utils/ens', () => { describe('@utils/ens', () => {
jest.setTimeout(10000) jest.setTimeout(10000)
jest.retryTimes(2) jest.retryTimes(2)

View File

@ -1,4 +1,4 @@
import { fetchData } from './fetch' import { fetchData } from '../fetch'
const apiUrl = 'https://ens-proxy.oceanprotocol.com/api' const apiUrl = 'https://ens-proxy.oceanprotocol.com/api'

View File

@ -3,12 +3,6 @@ import { Asset } from '@oceanprotocol/lib'
// Boolean value that will be true if we are inside a browser, false otherwise // Boolean value that will be true if we are inside a browser, false otherwise
export const isBrowser = typeof window !== 'undefined' export const isBrowser = typeof window !== 'undefined'
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
export function removeItemFromArray<T>(arr: Array<T>, value: T): Array<T> { export function removeItemFromArray<T>(arr: Array<T>, value: T): Array<T> {
const index = arr.indexOf(value) const index = arr.indexOf(value)
if (index > -1) { if (index > -1) {

View File

@ -1,4 +1,4 @@
import remark from 'remark' import { remark } from 'remark'
import remarkHtml from 'remark-html' import remarkHtml from 'remark-html'
import remarkGfm from 'remark-gfm' import remarkGfm from 'remark-gfm'
@ -6,7 +6,7 @@ export function markdownToHtml(markdown: string): string {
const result = remark() const result = remark()
.use(remarkGfm) .use(remarkGfm)
.use(remarkHtml) // serializes through remark-rehype and rehype-stringify .use(remarkHtml) // serializes through remark-rehype and rehype-stringify
.processSync(markdown).contents .processSync(markdown)
return result.toString() return result.toString()
} }

View File

@ -1,4 +1,4 @@
import { sanitizeUrl } from './url' import { sanitizeUrl } from '.'
describe('@utils/url', () => { describe('@utils/url', () => {
test('sanitizeUrl', () => { test('sanitizeUrl', () => {

View File

@ -1,7 +1,7 @@
import { AllLockedQuery } from 'src/@types/subgraph/AllLockedQuery' import { AllLockedQuery } from '../../src/@types/subgraph/AllLockedQuery'
import { OwnAllocationsQuery } from 'src/@types/subgraph/OwnAllocationsQuery' import { OwnAllocationsQuery } from '../../src/@types/subgraph/OwnAllocationsQuery'
import { NftOwnAllocationQuery } from 'src/@types/subgraph/NftOwnAllocationQuery' import { NftOwnAllocationQuery } from '../../src/@types/subgraph/NftOwnAllocationQuery'
import { OceanLockedQuery } from 'src/@types/subgraph/OceanLockedQuery' import { OceanLockedQuery } from '../../src/@types/subgraph/OceanLockedQuery'
import { gql, OperationResult } from 'urql' import { gql, OperationResult } from 'urql'
import { fetchData, getQueryContext } from './subgraph' import { fetchData, getQueryContext } from './subgraph'
import axios from 'axios' import axios from 'axios'
@ -11,9 +11,6 @@ import {
getNetworkType, getNetworkType,
NetworkType NetworkType
} from '@hooks/useNetworkMetadata' } from '@hooks/useNetworkMetadata'
import { getAssetsFromNftList } from './aquarius'
import { chainIdsSupported } from '../../app.config'
import { Asset } from '@oceanprotocol/lib'
const AllLocked = gql` const AllLocked = gql`
query AllLockedQuery { query AllLockedQuery {
@ -80,6 +77,7 @@ export function getVeChainNetworkIds(assetNetworkIds: number[]): number[] {
}) })
return veNetworkIds return veNetworkIds
} }
export async function getNftOwnAllocation( export async function getNftOwnAllocation(
userAddress: string, userAddress: string,
nftAddress: string, nftAddress: string,
@ -177,17 +175,3 @@ export async function getOwnAllocations(
return allocations return allocations
} }
export async function getOwnAssetsWithAllocation(
networkIds: number[],
userAddress: string
): Promise<Asset[]> {
const allocations = await getOwnAllocations(networkIds, userAddress)
const assets = await getAssetsFromNftList(
allocations.map((x) => x.nftAddress),
chainIdsSupported,
null
)
return assets
}

View File

@ -33,7 +33,7 @@ export async function addCustomNetwork(
const newNetworkData = { const newNetworkData = {
chainId: `0x${network.chainId.toString(16)}`, chainId: `0x${network.chainId.toString(16)}`,
chainName: getNetworkDisplayName(network, network.chainId), chainName: getNetworkDisplayName(network),
nativeCurrency: network.nativeCurrency, nativeCurrency: network.nativeCurrency,
rpcUrls: network.rpc, rpcUrls: network.rpc,
blockExplorerUrls blockExplorerUrls

View File

@ -41,9 +41,7 @@ export default function AssetListTitle({
return ( return (
<h3 className={styles.title}> <h3 className={styles.title}>
<Link href={`/asset/${did || asset?.id}`}> <Link href={`/asset/${did || asset?.id}`}>{assetTitle}</Link>
<a>{assetTitle}</a>
</Link>
</h3> </h3>
) )
} }

View File

@ -35,83 +35,77 @@ export default function AssetTeaser({
return ( return (
<article className={`${styles.teaser} ${styles[type]}`}> <article className={`${styles.teaser} ${styles[type]}`}>
<Link href={`/asset/${asset.id}`}> <Link href={`/asset/${asset.id}`} className={styles.link}>
<a className={styles.link}> <aside className={styles.detailLine}>
<aside className={styles.detailLine}> <AssetType
<AssetType className={styles.typeLabel}
className={styles.typeLabel} type={type}
type={type} accessType={accessType}
accessType={accessType} />
/> <span className={styles.typeLabel}>
<span className={styles.typeLabel}> {datatokens[0]?.symbol.substring(0, 9)}
{datatokens[0]?.symbol.substring(0, 9)} </span>
</span> <NetworkName networkId={asset.chainId} className={styles.typeLabel} />
<NetworkName </aside>
networkId={asset.chainId} <header className={styles.header}>
className={styles.typeLabel} <Dotdotdot tagName="h1" clamp={3} className={styles.title}>
/> {name.slice(0, 200)}
</aside> </Dotdotdot>
<header className={styles.header}> {!noPublisher && <Publisher account={owner} minimal />}
<Dotdotdot tagName="h1" clamp={3} className={styles.title}> </header>
{name.slice(0, 200)} {!noDescription && (
<div className={styles.content}>
<Dotdotdot tagName="p" clamp={3}>
{removeMarkdown(description?.substring(0, 300) || '')}
</Dotdotdot> </Dotdotdot>
{!noPublisher && <Publisher account={owner} minimal />} </div>
</header> )}
{!noDescription && ( {!noPrice && (
<div className={styles.content}> <div className={styles.price}>
<Dotdotdot tagName="p" clamp={3}> {isUnsupportedPricing || !asset.services.length ? (
{removeMarkdown(description?.substring(0, 300) || '')} <strong>No pricing schema available</strong>
</Dotdotdot> ) : (
</div> <Price accessDetails={asset.accessDetails} size="small" />
)} )}
{!noPrice && ( </div>
<div className={styles.price}> )}
{isUnsupportedPricing || !asset.services.length ? ( <footer className={styles.footer}>
<strong>No pricing schema available</strong> {allocated && allocated > 0 ? (
<span className={styles.typeLabel}>
{allocated < 0 ? (
''
) : ( ) : (
<Price accessDetails={asset.accessDetails} size="small" /> <>
<strong>{formatNumber(allocated, locale, '0')}</strong>{' '}
veOCEAN
</>
)} )}
</div> </span>
)} ) : null}
{orders && orders > 0 ? (
<footer className={styles.footer}> <span className={styles.typeLabel}>
{allocated && allocated > 0 ? ( {orders < 0 ? (
<span className={styles.typeLabel}> 'N/A'
{allocated < 0 ? ( ) : (
'' <>
) : ( <strong>{orders}</strong> {orders === 1 ? 'sale' : 'sales'}
<> </>
<strong>{formatNumber(allocated, locale, '0')}</strong>{' '} )}
veOCEAN </span>
</> ) : null}
)} {asset.views && asset.views > 0 ? (
</span> <span className={styles.typeLabel}>
) : null} {asset.views < 0 ? (
{orders && orders > 0 ? ( 'N/A'
<span className={styles.typeLabel}> ) : (
{orders < 0 ? ( <>
'N/A' <strong>{asset.views}</strong>{' '}
) : ( {asset.views === 1 ? 'view' : 'views'}
<> </>
<strong>{orders}</strong> {orders === 1 ? 'sale' : 'sales'} )}
</> </span>
)} ) : null}
</span> </footer>
) : null}
{asset.views && asset.views > 0 ? (
<span className={styles.typeLabel}>
{asset.views < 0 ? (
'N/A'
) : (
<>
<strong>{asset.views}</strong>{' '}
{asset.views === 1 ? 'view' : 'views'}
</>
)}
</span>
) : null}
</footer>
</a>
</Link> </Link>
</article> </article>
) )

View File

@ -2,7 +2,7 @@ import React, { ReactElement, useState } from 'react'
import { useField, useFormikContext } from 'formik' import { useField, useFormikContext } from 'formik'
import UrlInput from '../URLInput' import UrlInput from '../URLInput'
import { InputProps } from '@shared/FormInput' import { InputProps } from '@shared/FormInput'
import { FormPublishData } from 'src/components/Publish/_types' import { FormPublishData } from '@components/Publish/_types'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import ImageInfo from './Info' import ImageInfo from './Info'
import { getContainerChecksum } from '@utils/docker' import { getContainerChecksum } from '@utils/docker'

View File

@ -6,7 +6,7 @@ import FileInfo from '../FilesInput/Info'
import styles from './index.module.css' import styles from './index.module.css'
import Button from '@shared/atoms/Button' import Button from '@shared/atoms/Button'
import { LoggerInstance, ProviderInstance } from '@oceanprotocol/lib' import { LoggerInstance, ProviderInstance } from '@oceanprotocol/lib'
import { FormPublishData } from 'src/components/Publish/_types' import { FormPublishData } from '@components/Publish/_types'
import { getOceanConfig } from '@utils/ocean' import { getOceanConfig } from '@utils/ocean'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import axios from 'axios' import axios from 'axios'

View File

@ -17,7 +17,7 @@ export default function NetworkName({
}): ReactElement { }): ReactElement {
const { networksList } = useNetworkMetadata() const { networksList } = useNetworkMetadata()
const networkData = getNetworkDataById(networksList, networkId) const networkData = getNetworkDataById(networksList, networkId)
const networkName = getNetworkDisplayName(networkData, networkId) const networkName = getNetworkDisplayName(networkData)
return ( return (
<span <span

View File

@ -41,8 +41,8 @@ export default function Publisher({
name name
) : ( ) : (
<> <>
<Link href={`/profile/${account}`}> <Link href={`/profile/${account}`} title="Show profile page.">
<a title="Show profile page.">{name}</a> {name}
</Link> </Link>
</> </>
)} )}

View File

@ -18,10 +18,10 @@ export default function WalletNetworkSwitcher(): ReactElement {
const walletNetworkData = getNetworkDataById(networksList, networkId) const walletNetworkData = getNetworkDataById(networksList, networkId)
const ddoNetworkName = ( const ddoNetworkName = (
<strong>{getNetworkDisplayName(ddoNetworkData, asset.chainId)}</strong> <strong>{getNetworkDisplayName(ddoNetworkData)}</strong>
) )
const walletNetworkName = ( const walletNetworkName = (
<strong>{getNetworkDisplayName(walletNetworkData, networkId)}</strong> <strong>{getNetworkDisplayName(walletNetworkData)}</strong>
) )
async function switchWalletNetwork() { async function switchWalletNetwork() {

View File

@ -1,5 +1,4 @@
import React, { ReactElement, useEffect, useState } from 'react' import React, { ReactElement, useEffect, useState } from 'react'
import { useWeb3 } from '@context/Web3'
import Status from '@shared/atoms/Status' import Status from '@shared/atoms/Status'
import styles from './index.module.css' import styles from './index.module.css'
import WalletNetworkSwitcher from '../WalletNetworkSwitcher' import WalletNetworkSwitcher from '../WalletNetworkSwitcher'

View File

@ -41,10 +41,8 @@ export default function Button({
}) })
return to ? ( return to ? (
<Link href={to}> <Link href={to} className={styleClasses} {...props}>
<a className={styleClasses} {...props}> {children}
{children}
</a>
</Link> </Link>
) : href ? ( ) : href ? (
<a href={href} className={styleClasses} {...props}> <a href={href} className={styleClasses} {...props}>

View File

@ -15,10 +15,12 @@ const Tag = ({ tag, noLinks }: { tag: string; noLinks?: boolean }) => {
return noLinks ? ( return noLinks ? (
<span className={styles.tag}>{tag}</span> <span className={styles.tag}>{tag}</span>
) : ( ) : (
<Link href={`/search?tags=${urlEncodedTag}&sort=_score&sortOrder=desc`}> <Link
<a className={styles.tag} title={tag}> href={`/search?tags=${urlEncodedTag}&sort=_score&sortOrder=desc`}
{tag} className={styles.tag}
</a> title={tag}
>
{tag}
</Link> </Link>
) )
} }

View File

@ -24,24 +24,26 @@ export default function AssetComputeSelection({
<Empty /> <Empty />
) : ( ) : (
assets.map((asset: AssetSelectionAsset) => ( assets.map((asset: AssetSelectionAsset) => (
<Link href={`/asset/${asset.did}`} key={asset.did}> <Link
<a className={styles.row}> href={`/asset/${asset.did}`}
<div className={styles.info}> key={asset.did}
<h3 className={styles.title}> className={styles.row}
<Dotdotdot clamp={1} tagName="span"> >
{asset.name} <div className={styles.info}>
</Dotdotdot> <h3 className={styles.title}>
</h3> <Dotdotdot clamp={1} tagName="span">
<Dotdotdot clamp={1} tagName="code" className={styles.did}> {asset.name}
{asset.symbol} | {asset.did}
</Dotdotdot> </Dotdotdot>
</div> </h3>
<PriceUnit <Dotdotdot clamp={1} tagName="code" className={styles.did}>
price={Number(asset.price)} {asset.symbol} | {asset.did}
size="small" </Dotdotdot>
className={styles.price} </div>
/> <PriceUnit
</a> price={Number(asset.price)}
size="small"
className={styles.price}
/>
</Link> </Link>
)) ))
)} )}

View File

@ -10,7 +10,7 @@ export default function ComputeHistory({
}: { }: {
title: string title: string
children: ReactNode children: ReactNode
refetchJobs?: any refetchJobs?: React.Dispatch<React.SetStateAction<boolean>>
}): ReactElement { }): ReactElement {
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)

View File

@ -13,7 +13,7 @@ import { useCancelToken } from '@hooks/useCancelToken'
import { useIsMounted } from '@hooks/useIsMounted' import { useIsMounted } from '@hooks/useIsMounted'
import styles from './index.module.css' import styles from './index.module.css'
import { useFormikContext } from 'formik' import { useFormikContext } from 'formik'
import { FormPublishData } from 'src/components/Publish/_types' import { FormPublishData } from '@components/Publish/_types'
import { getTokenBalanceFromSymbol } from '@utils/web3' import { getTokenBalanceFromSymbol } from '@utils/web3'
import AssetStats from './AssetStats' import AssetStats from './AssetStats'

View File

@ -3,7 +3,7 @@ import Tooltip from '@shared/atoms/Tooltip'
import { decodeTokenURI } from '@utils/nft' import { decodeTokenURI } from '@utils/nft'
import { useFormikContext } from 'formik' import { useFormikContext } from 'formik'
import React from 'react' import React from 'react'
import { FormPublishData } from 'src/components/Publish/_types' import { FormPublishData } from '@components/Publish/_types'
import Logo from '@shared/atoms/Logo' import Logo from '@shared/atoms/Logo'
import NftTooltip from './NftTooltip' import NftTooltip from './NftTooltip'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -5,7 +5,7 @@ import FormActions from './FormActions'
jest.mock('formik') jest.mock('formik')
describe('src/components/Asset/Edit/FormActions.tsx', () => { describe('@components/Asset/Edit/FormActions.tsx', () => {
it('renders fixed price', () => { it('renders fixed price', () => {
const isValid = true const isValid = true
;(useFormikContext as jest.Mock).mockReturnValue([isValid]) ;(useFormikContext as jest.Mock).mockReturnValue([isValid])

View File

@ -3,7 +3,7 @@ import { Field, Form, useFormikContext } from 'formik'
import Input from '@shared/FormInput' import Input from '@shared/FormInput'
import FormActions from './FormActions' import FormActions from './FormActions'
import { useAsset } from '@context/Asset' import { useAsset } from '@context/Asset'
import { FormPublishData } from 'src/components/Publish/_types' import { FormPublishData } from '@components/Publish/_types'
import { getFileInfo } from '@utils/provider' import { getFileInfo } from '@utils/provider'
import { getFieldContent } from '@utils/form' import { getFieldContent } from '@utils/form'

View File

@ -24,17 +24,11 @@ export default function Links() {
</Fragment> </Fragment>
))} ))}
<Link href="/imprint"> <Link href="/imprint">Imprint</Link>
<a>Imprint</a>
</Link>
{' — '} {' — '}
<Link href="/terms"> <Link href="/terms">Terms</Link>
<a>Terms</a>
</Link>
{' — '} {' — '}
<Link href={privacyPolicySlug}> <Link href={privacyPolicySlug}>Privacy</Link>
<a>Privacy</a>
</Link>
{appConfig?.privacyPreferenceCenter === 'true' && ( {appConfig?.privacyPreferenceCenter === 'true' && (
<> <>
{' — '} {' — '}

View File

@ -6,7 +6,7 @@ import useNetworkMetadata, {
} from '@hooks/useNetworkMetadata' } from '@hooks/useNetworkMetadata'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import styles from './index.module.css' import styles from './index.module.css'
import { FooterStatsValues_globalStatistics as FooterStatsValuesGlobalStatistics } from 'src/@types/subgraph/FooterStatsValues' import { FooterStatsValues_globalStatistics as FooterStatsValuesGlobalStatistics } from '../../../../src/@types/subgraph/FooterStatsValues'
import MarketStatsTotal from './Total' import MarketStatsTotal from './Total'
import { queryGlobalStatistics } from './_queries' import { queryGlobalStatistics } from './_queries'
import { StatsTotal } from './_types' import { StatsTotal } from './_types'

View File

@ -24,8 +24,8 @@ function MenuLink({ item }: { item: MenuItem }) {
: styles.link : styles.link
return ( return (
<Link key={item.name} href={item.link}> <Link key={item.name} href={item.link} className={classes}>
<a className={classes}>{item.name}</a> {item.name}
</Link> </Link>
) )
} }
@ -35,11 +35,9 @@ export default function Menu(): ReactElement {
return ( return (
<nav className={styles.menu}> <nav className={styles.menu}>
<Link href="/"> <Link href="/" className={styles.logo}>
<a className={styles.logo}> <Logo noWordmark />
<Logo noWordmark /> <h1 className={styles.title}>{siteContent?.siteTitle}</h1>
<h1 className={styles.title}>{siteContent?.siteTitle}</h1>
</a>
</Link> </Link>
<ul className={styles.navigation}> <ul className={styles.navigation}>

View File

@ -17,12 +17,7 @@ async function emptySearch() {
const text = searchParams.get('text') const text = searchParams.get('text')
if (text !== ('' || undefined || null)) { if (text !== ('' || undefined || null)) {
const url = await addExistingParamsToUrl(location, [ await addExistingParamsToUrl(location, ['text', 'owner', 'tags'])
'text',
'owner',
'tags'
])
// router.push(`${url}&text=%20`)
} }
} }

View File

@ -5,7 +5,7 @@ import { LoggerInstance } from '@oceanprotocol/lib'
import Price from '@shared/Price' import Price from '@shared/Price'
import Tooltip from '@shared/atoms/Tooltip' import Tooltip from '@shared/atoms/Tooltip'
import AssetTitle from '@shared/AssetListTitle' import AssetTitle from '@shared/AssetListTitle'
import { retrieveDDOListByDIDs } from '@utils/aquarius' import { getAssetsFromDids } from '@utils/aquarius'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing' import { getAccessDetailsForAssets } from '@utils/accessDetailsAndPricing'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
@ -59,7 +59,7 @@ export default function Bookmarks(): ReactElement {
setIsLoading(true) setIsLoading(true)
try { try {
const result = await retrieveDDOListByDIDs( const result = await getAssetsFromDids(
bookmarks, bookmarks,
chainIds, chainIds,
newCancelToken() newCancelToken()

View File

@ -30,24 +30,25 @@ export default function Account({
}, [account?.id]) }, [account?.id])
return ( return (
<Link href={`/profile/${profile?.name || account.id}`}> <Link
<a className={styles.teaser}> href={`/profile/${profile?.name || account.id}`}
{place && <span className={styles.place}>{place}</span>} className={styles.teaser}
<Avatar >
accountId={account.id} {place && <span className={styles.place}>{place}</span>}
className={styles.avatar} <Avatar
src={profile?.avatar} accountId={account.id}
/> className={styles.avatar}
<div> src={profile?.avatar}
<Dotdotdot tagName="h4" clamp={2} className={styles.name}> />
{profile?.name ? profile?.name : accountTruncate(account.id)} <div>
</Dotdotdot> <Dotdotdot tagName="h4" clamp={2} className={styles.name}>
<p className={styles.sales}> {profile?.name ? profile?.name : accountTruncate(account.id)}
<span>{account.totalSales}</span> </Dotdotdot>
{`${account.totalSales === 1 ? ' sale' : ' sales'}`} <p className={styles.sales}>
</p> <span>{account.totalSales}</span>
</div> {`${account.totalSales === 1 ? ' sale' : ' sales'}`}
</a> </p>
</div>
</Link> </Link>
) )
} }

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import styles from './index.module.css' import styles from './index.module.css'
import Loader from '../../../@shared/atoms/Loader' import Loader from '../../../@shared/atoms/Loader'
import { useUserPreferences } from '@context/UserPreferences' import { useUserPreferences } from '@context/UserPreferences'
import Account from 'src/components/Home/TopSales/Account' import Account from '@components/Home/TopSales/Account'
import { UserSales } from '@utils/aquarius' import { UserSales } from '@utils/aquarius'
function LoaderArea() { function LoaderArea() {

View File

@ -1,6 +1,6 @@
import { useUserPreferences } from '@context/UserPreferences' import { useUserPreferences } from '@context/UserPreferences'
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import AccountList from 'src/components/Home/TopSales/AccountList' import AccountList from '@components/Home/TopSales/AccountList'
import { getTopAssetsPublishers, UserSales } from '@utils/aquarius' import { getTopAssetsPublishers, UserSales } from '@utils/aquarius'
import React, { ReactElement, useEffect, useState } from 'react' import React, { ReactElement, useEffect, useState } from 'react'
import styles from './index.module.css' import styles from './index.module.css'

View File

@ -1,7 +1,7 @@
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import { generateBaseQuery, queryMetadata } from '@utils/aquarius' import { generateBaseQuery, queryMetadata } from '@utils/aquarius'
import axios, { CancelToken } from 'axios' import axios, { CancelToken } from 'axios'
import { SortTermOptions } from 'src/@types/aquarius/SearchQuery' import { SortTermOptions } from '../../../../src/@types/aquarius/SearchQuery'
export async function getTopTags( export async function getTopTags(
chainIds: number[], chainIds: number[],
@ -32,7 +32,7 @@ export async function getTopTags(
try { try {
const result = await queryMetadata(query, cancelToken) const result = await queryMetadata(query, cancelToken)
const tagsList = result?.aggregations?.topTags?.buckets.map( const tagsList = result?.aggregations?.topTags?.buckets.map(
(x: { key: any }) => x.key (x: { key: string }) => x.key
) )
return tagsList return tagsList
} catch (error) { } catch (error) {

View File

@ -21,14 +21,13 @@ export default function PrivacyLanguages({
return ( return (
<React.Fragment key={policy.policy}> <React.Fragment key={policy.policy}>
{i > 0 && ' — '} {i > 0 && ' — '}
<Link href={slug}> <Link
<a href={slug}
onClick={() => { onClick={() => {
setPrivacyPolicySlug(slug) setPrivacyPolicySlug(slug)
}} }}
> >
{policy.language} {policy.language}
</a>
</Link> </Link>
</React.Fragment> </React.Fragment>
) )

View File

@ -3,7 +3,7 @@ import Time from '@shared/atoms/Time'
import Button from '@shared/atoms/Button' import Button from '@shared/atoms/Button'
import Modal from '@shared/atoms/Modal' import Modal from '@shared/atoms/Modal'
import External from '@images/external.svg' import External from '@images/external.svg'
import { retrieveAsset } from '@utils/aquarius' import { getAsset } from '@utils/aquarius'
import Results from './Results' import Results from './Results'
import styles from './Details.module.css' import styles from './Details.module.css'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
@ -49,7 +49,7 @@ function DetailsAssets({ job }: { job: ComputeJobMetaData }) {
useEffect(() => { useEffect(() => {
async function getAlgoMetadata() { async function getAlgoMetadata() {
const ddo = await retrieveAsset(job.algoDID, newCancelToken()) const ddo = await getAsset(job.algoDID, newCancelToken())
setAlgoDtSymbol(ddo.datatokens[0].symbol) setAlgoDtSymbol(ddo.datatokens[0].symbol)
setAlgoName(ddo?.metadata.name) setAlgoName(ddo?.metadata.name)
} }

View File

@ -12,7 +12,7 @@ import FormHelp from '@shared/FormInput/Help'
import content from '../../../../../content/pages/history.json' import content from '../../../../../content/pages/history.json'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { useCancelToken } from '@hooks/useCancelToken' import { useCancelToken } from '@hooks/useCancelToken'
import { retrieveAsset } from '@utils/aquarius' import { getAsset } from '@utils/aquarius'
export default function Results({ export default function Results({
job job
@ -21,7 +21,6 @@ export default function Results({
}): ReactElement { }): ReactElement {
const providerInstance = new Provider() const providerInstance = new Provider()
const { accountId, web3 } = useWeb3() const { accountId, web3 } = useWeb3()
const [isLoading, setIsLoading] = useState(false)
const isFinished = job.dateFinished !== null const isFinished = job.dateFinished !== null
const [datasetProvider, setDatasetProvider] = useState<string>() const [datasetProvider, setDatasetProvider] = useState<string>()
@ -29,7 +28,7 @@ export default function Results({
useEffect(() => { useEffect(() => {
async function getAssetMetadata() { async function getAssetMetadata() {
const ddo = await retrieveAsset(job.inputDID[0], newCancelToken()) const ddo = await getAsset(job.inputDID[0], newCancelToken())
setDatasetProvider(ddo.services[0].serviceEndpoint) setDatasetProvider(ddo.services[0].serviceEndpoint)
} }
getAssetMetadata() getAssetMetadata()
@ -61,7 +60,6 @@ export default function Results({
if (!accountId || !job) return if (!accountId || !job) return
try { try {
setIsLoading(true)
const jobResult = await providerInstance.getComputeResultUrl( const jobResult = await providerInstance.getComputeResultUrl(
datasetProvider, datasetProvider,
web3, web3,
@ -72,8 +70,6 @@ export default function Results({
await downloadFileBrowser(jobResult) await downloadFileBrowser(jobResult)
} catch (error) { } catch (error) {
LoggerInstance.error(error.message) LoggerInstance.error(error.message)
} finally {
setIsLoading(false)
} }
} }
@ -97,7 +93,7 @@ export default function Results({
</Button> </Button>
</ListItem> </ListItem>
) : ( ) : (
<ListItem>No results found.</ListItem> <ListItem key={i}>No results found.</ListItem>
) )
)} )}
</ul> </ul>

View File

@ -16,6 +16,7 @@ interface HistoryTab {
} }
const refreshInterval = 10000 // 10 sec. const refreshInterval = 10000 // 10 sec.
function getTabs( function getTabs(
accountId: string, accountId: string,
userAccountId: string, userAccountId: string,

View File

@ -8,7 +8,7 @@ import SuccessConfetti from '@shared/SuccessConfetti'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import Tooltip from '@shared/atoms/Tooltip' import Tooltip from '@shared/atoms/Tooltip'
import AvailableNetworks from 'src/components/Publish/AvailableNetworks' import AvailableNetworks from '@components/Publish/AvailableNetworks'
import Info from '@images/info.svg' import Info from '@images/info.svg'
import Loader from '@shared/atoms/Loader' import Loader from '@shared/atoms/Loader'

View File

@ -1,5 +1,5 @@
import { FormikContextType, useFormikContext } from 'formik' import { FormikContextType, useFormikContext } from 'formik'
import React, { ReactElement, useEffect, useState } from 'react' import React, { ReactElement, useEffect } from 'react'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { FormPublishData } from '../_types' import { FormPublishData } from '../_types'
import { wizardSteps } from '../_constants' import { wizardSteps } from '../_constants'

View File

@ -2,7 +2,7 @@ import React, { ReactElement, useEffect, useState } from 'react'
import styles from './index.module.css' import styles from './index.module.css'
import { FormPublishData } from '../_types' import { FormPublishData } from '../_types'
import { useFormikContext } from 'formik' import { useFormikContext } from 'formik'
import AssetContent from 'src/components/Asset/AssetContent' import AssetContent from '@components/Asset/AssetContent'
import { transformPublishFormToDdo } from '../_utils' import { transformPublishFormToDdo } from '../_utils'
import { ZERO_ADDRESS } from '@oceanprotocol/lib' import { ZERO_ADDRESS } from '@oceanprotocol/lib'

View File

@ -14,6 +14,8 @@ export function Steps({
const { values, setFieldValue, touched, setTouched } = const { values, setFieldValue, touched, setTouched } =
useFormikContext<FormPublishData>() useFormikContext<FormPublishData>()
const isCustomProviderUrl = values?.services?.[0]?.providerUrl.custom
// auto-sync user chainId & account into form data values // auto-sync user chainId & account into form data values
useEffect(() => { useEffect(() => {
if (!chainId || !accountId) return if (!chainId || !accountId) return
@ -41,11 +43,7 @@ export function Steps({
// Auto-change default providerUrl on user network change // Auto-change default providerUrl on user network change
useEffect(() => { useEffect(() => {
if ( if (!values?.user?.chainId || isCustomProviderUrl === true) return
!values?.user?.chainId ||
values?.services[0]?.providerUrl.custom === true
)
return
const config = getOceanConfig(values.user.chainId) const config = getOceanConfig(values.user.chainId)
if (config) { if (config) {
@ -57,12 +55,7 @@ export function Steps({
} }
setTouched({ ...touched, services: [{ providerUrl: { url: true } }] }) setTouched({ ...touched, services: [{ providerUrl: { url: true } }] })
}, [ }, [values?.user?.chainId, isCustomProviderUrl, setFieldValue, setTouched])
values?.user?.chainId,
values?.services[0]?.providerUrl.custom,
setFieldValue,
setTouched
])
const { component } = wizardSteps.filter((stepContent) => { const { component } = wizardSteps.filter((stepContent) => {
return stepContent.step === values.user.stepCurrent return stepContent.step === values.user.stepCurrent

View File

@ -5,7 +5,7 @@ import styles from './index.module.css'
import content from '../../../../content/publish/index.json' import content from '../../../../content/publish/index.json'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import Info from '@images/info.svg' import Info from '@images/info.svg'
import AvailableNetworks from 'src/components/Publish/AvailableNetworks' import AvailableNetworks from '@components/Publish/AvailableNetworks'
export default function Title({ export default function Title({
networkId networkId

View File

@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { allowFixedPricing } from '../../../app.config.js' import { allowFixedPricing } from '../../../app.config'
import { import {
FormPublishData, FormPublishData,
MetadataAlgorithmContainer, MetadataAlgorithmContainer,

View File

@ -1,5 +1,6 @@
import { LoggerInstance } from '@oceanprotocol/lib' import { LoggerInstance } from '@oceanprotocol/lib'
import { import {
escapeEsReservedCharacters,
generateBaseQuery, generateBaseQuery,
getFilterTerm, getFilterTerm,
queryMetadata queryMetadata
@ -26,10 +27,6 @@ export function updateQueryStringParameter(
} }
} }
export function escapeESReservedChars(text: string): string {
return text?.replace(/([!*+\-=<>&|()\\[\]{}^~?:\\/"])/g, '\\$1')
}
export function getSearchQuery( export function getSearchQuery(
chainIds: number[], chainIds: number[],
text?: string, text?: string,
@ -42,7 +39,7 @@ export function getSearchQuery(
serviceType?: string, serviceType?: string,
accessType?: string accessType?: string
): SearchQuery { ): SearchQuery {
text = escapeESReservedChars(text) text = escapeEsReservedCharacters(text)
const emptySearchTerm = text === undefined || text === '' const emptySearchTerm = text === undefined || text === ''
const filters: FilterTerm[] = [] const filters: FilterTerm[] = []
let searchTerm = text || '' let searchTerm = text || ''
@ -150,7 +147,7 @@ export async function getResults(
}, },
chainIds: number[], chainIds: number[],
cancelToken?: CancelToken cancelToken?: CancelToken
): Promise<any> { ): Promise<PagedAssets> {
const { const {
text, text,
owner, owner,

View File

@ -6,7 +6,7 @@ import { UserPreferencesProvider } from '@context/UserPreferences'
import PricesProvider from '@context/Prices' import PricesProvider from '@context/Prices'
import UrqlProvider from '@context/UrqlProvider' import UrqlProvider from '@context/UrqlProvider'
import ConsentProvider from '@context/CookieConsent' import ConsentProvider from '@context/CookieConsent'
import App from 'src/components/App' import App from '../../src/components/App'
import '@oceanprotocol/typographies/css/ocean-typo.css' import '@oceanprotocol/typographies/css/ocean-typo.css'
import '../stylesGlobal/styles.css' import '../stylesGlobal/styles.css'

View File

@ -1,33 +1,30 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "esnext", "baseUrl": ".", // This must be specified if "paths" is.
"module": "ES2020", "target": "es5",
"lib": ["dom", "ES2020"], "lib": ["dom", "dom.iterable", "esnext"],
"resolveJsonModule": true, "allowJs": true,
"moduleResolution": "node", "skipLibCheck": true,
"jsx": "preserve", "strict": false,
"experimentalDecorators": true, "forceConsistentCasingInFileNames": true,
"emitDecoratorMetadata": true,
"noEmit": true, "noEmit": true,
"sourceMap": true, "incremental": true,
"noImplicitAny": true, "esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"paths": { "paths": {
"@components/*": ["./src/components/*"],
"@shared/*": ["./src/components/@shared/*"], "@shared/*": ["./src/components/@shared/*"],
"@hooks/*": ["./src/@hooks/*"], "@hooks/*": ["./src/@hooks/*"],
"@context/*": ["./src/@context/*"], "@context/*": ["./src/@context/*"],
"@images/*": ["./src/@images/*"], "@images/*": ["./src/@images/*"],
"@utils/*": ["./src/@utils/*"], "@utils/*": ["./src/@utils/*"],
"@content/*": ["./@content/*"] "@content/*": ["./@content/*"]
}, }
"baseUrl": ".",
"strict": false,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"skipLibCheck": true,
"allowJs": true,
"esModuleInterop": true,
"incremental": true
}, },
"exclude": ["node_modules", ".next", "*.js"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"include": ["./src/**/*", "./.jest/**/*", "./next-env.d.ts", "./content/**/*"] "exclude": ["node_modules", ".next", "*.js"]
} }