Repository: oceanprotocol/market
Pull request #1698 (2022-09-20 17:56:43)

Bump next from 12.1.6 to 12.3.1
Bumps [next](https://github.com/vercel/next.js) from 12.1.6 to 12.3.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/vercel/next.js/releases">next's releases</a>.</em></p>
<blockquote>
<h2>v12.3.1</h2>
<h3>Core Changes</h3>
<ul>
<li>Update react-server-dom-webpack: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40356">#40356</a></li>
<li>Fix flight manifest to include all chunks: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40365">#40365</a></li>
<li>docs: fix typos: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40342">#40342</a></li>
<li>Fix page url for edge routes in app dir: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40361">#40361</a></li>
<li>Subresource Integrity for App Directory: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/39729">#39729</a></li>
<li>Stop build warning about <code>experimental: { esmExternals: 'loose' }</code>: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40377">#40377</a></li>
<li>Add template and error file types: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/39808">#39808</a></li>
<li>Bump styled-jsx for showing displayName: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40411">#40411</a></li>
<li>fix(<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40388">#40388</a>): <code>next/dynamic</code> should only add default loading without suspense: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40397">#40397</a></li>
<li>Add missing trace for full reload event: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40393">#40393</a></li>
<li>feat(ts): expose <code>AppType</code>: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40391">#40391</a></li>
<li>Update dev watcher to ignore more accurately: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40412">#40412</a></li>
<li>Add failing case for location throw: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40445">#40445</a></li>
<li>Drop legacy RSC handling in client for pages: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40472">#40472</a></li>
<li>fix: eslint no-script-component-in-head error url: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40422">#40422</a></li>
<li>chore: Update swc: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40292">#40292</a></li>
<li>feat(edge): allows configuring Dynamic code execution guard: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/39539">#39539</a></li>
<li>Rename allowDynamic to unstable_allowDynamic: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40496">#40496</a></li>
<li>Don't execute prefetches for bot user agents: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40435">#40435</a></li>
<li>Update semver of eslint-plugin-react: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40246">#40246</a></li>
<li>Clean up startTransition in Link: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40505">#40505</a></li>
<li>docs(README): next.js logo with dark mode: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40223">#40223</a></li>
<li>Passing down original sourcemap for flight client loader: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40508">#40508</a></li>
<li>next/script: make <code>onLoad</code> concurrent rendering resilient: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40191">#40191</a></li>
<li>chore: Update swc: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40520">#40520</a></li>
<li>Add missing feature in next-swc: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40550">#40550</a></li>
<li>Mask Flight Parameters from Middleware: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/39939">#39939</a></li>
<li>Unwrap promise with experimental_use: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40575">#40575</a></li>
<li>fix(next/router): Prevent query delete in routing when next.config basePath option is truthy: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40566">#40566</a></li>
<li>fix(image): handle image imports with high aspect ratio: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40563">#40563</a></li>
<li>fix: loosen webpack compilation with <code>fallbackNodePolyfills: false</code>: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40612">#40612</a></li>
<li>Adding experimentalAdjustFallback feature to font optimization: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40185">#40185</a></li>
<li>fix: handle <code>notFound: true</code> in <code>/</code> with <code>next export</code>: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40592">#40592</a></li>
<li>refactor: split up <code>CONTRIBUTING.md</code>: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40515">#40515</a></li>
<li>Implement SWC transformer for server and client graphs: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40603">#40603</a></li>
<li>Fix edge wasm handling during deploy: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40625">#40625</a></li>
<li>Client directive: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40415">#40415</a></li>
<li>Remove internal client next api detection: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40646">#40646</a></li>
<li>Attach module trace for RSC related errors: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40652">#40652</a></li>
<li>Use createFromFetch instead of createFromReadableStream to fetch Flight: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40656">#40656</a></li>
<li>Change Flight response content type to application/octet-stream: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40665">#40665</a></li>
<li>Send web vitals to Vercel analytics in app: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40669">#40669</a></li>
<li>Refactor fetchServerResponse: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40674">#40674</a></li>
<li>Port page and layout level API assertions to SWC transform: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40653">#40653</a></li>
<li>Ensure smooth scroll is disabled for navigation in new and existing router: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40642">#40642</a></li>
<li>Upgrade to latest React experimental: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40672">#40672</a></li>
<li>Refine error messages: <a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40661">#40661</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/vercel/next.js/commit/980095d59e0f108019415641a724910cd41a7630"><code>980095d</code></a> v12.3.1</li>
<li><a href="https://github.com/vercel/next.js/commit/4901fc73daaecc70215e50b48d04fecd28426772"><code>4901fc7</code></a> v12.3.1-canary.5</li>
<li><a href="https://github.com/vercel/next.js/commit/a03cdc6d350192a5ef960de3b5bc037b691cb8c0"><code>a03cdc6</code></a> docs(examples): fix error connection handling (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40633">#40633</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/5a50a9980ff7d55c443656cf1091f756faac82fa"><code>5a50a99</code></a> Drop legacy RSC server and client extension (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40692">#40692</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/35098a1477752e06030afa2555023138b772c4a4"><code>35098a1</code></a> v12.3.1-canary.4</li>
<li><a href="https://github.com/vercel/next.js/commit/7f9fe8ca30a66c16491c004dc08236d2b3765220"><code>7f9fe8c</code></a> chore: Refactor active-class-name example (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40670">#40670</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/24b20dd13a52ecf602d7ddba5ce01ffba0e8f634"><code>24b20dd</code></a> chore: Migrate with-prefetching example to typescript (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40671">#40671</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/6279dba3b8fe1d6b881145d6079db6ffb26e593d"><code>6279dba</code></a> Avoid direct React client API imports in the server graph (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40686">#40686</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/aed2dc0c853afd1f42eec5e360fb7eab73d5fc93"><code>aed2dc0</code></a> Add handling for static generation in app (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40561">#40561</a>)</li>
<li><a href="https://github.com/vercel/next.js/commit/4a53582e14c313056f29bf8a241c9352dc17db70"><code>4a53582</code></a> fix(image): preload should respect crossOrigin (<a href="https://github-redirect.dependabot.com/vercel/next.js/issues/40676">#40676</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/vercel/next.js/compare/v12.1.6...v12.3.1">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=next&package-manager=npm_and_yarn&previous-version=12.1.6&new-version=12.3.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

vercel[bot]: **The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated |
| :--- | :----- | :------ | :------ |
| **market** | 🔄 Building ([Inspect](https://vercel.com/oceanprotocol/market/5LYXJUA3cVEbduZH3SXLY4EzyW14)) |  | Sep 20, 2022 at 5:56PM (UTC) |



Patch:
diff --git a/.eslintrc b/.eslintrc
index 585180b3..8cf04d8a 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -53,7 +53,8 @@
             "object": true,
             "array": false
           }
-        ]
+        ],
+        "testing-library/no-node-access": "off"
       }
     }
   ]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 72f33fd0..43cc16fb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,13 +23,13 @@ jobs:
         node: ['16']
 
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
         with:
           node-version: ${{ matrix.node }}
 
       - name: Cache node_modules
-        uses: actions/cache@v2
+        uses: actions/cache@v3
         env:
           cache-name: cache-node-modules
         with:
@@ -37,7 +37,7 @@ jobs:
           key: ${{ runner.os }}-${{ matrix.node }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
           restore-keys: ${{ runner.os }}-${{ matrix.node }}-build-${{ env.cache-name }}-
 
-      - run: npm ci --legacy-peer-deps
+      - run: npm ci
       - run: npm run build
 
   test:
@@ -50,13 +50,13 @@ jobs:
         node: ['16']
 
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
         with:
           node-version: ${{ matrix.node }}
 
       - name: Cache node_modules
-        uses: actions/cache@v2
+        uses: actions/cache@v3
         env:
           cache-name: cache-node-modules
         with:
@@ -64,11 +64,11 @@ jobs:
           key: ${{ runner.os }}-${{ matrix.node }}-test-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
           restore-keys: ${{ runner.os }}-${{ matrix.node }}-test-${{ env.cache-name }}-
 
-      - run: npm ci --legacy-peer-deps
+      - run: npm ci
       - run: npm test
 
       - name: Upload coverage artifact
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
           name: coverage-${{ runner.os }}
           path: coverage/
@@ -79,12 +79,12 @@ jobs:
     if: ${{ success() && github.actor != 'dependabot[bot]' }}
 
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
         with:
           node-version: '16'
       - name: Cache node_modules
-        uses: actions/cache@v2
+        uses: actions/cache@v3
         env:
           cache-name: cache-node-modules
         with:
@@ -92,11 +92,11 @@ jobs:
           key: ${{ runner.os }}-coverage-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
           restore-keys: ${{ runner.os }}-coverage-${{ env.cache-name }}-
 
-      - uses: actions/download-artifact@v2
+      - uses: actions/download-artifact@v3
         with:
           name: coverage-${{ runner.os }}
 
-      - run: npm ci --legacy-peer-deps
+      - run: npm ci
       - run: npm run codegen:apollo
 
       - uses: paambaati/codeclimate-action@v3.0.0
@@ -113,13 +113,13 @@ jobs:
         node: ['16']
 
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
         with:
           node-version: ${{ matrix.node }}
 
       - name: Cache node_modules
-        uses: actions/cache@v2
+        uses: actions/cache@v3
         env:
           cache-name: cache-node-modules
         with:
@@ -127,6 +127,6 @@ jobs:
           key: ${{ runner.os }}-${{ matrix.node }}-storybook-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
           restore-keys: ${{ runner.os }}-${{ matrix.node }}-storybook-${{ env.cache-name }}-
 
-      - run: npm ci --legacy-peer-deps
+      - run: npm ci
       - run: npm run pregenerate
       - run: npm run storybook:build
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index fe99c059..d41572ce 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -35,11 +35,11 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
 
       # Initializes the CodeQL tools for scanning.
       - name: Initialize CodeQL
-        uses: github/codeql-action/init@v1
+        uses: github/codeql-action/init@v2
         with:
           languages: ${{ matrix.language }}
           # If you wish to specify custom queries, you can do so here or in a config file.
@@ -50,7 +50,7 @@ jobs:
       # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
       # If this step fails, then you should remove it and run the build manually (see below)
       - name: Autobuild
-        uses: github/codeql-action/autobuild@v1
+        uses: github/codeql-action/autobuild@v2
 
       # ℹ️ Command-line programs to run using the OS shell.
       # 📚 https://git.io/JvXDl
@@ -64,4 +64,4 @@ jobs:
       #   make release
 
       - name: Perform CodeQL Analysis
-        uses: github/codeql-action/analyze@v1
+        uses: github/codeql-action/analyze@v2
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 7f73fb65..7735d668 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -10,9 +10,9 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-node@v2
-      - run: npm ci --legacy-peer-deps
+      - uses: actions/checkout@v3
+      - uses: actions/setup-node@v3
+      - run: npm ci
 
       - run: npm run build:static
         env:
diff --git a/.jest/jest.config.js b/.jest/jest.config.js
index 1facc291..0e3dc230 100644
--- a/.jest/jest.config.js
+++ b/.jest/jest.config.js
@@ -14,7 +14,7 @@ const customJestConfig = {
   moduleDirectories: ['node_modules', '<rootDir>/src'],
   testEnvironment: 'jest-environment-jsdom',
   moduleNameMapper: {
-    '\\.svg': '<rootDir>/.jest/__mocks__/svgrMock.tsx',
+    '^.+\\.(svg)$': '<rootDir>/.jest/__mocks__/svgrMock.tsx',
     // '^@/components/(.*)$': '<rootDir>/components/$1',
     '@shared(.*)$': '<rootDir>/src/components/@shared/$1',
     '@hooks/(.*)$': '<rootDir>/src/@hooks/$1',
diff --git a/README.md b/README.md
index c32d8248..355babc4 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@
 - [🦀 Data Sources](#-data-sources)
   - [Aquarius](#aquarius)
   - [Ocean Protocol Subgraph](#ocean-protocol-subgraph)
-  - [3Box](#3box)
+  - [ENS](#ens)
   - [Purgatory](#purgatory)
   - [Network Metadata](#network-metadata)
 - [👩‍🎤 Storybook](#-storybook)
@@ -194,37 +194,21 @@ function Component() {
 }
 ```
 
-### 3Box
+### ENS
 
-Publishers can create a profile on [3Box Hub](https://www.3box.io/hub) and when found, it will be displayed in the app.
+Publishers can fill their account's [ENS domain](https://ens.domains) profile and when found, it will be displayed in the app.
 
-For this our own [3box-proxy](https://github.com/oceanprotocol/3box-proxy) is used, within the app the utility method `get3BoxProfile()` can be used to get all info:
+For this our own [ens-proxy](https://github.com/oceanprotocol/ens-proxy) is used, within the app the utility method `getEnsProfile()` is called as part of the `useProfile()` hook:
 
 ```tsx
-import get3BoxProfile from '@utils/profile'
+import { useProfile } from '@context/Profile'
 
 function Component() {
-  const [profile, setProfile] = useState<Profile>()
+  const { profile } = useProfile()
 
-  useEffect(() => {
-    if (!account) return
-    const source = axios.CancelToken.source()
-
-    async function get3Box() {
-      const profile = await get3BoxProfile(account, source.token)
-      if (!profile) return
-
-      setProfile(profile)
-    }
-    get3Box()
-
-    return () => {
-      source.cancel()
-    }
-  }, [account])
   return (
     <div>
-      {profile.emoji} {profile.name}
+      {profile.avatar} {profile.name}
     </div>
   )
 }
diff --git a/package-lock.json b/package-lock.json
index 1b96a201..a071dd19 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -30,11 +30,10 @@
         "gray-matter": "^4.0.3",
         "is-url-superb": "^6.1.0",
         "js-cookie": "^3.0.1",
-        "jwt-decode": "^3.1.2",
         "lodash.debounce": "^4.0.8",
         "lodash.omit": "^4.5.0",
         "myetherwallet-blockies": "^0.1.1",
-        "next": "12.1.6",
+        "next": "12.3.1",
         "query-string": "^7.1.1",
         "react": "^18.2.0",
         "react-clipboard.js": "^2.0.16",
@@ -4112,14 +4111,14 @@
       "dev": true
     },
     "node_modules/@next/env": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.6.tgz",
-      "integrity": "sha512-Te/OBDXFSodPU6jlXYPAXpmZr/AkG6DCATAxttQxqOWaq6eDFX25Db3dK0120GZrSZmv4QCe9KsZmJKDbWs4OA=="
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.1.tgz",
+      "integrity": "sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg=="
     },
     "node_modules/@next/swc-android-arm-eabi": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.6.tgz",
-      "integrity": "sha512-BxBr3QAAAXWgk/K7EedvzxJr2dE014mghBSA9iOEAv0bMgF+MRq4PoASjuHi15M2zfowpcRG8XQhMFtxftCleQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz",
+      "integrity": "sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==",
       "cpu": [
         "arm"
       ],
@@ -4132,9 +4131,9 @@
       }
     },
     "node_modules/@next/swc-android-arm64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.1.6.tgz",
-      "integrity": "sha512-EboEk3ROYY7U6WA2RrMt/cXXMokUTXXfnxe2+CU+DOahvbrO8QSWhlBl9I9ZbFzJx28AGB9Yo3oQHCvph/4Lew==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz",
+      "integrity": "sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==",
       "cpu": [
         "arm64"
       ],
@@ -4147,9 +4146,9 @@
       }
     },
     "node_modules/@next/swc-darwin-arm64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.6.tgz",
-      "integrity": "sha512-P0EXU12BMSdNj1F7vdkP/VrYDuCNwBExtRPDYawgSUakzi6qP0iKJpya2BuLvNzXx+XPU49GFuDC5X+SvY0mOw==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz",
+      "integrity": "sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==",
       "cpu": [
         "arm64"
       ],
@@ -4162,9 +4161,9 @@
       }
     },
     "node_modules/@next/swc-darwin-x64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.6.tgz",
-      "integrity": "sha512-9FptMnbgHJK3dRDzfTpexs9S2hGpzOQxSQbe8omz6Pcl7rnEp9x4uSEKY51ho85JCjL4d0tDLBcXEJZKKLzxNg==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz",
+      "integrity": "sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==",
       "cpu": [
         "x64"
       ],
@@ -4176,10 +4175,25 @@
         "node": ">= 10"
       }
     },
+    "node_modules/@next/swc-freebsd-x64": {
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz",
+      "integrity": "sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==",
+      "cpu": [
+        "x64"
+      ],
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">= 10"
+      }
+    },
     "node_modules/@next/swc-linux-arm-gnueabihf": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.6.tgz",
-      "integrity": "sha512-PvfEa1RR55dsik/IDkCKSFkk6ODNGJqPY3ysVUZqmnWMDSuqFtf7BPWHFa/53znpvVB5XaJ5Z1/6aR5CTIqxPw==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz",
+      "integrity": "sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==",
       "cpu": [
         "arm"
       ],
@@ -4192,9 +4206,9 @@
       }
     },
     "node_modules/@next/swc-linux-arm64-gnu": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.6.tgz",
-      "integrity": "sha512-53QOvX1jBbC2ctnmWHyRhMajGq7QZfl974WYlwclXarVV418X7ed7o/EzGY+YVAEKzIVaAB9JFFWGXn8WWo0gQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz",
+      "integrity": "sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==",
       "cpu": [
         "arm64"
       ],
@@ -4207,9 +4221,9 @@
       }
     },
     "node_modules/@next/swc-linux-arm64-musl": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.6.tgz",
-      "integrity": "sha512-CMWAkYqfGdQCS+uuMA1A2UhOfcUYeoqnTW7msLr2RyYAys15pD960hlDfq7QAi8BCAKk0sQ2rjsl0iqMyziohQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz",
+      "integrity": "sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==",
       "cpu": [
         "arm64"
       ],
@@ -4222,9 +4236,9 @@
       }
     },
     "node_modules/@next/swc-linux-x64-gnu": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.6.tgz",
-      "integrity": "sha512-AC7jE4Fxpn0s3ujngClIDTiEM/CQiB2N2vkcyWWn6734AmGT03Duq6RYtPMymFobDdAtZGFZd5nR95WjPzbZAQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz",
+      "integrity": "sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==",
       "cpu": [
         "x64"
       ],
@@ -4237,9 +4251,9 @@
       }
     },
     "node_modules/@next/swc-linux-x64-musl": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.6.tgz",
-      "integrity": "sha512-c9Vjmi0EVk0Kou2qbrynskVarnFwfYIi+wKufR9Ad7/IKKuP6aEhOdZiIIdKsYWRtK2IWRF3h3YmdnEa2WLUag==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz",
+      "integrity": "sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==",
       "cpu": [
         "x64"
       ],
@@ -4252,9 +4266,9 @@
       }
     },
     "node_modules/@next/swc-win32-arm64-msvc": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.6.tgz",
-      "integrity": "sha512-3UTOL/5XZSKFelM7qN0it35o3Cegm6LsyuERR3/OoqEExyj3aCk7F025b54/707HTMAnjlvQK3DzLhPu/xxO4g==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz",
+      "integrity": "sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==",
       "cpu": [
         "arm64"
       ],
@@ -4267,9 +4281,9 @@
       }
     },
     "node_modules/@next/swc-win32-ia32-msvc": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.6.tgz",
-      "integrity": "sha512-8ZWoj6nCq6fI1yCzKq6oK0jE6Mxlz4MrEsRyu0TwDztWQWe7rh4XXGLAa2YVPatYcHhMcUL+fQQbqd1MsgaSDA==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz",
+      "integrity": "sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==",
       "cpu": [
         "ia32"
       ],
@@ -4282,9 +4296,9 @@
       }
     },
     "node_modules/@next/swc-win32-x64-msvc": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.6.tgz",
-      "integrity": "sha512-4ZEwiRuZEicXhXqmhw3+de8Z4EpOLQj/gp+D9fFWo6ii6W1kBkNNvvEx4A90ugppu+74pT1lIJnOuz3A9oQeJA==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz",
+      "integrity": "sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==",
       "cpu": [
         "x64"
       ],
@@ -12499,6 +12513,14 @@
         "url": "https://github.com/sponsors/gregberge"
       }
     },
+    "node_modules/@swc/helpers": {
+      "version": "0.4.11",
+      "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz",
+      "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==",
+      "dependencies": {
+        "tslib": "^2.4.0"
+      }
+    },
     "node_modules/@szmarczak/http-timer": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
@@ -28113,11 +28135,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/jwt-decode": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
-      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
-    },
     "node_modules/keccak": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz",
@@ -31694,14 +31711,16 @@
       "dev": true
     },
     "node_modules/next": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/next/-/next-12.1.6.tgz",
-      "integrity": "sha512-cebwKxL3/DhNKfg9tPZDQmbRKjueqykHHbgaoG4VBRH3AHQJ2HO0dbKFiS1hPhe1/qgc2d/hFeadsbPicmLD+A==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/next/-/next-12.3.1.tgz",
+      "integrity": "sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==",
       "dependencies": {
-        "@next/env": "12.1.6",
-        "caniuse-lite": "^1.0.30001332",
-        "postcss": "8.4.5",
-        "styled-jsx": "5.0.2"
+        "@next/env": "12.3.1",
+        "@swc/helpers": "0.4.11",
+        "caniuse-lite": "^1.0.30001406",
+        "postcss": "8.4.14",
+        "styled-jsx": "5.0.7",
+        "use-sync-external-store": "1.2.0"
       },
       "bin": {
         "next": "dist/bin/next"
@@ -31710,18 +31729,19 @@
         "node": ">=12.22.0"
       },
       "optionalDependencies": {
-        "@next/swc-android-arm-eabi": "12.1.6",
-        "@next/swc-android-arm64": "12.1.6",
-        "@next/swc-darwin-arm64": "12.1.6",
-        "@next/swc-darwin-x64": "12.1.6",
-        "@next/swc-linux-arm-gnueabihf": "12.1.6",
-        "@next/swc-linux-arm64-gnu": "12.1.6",
-        "@next/swc-linux-arm64-musl": "12.1.6",
-        "@next/swc-linux-x64-gnu": "12.1.6",
-        "@next/swc-linux-x64-musl": "12.1.6",
-        "@next/swc-win32-arm64-msvc": "12.1.6",
-        "@next/swc-win32-ia32-msvc": "12.1.6",
-        "@next/swc-win32-x64-msvc": "12.1.6"
+        "@next/swc-android-arm-eabi": "12.3.1",
+        "@next/swc-android-arm64": "12.3.1",
+        "@next/swc-darwin-arm64": "12.3.1",
+        "@next/swc-darwin-x64": "12.3.1",
+        "@next/swc-freebsd-x64": "12.3.1",
+        "@next/swc-linux-arm-gnueabihf": "12.3.1",
+        "@next/swc-linux-arm64-gnu": "12.3.1",
+        "@next/swc-linux-arm64-musl": "12.3.1",
+        "@next/swc-linux-x64-gnu": "12.3.1",
+        "@next/swc-linux-x64-musl": "12.3.1",
+        "@next/swc-win32-arm64-msvc": "12.3.1",
+        "@next/swc-win32-ia32-msvc": "12.3.1",
+        "@next/swc-win32-x64-msvc": "12.3.1"
       },
       "peerDependencies": {
         "fibers": ">= 3.1.0",
@@ -31753,20 +31773,26 @@
       "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
     },
     "node_modules/next/node_modules/postcss": {
-      "version": "8.4.5",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
-      "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
+      "version": "8.4.14",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+      "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        }
+      ],
       "dependencies": {
-        "nanoid": "^3.1.30",
+        "nanoid": "^3.3.4",
         "picocolors": "^1.0.0",
-        "source-map-js": "^1.0.1"
+        "source-map-js": "^1.0.2"
       },
       "engines": {
         "node": "^10 || ^12 || >=14"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/postcss/"
       }
     },
     "node_modules/nice-try": {
@@ -37851,9 +37877,9 @@
       }
     },
     "node_modules/styled-jsx": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz",
-      "integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==",
+      "version": "5.0.7",
+      "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
+      "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
       "engines": {
         "node": ">= 12.0.0"
       },
@@ -39566,7 +39592,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
       "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
-      "peer": true,
       "peerDependencies": {
         "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
       }
@@ -44232,80 +44257,86 @@
       }
     },
     "@next/env": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/env/-/env-12.1.6.tgz",
-      "integrity": "sha512-Te/OBDXFSodPU6jlXYPAXpmZr/AkG6DCATAxttQxqOWaq6eDFX25Db3dK0120GZrSZmv4QCe9KsZmJKDbWs4OA=="
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.1.tgz",
+      "integrity": "sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg=="
     },
     "@next/swc-android-arm-eabi": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.1.6.tgz",
-      "integrity": "sha512-BxBr3QAAAXWgk/K7EedvzxJr2dE014mghBSA9iOEAv0bMgF+MRq4PoASjuHi15M2zfowpcRG8XQhMFtxftCleQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz",
+      "integrity": "sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==",
       "optional": true
     },
     "@next/swc-android-arm64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.1.6.tgz",
-      "integrity": "sha512-EboEk3ROYY7U6WA2RrMt/cXXMokUTXXfnxe2+CU+DOahvbrO8QSWhlBl9I9ZbFzJx28AGB9Yo3oQHCvph/4Lew==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz",
+      "integrity": "sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==",
       "optional": true
     },
     "@next/swc-darwin-arm64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.6.tgz",
-      "integrity": "sha512-P0EXU12BMSdNj1F7vdkP/VrYDuCNwBExtRPDYawgSUakzi6qP0iKJpya2BuLvNzXx+XPU49GFuDC5X+SvY0mOw==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz",
+      "integrity": "sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==",
       "optional": true
     },
     "@next/swc-darwin-x64": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.6.tgz",
-      "integrity": "sha512-9FptMnbgHJK3dRDzfTpexs9S2hGpzOQxSQbe8omz6Pcl7rnEp9x4uSEKY51ho85JCjL4d0tDLBcXEJZKKLzxNg==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz",
+      "integrity": "sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==",
+      "optional": true
+    },
+    "@next/swc-freebsd-x64": {
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz",
+      "integrity": "sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==",
       "optional": true
     },
     "@next/swc-linux-arm-gnueabihf": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.6.tgz",
-      "integrity": "sha512-PvfEa1RR55dsik/IDkCKSFkk6ODNGJqPY3ysVUZqmnWMDSuqFtf7BPWHFa/53znpvVB5XaJ5Z1/6aR5CTIqxPw==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz",
+      "integrity": "sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==",
       "optional": true
     },
     "@next/swc-linux-arm64-gnu": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.6.tgz",
-      "integrity": "sha512-53QOvX1jBbC2ctnmWHyRhMajGq7QZfl974WYlwclXarVV418X7ed7o/EzGY+YVAEKzIVaAB9JFFWGXn8WWo0gQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz",
+      "integrity": "sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==",
       "optional": true
     },
     "@next/swc-linux-arm64-musl": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.6.tgz",
-      "integrity": "sha512-CMWAkYqfGdQCS+uuMA1A2UhOfcUYeoqnTW7msLr2RyYAys15pD960hlDfq7QAi8BCAKk0sQ2rjsl0iqMyziohQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz",
+      "integrity": "sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==",
       "optional": true
     },
     "@next/swc-linux-x64-gnu": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.6.tgz",
-      "integrity": "sha512-AC7jE4Fxpn0s3ujngClIDTiEM/CQiB2N2vkcyWWn6734AmGT03Duq6RYtPMymFobDdAtZGFZd5nR95WjPzbZAQ==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz",
+      "integrity": "sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==",
       "optional": true
     },
     "@next/swc-linux-x64-musl": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.6.tgz",
-      "integrity": "sha512-c9Vjmi0EVk0Kou2qbrynskVarnFwfYIi+wKufR9Ad7/IKKuP6aEhOdZiIIdKsYWRtK2IWRF3h3YmdnEa2WLUag==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz",
+      "integrity": "sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==",
       "optional": true
     },
     "@next/swc-win32-arm64-msvc": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.6.tgz",
-      "integrity": "sha512-3UTOL/5XZSKFelM7qN0it35o3Cegm6LsyuERR3/OoqEExyj3aCk7F025b54/707HTMAnjlvQK3DzLhPu/xxO4g==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz",
+      "integrity": "sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==",
       "optional": true
     },
     "@next/swc-win32-ia32-msvc": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.6.tgz",
-      "integrity": "sha512-8ZWoj6nCq6fI1yCzKq6oK0jE6Mxlz4MrEsRyu0TwDztWQWe7rh4XXGLAa2YVPatYcHhMcUL+fQQbqd1MsgaSDA==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz",
+      "integrity": "sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==",
       "optional": true
     },
     "@next/swc-win32-x64-msvc": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.6.tgz",
-      "integrity": "sha512-4ZEwiRuZEicXhXqmhw3+de8Z4EpOLQj/gp+D9fFWo6ii6W1kBkNNvvEx4A90ugppu+74pT1lIJnOuz3A9oQeJA==",
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz",
+      "integrity": "sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==",
       "optional": true
     },
     "@nodelib/fs.scandir": {
@@ -50602,6 +50633,14 @@
         "@svgr/plugin-svgo": "^6.3.1"
       }
     },
+    "@swc/helpers": {
+      "version": "0.4.11",
+      "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.11.tgz",
+      "integrity": "sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==",
+      "requires": {
+        "tslib": "^2.4.0"
+      }
+    },
     "@szmarczak/http-timer": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
@@ -63001,11 +63040,6 @@
       "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==",
       "dev": true
     },
-    "jwt-decode": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
-      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
-    },
     "keccak": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz",
@@ -65963,26 +65997,29 @@
       "dev": true
     },
     "next": {
-      "version": "12.1.6",
-      "resolved": "https://registry.npmjs.org/next/-/next-12.1.6.tgz",
-      "integrity": "sha512-cebwKxL3/DhNKfg9tPZDQmbRKjueqykHHbgaoG4VBRH3AHQJ2HO0dbKFiS1hPhe1/qgc2d/hFeadsbPicmLD+A==",
-      "requires": {
-        "@next/env": "12.1.6",
-        "@next/swc-android-arm-eabi": "12.1.6",
-        "@next/swc-android-arm64": "12.1.6",
-        "@next/swc-darwin-arm64": "12.1.6",
-        "@next/swc-darwin-x64": "12.1.6",
-        "@next/swc-linux-arm-gnueabihf": "12.1.6",
-        "@next/swc-linux-arm64-gnu": "12.1.6",
-        "@next/swc-linux-arm64-musl": "12.1.6",
-        "@next/swc-linux-x64-gnu": "12.1.6",
-        "@next/swc-linux-x64-musl": "12.1.6",
-        "@next/swc-win32-arm64-msvc": "12.1.6",
-        "@next/swc-win32-ia32-msvc": "12.1.6",
-        "@next/swc-win32-x64-msvc": "12.1.6",
-        "caniuse-lite": "^1.0.30001332",
-        "postcss": "8.4.5",
-        "styled-jsx": "5.0.2"
+      "version": "12.3.1",
+      "resolved": "https://registry.npmjs.org/next/-/next-12.3.1.tgz",
+      "integrity": "sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==",
+      "requires": {
+        "@next/env": "12.3.1",
+        "@next/swc-android-arm-eabi": "12.3.1",
+        "@next/swc-android-arm64": "12.3.1",
+        "@next/swc-darwin-arm64": "12.3.1",
+        "@next/swc-darwin-x64": "12.3.1",
+        "@next/swc-freebsd-x64": "12.3.1",
+        "@next/swc-linux-arm-gnueabihf": "12.3.1",
+        "@next/swc-linux-arm64-gnu": "12.3.1",
+        "@next/swc-linux-arm64-musl": "12.3.1",
+        "@next/swc-linux-x64-gnu": "12.3.1",
+        "@next/swc-linux-x64-musl": "12.3.1",
+        "@next/swc-win32-arm64-msvc": "12.3.1",
+        "@next/swc-win32-ia32-msvc": "12.3.1",
+        "@next/swc-win32-x64-msvc": "12.3.1",
+        "@swc/helpers": "0.4.11",
+        "caniuse-lite": "^1.0.30001406",
+        "postcss": "8.4.14",
+        "styled-jsx": "5.0.7",
+        "use-sync-external-store": "1.2.0"
       },
       "dependencies": {
         "picocolors": {
@@ -65991,13 +66028,13 @@
           "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
         },
         "postcss": {
-          "version": "8.4.5",
-          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz",
-          "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==",
+          "version": "8.4.14",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz",
+          "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==",
           "requires": {
-            "nanoid": "^3.1.30",
+            "nanoid": "^3.3.4",
             "picocolors": "^1.0.0",
-            "source-map-js": "^1.0.1"
+            "source-map-js": "^1.0.2"
           }
         }
       }
@@ -70764,9 +70801,9 @@
       }
     },
     "styled-jsx": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.2.tgz",
-      "integrity": "sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==",
+      "version": "5.0.7",
+      "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
+      "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
       "requires": {}
     },
     "sudo-prompt": {
@@ -72078,7 +72115,6 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
       "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
-      "peer": true,
       "requires": {}
     },
     "utf-8-validate": {
diff --git a/package.json b/package.json
index 2d8f9335..1553815b 100644
--- a/package.json
+++ b/package.json
@@ -43,11 +43,10 @@
     "gray-matter": "^4.0.3",
     "is-url-superb": "^6.1.0",
     "js-cookie": "^3.0.1",
-    "jwt-decode": "^3.1.2",
     "lodash.debounce": "^4.0.8",
     "lodash.omit": "^4.5.0",
     "myetherwallet-blockies": "^0.1.1",
-    "next": "12.1.6",
+    "next": "12.3.1",
     "query-string": "^7.1.1",
     "react": "^18.2.0",
     "react-clipboard.js": "^2.0.16",
diff --git a/src/@context/Profile.tsx b/src/@context/Profile/index.tsx
similarity index 78%
rename from src/@context/Profile.tsx
rename to src/@context/Profile/index.tsx
index bd895c6a..ab6b46f2 100644
--- a/src/@context/Profile.tsx
+++ b/src/@context/Profile/index.tsx
@@ -7,15 +7,18 @@ import React, {
   useCallback,
   ReactNode
 } from 'react'
-import { getUserSales, getUserTokenOrders } from '@utils/subgraph'
-import { useUserPreferences } from './UserPreferences'
+import { getUserTokenOrders } from '@utils/subgraph'
+import { useUserPreferences } from '../UserPreferences'
 import { Asset, LoggerInstance } from '@oceanprotocol/lib'
-import { getDownloadAssets, getPublishedAssets } from '@utils/aquarius'
-import { accountTruncate } from '@utils/web3'
+import {
+  getDownloadAssets,
+  getPublishedAssets,
+  getUserSales
+} from '@utils/aquarius'
 import axios, { CancelToken } from 'axios'
-import get3BoxProfile from '@utils/profile'
 import web3 from 'web3'
-import { useMarketMetadata } from './MarketMetadata'
+import { useMarketMetadata } from '../MarketMetadata'
+import { getEnsProfile } from '@utils/ens'
 
 interface ProfileProviderValue {
   profile: Profile
@@ -32,6 +35,14 @@ const ProfileContext = createContext({} as ProfileProviderValue)
 
 const refreshInterval = 10000 // 10 sec.
 
+const clearedProfile: Profile = {
+  name: null,
+  avatar: null,
+  url: null,
+  description: null,
+  links: null
+}
+
 function ProfileProvider({
   accountId,
   accountEns,
@@ -56,9 +67,9 @@ function ProfileProvider({
   }, [accountId])
 
   //
-  // User profile: ENS + 3Box
+  // User profile: ENS
   //
-  const [profile, setProfile] = useState<Profile>()
+  const [profile, setProfile] = useState<Profile>({ name: accountEns })
 
   useEffect(() => {
     if (!accountEns) return
@@ -66,53 +77,22 @@ function ProfileProvider({
   }, [accountId, accountEns])
 
   useEffect(() => {
-    const clearedProfile: Profile = {
-      name: null,
-      accountEns: null,
-      image: null,
-      description: null,
-      links: null
-    }
-
-    if (!accountId || !isEthAddress) {
+    if (
+      !accountId ||
+      accountId === '0x0000000000000000000000000000000000000000' ||
+      !isEthAddress
+    ) {
       setProfile(clearedProfile)
       return
     }
 
-    const cancelTokenSource = axios.CancelToken.source()
-
     async function getInfo() {
-      setProfile({ name: accountEns || accountTruncate(accountId), accountEns })
-
-      const profile3Box = await get3BoxProfile(
-        accountId,
-        cancelTokenSource.token
-      )
-      if (profile3Box) {
-        const { name, emoji, description, image, links } = profile3Box
-        const newName = `${emoji || ''} ${name || accountTruncate(accountId)}`
-        const newProfile = {
-          name: newName,
-          image,
-          description,
-          links
-        }
-        setProfile((prevState) => ({
-          ...prevState,
-          ...newProfile
-        }))
-        LoggerInstance.log('[profile] Found and set 3box profile.', newProfile)
-      } else {
-        // setProfile(clearedProfile)
-        LoggerInstance.log('[profile] No 3box profile found.')
-      }
+      const profile = await getEnsProfile(accountId)
+      setProfile(profile)
+      LoggerInstance.log(`[profile] ENS metadata for ${accountId}:`, profile)
     }
     getInfo()
-
-    return () => {
-      cancelTokenSource.cancel()
-    }
-  }, [accountId, accountEns, isEthAddress])
+  }, [accountId, isEthAddress])
 
   //
   // PUBLISHED ASSETS
diff --git a/src/@context/Web3.tsx b/src/@context/Web3.tsx
index 7dcf1dd3..71e48f19 100644
--- a/src/@context/Web3.tsx
+++ b/src/@context/Web3.tsx
@@ -13,7 +13,7 @@ import { infuraProjectId as infuraId } from '../../app.config'
 import WalletConnectProvider from '@walletconnect/web3-provider'
 import { LoggerInstance } from '@oceanprotocol/lib'
 import { isBrowser } from '@utils/index'
-import { getEnsName } from '@utils/ens'
+import { getEnsProfile } from '@utils/ens'
 import useNetworkMetadata, {
   getNetworkDataById,
   getNetworkDisplayName,
@@ -32,6 +32,7 @@ interface Web3ProviderValue {
   web3ProviderInfo: IProviderInfo
   accountId: string
   accountEns: string
+  accountEnsAvatar: string
   balance: UserBalance
   networkId: number
   chainId: number
@@ -54,8 +55,6 @@ const web3ModalTheme = {
   hover: 'var(--background-highlight)'
 }
 
-// HEADS UP! We inline-require some packages so the SSR build does not break.
-// We only need them client-side.
 const providerOptions = isBrowser
   ? {
       walletconnect: {
@@ -99,6 +98,7 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
   const [isTestnet, setIsTestnet] = useState<boolean>()
   const [accountId, setAccountId] = useState<string>()
   const [accountEns, setAccountEns] = useState<string>()
+  const [accountEnsAvatar, setAccountEnsAvatar] = useState<string>()
   const [web3Loading, setWeb3Loading] = useState<boolean>(true)
   const [balance, setBalance] = useState<UserBalance>({
     eth: '0'
@@ -192,24 +192,35 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
   }, [accountId, approvedBaseTokens, networkId, web3, networkData])
 
   // -----------------------------------
-  // Helper: Get user ENS name
+  // Helper: Get user ENS info
   // -----------------------------------
-  const getUserEnsName = useCallback(async () => {
+  const getUserEns = useCallback(async () => {
     if (!accountId) return
 
     try {
-      // const accountEns = await getEnsNameWithWeb3(
-      //   accountId,
-      //   web3Provider,
-      //   `${networkId}`
-      // )
-      const accountEns = await getEnsName(accountId)
-      setAccountEns(accountEns)
-      accountEns &&
+      const profile = await getEnsProfile(accountId)
+
+      if (!profile) {
+        setAccountEns(null)
+        setAccountEnsAvatar(null)
+        return
+      }
+
+      setAccountEns(profile.name)
+      LoggerInstance.log(
+        `[web3] ENS name found for ${accountId}:`,
+        profile.name
+      )
+
+      if (profile.avatar) {
+        setAccountEnsAvatar(profile.avatar)
         LoggerInstance.log(
-          `[web3] ENS name found for ${accountId}:`,
-          accountEns
+          `[web3] ENS avatar found for ${accountId}:`,
+          profile.avatar
         )
+      } else {
+        setAccountEnsAvatar(null)
+      }
     } catch (error) {
       LoggerInstance.error('[web3] Error: ', error.message)
     }
@@ -275,11 +286,11 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
   }, [getUserBalance])
 
   // -----------------------------------
-  // Get and set user ENS name
+  // Get and set user ENS info
   // -----------------------------------
   useEffect(() => {
-    getUserEnsName()
-  }, [getUserEnsName])
+    getUserEns()
+  }, [getUserEns])
 
   // -----------------------------------
   // Get and set network metadata
@@ -337,7 +348,7 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
   // -----------------------------------
   async function logout() {
     /* eslint-disable @typescript-eslint/no-explicit-any */
-    if (web3 && web3.currentProvider && (web3.currentProvider as any).close) {
+    if ((web3?.currentProvider as any)?.close) {
       await (web3.currentProvider as any).close()
     }
     /* eslint-enable @typescript-eslint/no-explicit-any */
@@ -402,6 +413,7 @@ function Web3Provider({ children }: { children: ReactNode }): ReactElement {
         web3ProviderInfo,
         accountId,
         accountEns,
+        accountEnsAvatar,
         balance,
         networkId,
         chainId,
diff --git a/src/@hooks/contracts/useNftFactory.ts b/src/@hooks/useNftFactory.ts
similarity index 100%
rename from src/@hooks/contracts/useNftFactory.ts
rename to src/@hooks/useNftFactory.ts
diff --git a/src/@types/Profile.d.ts b/src/@types/Profile.d.ts
index 5649571b..e0c1d1a6 100644
--- a/src/@types/Profile.d.ts
+++ b/src/@types/Profile.d.ts
@@ -1,36 +1,12 @@
 interface ProfileLink {
-  name: string
+  key: string
   value: string
 }
 
 interface Profile {
-  did?: string
-  name?: string
-  accountEns?: string
+  name: string
+  url?: string
+  avatar?: string
   description?: string
-  emoji?: string
-  image?: string
   links?: ProfileLink[]
 }
-
-interface ResponseData3Box {
-  name: string
-  description: string
-  website: string
-  status?: 'error'
-  /* eslint-disable camelcase */
-  proof_did: string
-  proof_twitter: string
-  proof_github: string
-  /* eslint-enable camelcase */
-  emoji: string
-  job: string
-  employer: string
-  location: string
-  memberSince: string
-  image: {
-    contentUrl: {
-      [key: string]: string
-    }
-  }[]
-}
diff --git a/src/@types/viewModels/AccountTeaserVM.d.ts b/src/@types/viewModels/AccountTeaserVM.d.ts
deleted file mode 100644
index 0367993d..00000000
--- a/src/@types/viewModels/AccountTeaserVM.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-interface AccountTeaserVM {
-  address: string
-  nrSales: number
-}
diff --git a/src/@utils/aquarius.ts b/src/@utils/aquarius.ts
index 5ca056db..036139f2 100644
--- a/src/@utils/aquarius.ts
+++ b/src/@utils/aquarius.ts
@@ -9,6 +9,11 @@ import {
 } from '../@types/aquarius/SearchQuery'
 import { transformAssetToAssetSelection } from './assetConvertor'
 
+export interface UserSales {
+  id: string
+  totalSales: number
+}
+
 export const MAXIMUM_NUMBER_OF_PAGES_WITH_RESULTS = 476
 
 export function escapeEsReservedCharacters(value: string): string {
@@ -397,6 +402,40 @@ export async function getTopPublishers(
   }
 }
 
+export async function getTopAssetsPublishers(
+  chainIds: number[],
+  nrItems = 9
+): Promise<UserSales[]> {
+  const publishers: UserSales[] = []
+
+  const result = await getTopPublishers(chainIds, null)
+  const { topPublishers } = result.aggregations
+
+  for (let i = 0; i < topPublishers.buckets.length; i++) {
+    publishers.push({
+      id: topPublishers.buckets[i].key,
+      totalSales: parseInt(topPublishers.buckets[i].totalSales.value)
+    })
+  }
+
+  publishers.sort((a, b) => b.totalSales - a.totalSales)
+
+  return publishers.slice(0, nrItems)
+}
+
+export async function getUserSales(
+  accountId: string,
+  chainIds: number[]
+): Promise<number> {
+  try {
+    const result = await getPublishedAssets(accountId, chainIds, null)
+    const { totalOrders } = result.aggregations
+    return totalOrders.value
+  } catch (error) {
+    LoggerInstance.error('Error getUserSales', error.message)
+  }
+}
+
 export async function getDownloadAssets(
   dtList: string[],
   tokenOrders: OrdersData[],
diff --git a/src/@utils/ens.ts b/src/@utils/ens.ts
index 9f2807bc..b367db96 100644
--- a/src/@utils/ens.ts
+++ b/src/@utils/ens.ts
@@ -1,52 +1,24 @@
-import { gql, OperationContext, OperationResult } from 'urql'
-import { fetchData } from './subgraph'
+import { fetchData } from './fetch'
 
-// make sure to only query for domains owned by account, so domains
-// solely set by 3rd parties like *.gitcoin.eth won't show up
-const UserEnsNames = gql<any>`
-  query UserEnsDomains($accountId: String!) {
-    domains(where: { resolvedAddress: $accountId, owner: $accountId }) {
-      name
-    }
-  }
-`
+const apiUrl = 'https://ens-proxy.oceanprotocol.com/api'
 
-const UserEnsAddress = gql<any>`
-  query UserEnsDomainsAddress($name: String!) {
-    domains(where: { name: $name }) {
-      resolvedAddress {
-        id
-      }
-    }
-  }
-`
+export async function getEnsName(accountId: string): Promise<string> {
+  if (!accountId || accountId === '') return
 
-const ensSubgraphQueryContext: OperationContext = {
-  url: `https://api.thegraph.com/subgraphs/name/ensdomains/ens`,
-  requestPolicy: 'cache-and-network'
+  const data = await fetchData(`${apiUrl}/name?accountId=${accountId}`)
+  return data?.name
 }
 
-export async function getEnsName(accountId: string): Promise<string> {
-  const response: OperationResult<any> = await fetchData(
-    UserEnsNames,
-    { accountId: accountId.toLowerCase() },
-    ensSubgraphQueryContext
-  )
-  if (!response?.data?.domains?.length) return
+export async function getEnsAddress(accountId: string): Promise<string> {
+  if (!accountId || accountId === '' || !accountId.includes('.')) return
 
-  // Default order of response.data.domains seems to be by creation time, from oldest to newest.
-  // Pick the last one as that is what direct web3 calls do.
-  const { name } = response.data.domains.slice(-1)[0]
-  return name
+  const data = await fetchData(`${apiUrl}/address?name=${accountId}`)
+  return data?.address
 }
 
-export async function getEnsAddress(ensName: string): Promise<string> {
-  const response: OperationResult<any> = await fetchData(
-    UserEnsAddress,
-    { name: ensName },
-    ensSubgraphQueryContext
-  )
-  if (!response?.data?.domains?.length) return
-  const { id } = response.data.domains[0].resolvedAddress
-  return id
+export async function getEnsProfile(accountId: string): Promise<Profile> {
+  if (!accountId || accountId === '') return
+
+  const data = await fetchData(`${apiUrl}/profile?address=${accountId}`)
+  return data?.profile
 }
diff --git a/src/@utils/fetch.ts b/src/@utils/fetch.ts
index 2c07ff44..305e06b3 100644
--- a/src/@utils/fetch.ts
+++ b/src/@utils/fetch.ts
@@ -1,15 +1,24 @@
+import { LoggerInstance } from '@oceanprotocol/lib'
 import axios, { AxiosResponse } from 'axios'
 
 export async function fetchData(url: string): Promise<AxiosResponse['data']> {
   try {
     const response = await axios(url)
-
-    if (response.status !== 200) {
-      return console.error('Non-200 response: ' + response.status)
-    }
-
-    return response.data
+    return response?.data
   } catch (error) {
-    console.error('Error parsing json: ' + error.message)
+    if (error.response) {
+      // The request was made and the server responded with a status code
+      // that falls out of the range of 2xx
+      LoggerInstance.error(`Non-200 response from ${url}:`, error.response)
+    } else if (error.request) {
+      // The request was made but no response was received
+      // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
+      // http.ClientRequest in node.js
+      LoggerInstance.error('No response with:', error.request)
+    } else {
+      // Something happened in setting up the request that triggered an Error
+      LoggerInstance.error('Error in setting up request:', error.message)
+    }
+    LoggerInstance.error(error.message)
   }
 }
diff --git a/src/@utils/numbers.ts b/src/@utils/numbers.ts
index 0d31581b..e7b4a432 100644
--- a/src/@utils/numbers.ts
+++ b/src/@utils/numbers.ts
@@ -1,14 +1,5 @@
 import { Decimal } from 'decimal.js'
 
-export function isValidNumber(value: any): boolean {
-  const isUndefinedValue = typeof value === 'undefined'
-  const isNullValue = value === null
-  const isNaNValue = isNaN(Number(value))
-  const isEmptyString = value === ''
-
-  return !isUndefinedValue && !isNullValue && !isNaNValue && !isEmptyString
-}
-
 // Run decimal.js comparison
 // http://mikemcl.github.io/decimal.js/#cmp
 export function compareAsBN(balance: string, price: string): boolean {
diff --git a/src/@utils/pricingFeedback.ts b/src/@utils/pricingFeedback.ts
deleted file mode 100644
index ad49d8cb..00000000
--- a/src/@utils/pricingFeedback.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export function getBuyDTFeedback(dtSymbol: string): { [key: number]: string } {
-  return {
-    1: '1/3 Approving OCEAN ...',
-    2: `2/3 Buying ${dtSymbol} ...`,
-    3: `3/3 ${dtSymbol} bought.`
-  }
-}
-
-export function getSellDTFeedback(dtSymbol: string): { [key: number]: string } {
-  return {
-    1: '1/3 Approving OCEAN ...',
-    2: `2/3 Selling ${dtSymbol} ...`,
-    3: `3/3 ${dtSymbol} sold.`
-  }
-}
diff --git a/src/@utils/profile.ts b/src/@utils/profile.ts
deleted file mode 100644
index b61bc1c4..00000000
--- a/src/@utils/profile.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import axios, { AxiosResponse, CancelToken } from 'axios'
-import jwtDecode from 'jwt-decode'
-
-// https://docs.3box.io/api/rest-api
-const apiUri = 'https://3box.oceanprotocol.com'
-const ipfsUrl = 'https://infura-ipfs.io'
-
-function decodeProof(proofJWT: string) {
-  if (!proofJWT) return
-  const proof = jwtDecode(proofJWT) as any
-  return proof
-}
-
-function getLinks(
-  website: string,
-  twitterProof: string,
-  githubProof: string
-): ProfileLink[] {
-  // Conditionally add links if they exist
-  const links = [
-    ...(website ? [{ name: 'Website', value: website }] : []),
-    ...(twitterProof
-      ? [
-          {
-            name: 'Twitter',
-            value: decodeProof(twitterProof).claim.twitter_handle
-          }
-        ]
-      : []),
-    ...(githubProof
-      ? [{ name: 'GitHub', value: githubProof.split('/')[3] }]
-      : [])
-  ]
-
-  return links
-}
-
-function transformResponse({
-  name,
-  description,
-  website,
-  emoji,
-  image,
-  /* eslint-disable camelcase */
-  proof_twitter,
-  proof_github,
-  proof_did
-}: ResponseData3Box) {
-  /* eslint-enable camelcase */
-  const links = getLinks(website, proof_twitter, proof_github)
-
-  const profile: Profile = {
-    did: decodeProof(proof_did).iss,
-    // Conditionally add profile items if they exist
-    ...(name && { name }),
-    ...(description && { description }),
-    ...(emoji && { emoji }),
-    ...(image && {
-      image: `${ipfsUrl}/ipfs/${
-        image.map(
-          (img: { contentUrl: { [key: string]: string } }) =>
-            img.contentUrl['/']
-        )[0]
-      }`
-    }),
-    ...(links.length && { links })
-  }
-
-  return profile
-}
-
-export default async function get3BoxProfile(
-  accountId: string,
-  cancelToken: CancelToken
-): Promise<Profile> {
-  try {
-    const response = (await axios(`${apiUri}/profile/${accountId}`, {
-      cancelToken
-    })) as AxiosResponse<ResponseData3Box>
-
-    if (
-      !response ||
-      !response.data ||
-      response.status !== 200 ||
-      response.data.status === 'error'
-    )
-      return
-
-    // LoggerInstance.log(`3Box profile found for ${accountId}`, response.data)
-    const profile = transformResponse(response.data)
-    return profile
-    // eslint-disable-next-line no-empty
-  } catch (error) {}
-}
diff --git a/src/@utils/purgatory.ts b/src/@utils/purgatory.ts
index 9d9dae04..81ed2a33 100644
--- a/src/@utils/purgatory.ts
+++ b/src/@utils/purgatory.ts
@@ -1,4 +1,3 @@
-import { Purgatory } from '@oceanprotocol/lib'
 import { fetchData } from './fetch'
 
 const purgatoryUrl = 'https://market-purgatory.oceanprotocol.com/api/'
diff --git a/src/@utils/subgraph.ts b/src/@utils/subgraph.ts
index 41ca897b..c8ac601f 100644
--- a/src/@utils/subgraph.ts
+++ b/src/@utils/subgraph.ts
@@ -6,16 +6,6 @@ import { AssetPreviousOrder } from '../@types/subgraph/AssetPreviousOrder'
 import { OrdersData_orders as OrdersData } from '../@types/subgraph/OrdersData'
 import { OpcFeesQuery as OpcFeesData } from '../@types/subgraph/OpcFeesQuery'
 
-import { getPublishedAssets, getTopPublishers } from '@utils/aquarius'
-export interface UserLiquidity {
-  price: string
-  oceanBalance: string
-}
-
-export interface PriceList {
-  [key: string]: string
-}
-
 const PreviousOrderQuery = gql`
   query AssetPreviousOrder($id: String!, $account: String!) {
     orders(
@@ -153,29 +143,6 @@ export async function getOpcFees(chainId: number) {
   return opcFees
 }
 
-export async function getPreviousOrders(
-  id: string,
-  account: string,
-  assetTimeout: string
-): Promise<string> {
-  const variables = { id, account }
-  const fetchedPreviousOrders: OperationResult<AssetPreviousOrder> =
-    await fetchData(PreviousOrderQuery, variables, null)
-  if (fetchedPreviousOrders.data?.orders?.length === 0) return null
-  if (assetTimeout === '0') {
-    return fetchedPreviousOrders?.data?.orders[0]?.tx
-  } else {
-    const expiry =
-      fetchedPreviousOrders?.data?.orders[0]?.createdTimestamp * 1000 +
-      Number(assetTimeout) * 1000
-    if (Date.now() <= expiry) {
-      return fetchedPreviousOrders?.data?.orders[0]?.tx
-    } else {
-      return null
-    }
-  }
-}
-
 export async function getUserTokenOrders(
   accountId: string,
   chainIds: number[]
@@ -201,40 +168,6 @@ export async function getUserTokenOrders(
   }
 }
 
-export async function getUserSales(
-  accountId: string,
-  chainIds: number[]
-): Promise<number> {
-  try {
-    const result = await getPublishedAssets(accountId, chainIds, null)
-    const { totalOrders } = result.aggregations
-    return totalOrders.value
-  } catch (error) {
-    LoggerInstance.error('Error getUserSales', error.message)
-  }
-}
-
-export async function getTopAssetsPublishers(
-  chainIds: number[],
-  nrItems = 9
-): Promise<AccountTeaserVM[]> {
-  const publishers: AccountTeaserVM[] = []
-
-  const result = await getTopPublishers(chainIds, null)
-  const { topPublishers } = result.aggregations
-
-  for (let i = 0; i < topPublishers.buckets.length; i++) {
-    publishers.push({
-      address: topPublishers.buckets[i].key,
-      nrSales: parseInt(topPublishers.buckets[i].totalSales.value)
-    })
-  }
-
-  publishers.sort((a, b) => b.nrSales - a.nrSales)
-
-  return publishers.slice(0, nrItems)
-}
-
 export async function getOpcsApprovedTokens(
   chainId: number
 ): Promise<TokenInfo[]> {
diff --git a/src/@utils/url.ts b/src/@utils/url.ts
index 5fbfe5f4..0ef9ea78 100644
--- a/src/@utils/url.ts
+++ b/src/@utils/url.ts
@@ -1,10 +1,5 @@
 export function sanitizeUrl(url: string) {
   const u = decodeURI(url).trim().toLowerCase()
-  if (
-    u.startsWith('javascript:') ||
-    u.startsWith('data:') ||
-    u.startsWith('vbscript:')
-  )
-    return 'about:blank'
-  return url
+  const isAllowedUrlScheme = u.startsWith('http://') || u.startsWith('https://')
+  return isAllowedUrlScheme ? url : 'about:blank'
 }
diff --git a/src/components/@shared/AccountList/AccountList.tsx b/src/components/@shared/AccountList/AccountList.tsx
deleted file mode 100644
index fc2a9fa6..00000000
--- a/src/components/@shared/AccountList/AccountList.tsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React, { ReactElement } from 'react'
-import styles from './index.module.css'
-import classNames from 'classnames/bind'
-import Loader from '../atoms/Loader'
-import { useUserPreferences } from '@context/UserPreferences'
-import AccountTeaser from '@shared/AccountTeaser/AccountTeaser'
-
-const cx = classNames.bind(styles)
-
-function LoaderArea() {
-  return (
-    <div className={styles.loaderWrap}>
-      <Loader />
-    </div>
-  )
-}
-
-declare type AccountListProps = {
-  accounts: AccountTeaserVM[]
-  isLoading: boolean
-  className?: string
-}
-
-export default function AccountList({
-  accounts,
-  isLoading,
-  className
-}: AccountListProps): ReactElement {
-  const { chainIds } = useUserPreferences()
-
-  const styleClasses = cx({
-    accountList: true,
-    [className]: className
-  })
-
-  return accounts && (isLoading === undefined || isLoading === false) ? (
-    <>
-      <div className={styleClasses}>
-        {accounts.length > 0 ? (
-          accounts.map((account, index) => (
-            <AccountTeaser
-              accountTeaserVM={account}
-              key={index + 1}
-              place={index + 1}
-            />
-          ))
-        ) : chainIds.length === 0 ? (
-          <div className={styles.empty}>No network selected.</div>
-        ) : (
-          <div className={styles.empty}>No results found.</div>
-        )}
-      </div>
-    </>
-  ) : (
-    <LoaderArea />
-  )
-}
diff --git a/src/components/@shared/AccountTeaser/AccountTeaser.tsx b/src/components/@shared/AccountTeaser/AccountTeaser.tsx
deleted file mode 100644
index 4a20867a..00000000
--- a/src/components/@shared/AccountTeaser/AccountTeaser.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React, { ReactElement, useEffect, useState } from 'react'
-import Dotdotdot from 'react-dotdotdot'
-import Link from 'next/link'
-import styles from './AccountTeaser.module.css'
-import Blockies from '../atoms/Blockies'
-import { useCancelToken } from '@hooks/useCancelToken'
-import get3BoxProfile from '@utils/profile'
-import { accountTruncate } from '@utils/web3'
-
-declare type AccountTeaserProps = {
-  accountTeaserVM: AccountTeaserVM
-  place?: number
-}
-
-export default function AccountTeaser({
-  accountTeaserVM,
-  place
-}: AccountTeaserProps): ReactElement {
-  const [profile, setProfile] = useState<Profile>()
-  const newCancelToken = useCancelToken()
-
-  useEffect(() => {
-    if (!accountTeaserVM) return
-    async function getProfileData() {
-      const profile = await get3BoxProfile(
-        accountTeaserVM.address,
-        newCancelToken()
-      )
-      if (!profile) return
-      setProfile(profile)
-    }
-    getProfileData()
-  }, [accountTeaserVM, newCancelToken])
-
-  return (
-    <Link href={`/profile/${accountTeaserVM.address}`}>
-      <a className={styles.teaser}>
-        {place && <span className={styles.place}>{place}</span>}
-        <Blockies
-          accountId={accountTeaserVM.address}
-          className={styles.blockies}
-          image={profile?.image}
-        />
-        <div>
-          <Dotdotdot tagName="h4" clamp={2} className={styles.name}>
-            {profile?.name
-              ? profile?.name
-              : accountTruncate(accountTeaserVM.address)}
-          </Dotdotdot>
-          <p className={styles.sales}>
-            <span>{accountTeaserVM.nrSales}</span>
-            {`${accountTeaserVM.nrSales === 1 ? ' sale' : ' sales'}`}
-          </p>
-        </div>
-      </a>
-    </Link>
-  )
-}
diff --git a/src/components/@shared/AssetList/AssetComputeList.tsx b/src/components/@shared/AssetList/AssetComputeList.tsx
index 964ac85d..74ee4d33 100644
--- a/src/components/@shared/AssetList/AssetComputeList.tsx
+++ b/src/components/@shared/AssetList/AssetComputeList.tsx
@@ -37,7 +37,7 @@ export default function AssetComputeSelection({
                   </Dotdotdot>
                 </div>
                 <PriceUnit
-                  price={asset.price}
+                  price={Number(asset.price)}
                   size="small"
                   className={styles.price}
                 />
diff --git a/src/components/@shared/AssetType/index.tsx b/src/components/@shared/AssetType/index.tsx
index 565a8727..7d3384c0 100644
--- a/src/components/@shared/AssetType/index.tsx
+++ b/src/components/@shared/AssetType/index.tsx
@@ -29,11 +29,13 @@ export default function AssetType({
         {type === 'dataset' ? 'dataset' : 'algorithm'}
       </div>
 
-      {totalSales ? (
+      {(totalSales || totalSales === 0) && (
         <div className={styles.typeLabel}>
-          {`${totalSales} ${totalSales === 1 ? 'sale' : 'sales'}`}
+          {totalSales < 0
+            ? 'N/A'
+            : `${totalSales} ${totalSales === 1 ? 'sale' : 'sales'}`}
         </div>
-      ) : null}
+      )}
     </div>
   )
 }
diff --git a/src/components/@shared/FormFields/AssetSelection/index.tsx b/src/components/@shared/FormFields/AssetSelection/index.tsx
index 11d391ab..cd73b6b1 100644
--- a/src/components/@shared/FormFields/AssetSelection/index.tsx
+++ b/src/components/@shared/FormFields/AssetSelection/index.tsx
@@ -108,7 +108,7 @@ export default function AssetSelection({
                 </label>
 
                 <PriceUnit
-                  price={asset.price}
+                  price={Number(asset.price)}
                   type={asset.price === '0' ? 'free' : undefined}
                   size="small"
                   className={styles.price}
diff --git a/src/components/@shared/Price/Conversion.tsx b/src/components/@shared/Price/Conversion.tsx
index 5b3ff2bb..625b148d 100644
--- a/src/components/@shared/Price/Conversion.tsx
+++ b/src/components/@shared/Price/Conversion.tsx
@@ -10,7 +10,7 @@ export default function Conversion({
   className,
   hideApproximateSymbol
 }: {
-  price: string // expects price in OCEAN, not wei
+  price: number // expects price in OCEAN, not wei
   symbol: string
   className?: string
   hideApproximateSymbol?: boolean
@@ -28,18 +28,12 @@ export default function Conversion({
   const priceTokenId = getCoingeckoTokenId(symbol)
 
   useEffect(() => {
-    if (
-      !prices ||
-      !price ||
-      price === '0' ||
-      !priceTokenId ||
-      !prices[priceTokenId]
-    ) {
+    if (!prices || !price || !priceTokenId || !prices[priceTokenId]) {
       return
     }
 
     const conversionValue = prices[priceTokenId][currency.toLowerCase()]
-    const converted = conversionValue * Number(price)
+    const converted = conversionValue * price
     const convertedFormatted = formatCurrency(
       converted,
       // No passing of `currency` for non-fiat so symbol conversion
@@ -58,7 +52,7 @@ export default function Conversion({
     setPriceConverted(convertedFormattedHTMLstring)
   }, [price, prices, currency, locale, isFiat, priceTokenId])
 
-  return Number(price) > 0 ? (
+  return price > 0 ? (
     <span
       className={`${styles.conversion} ${className || ''}`}
       title="Approximation based on the current spot price on Coingecko"
diff --git a/src/components/@shared/Price/PriceUnit.tsx b/src/components/@shared/Price/PriceUnit.tsx
index 18dd8891..12a1ea7e 100644
--- a/src/components/@shared/Price/PriceUnit.tsx
+++ b/src/components/@shared/Price/PriceUnit.tsx
@@ -3,10 +3,9 @@ import { formatCurrency } from '@coingecko/cryptoformat'
 import Conversion from './Conversion'
 import styles from './PriceUnit.module.css'
 import { useUserPreferences } from '@context/UserPreferences'
-import Badge from '@shared/atoms/Badge'
 
-export function formatPrice(price: string, locale: string): string {
-  return formatCurrency(Number(price), '', locale, false, {
+export function formatPrice(price: number, locale: string): string {
+  return formatCurrency(price, '', locale, false, {
     // Not exactly clear what `significant figures` are for this library,
     // but setting this seems to give us the formatting we want.
     // See https://github.com/oceanprotocol/market/issues/70
@@ -22,7 +21,7 @@ export default function PriceUnit({
   symbol,
   type
 }: {
-  price: string
+  price: number
   type?: string
   className?: string
   size?: 'small' | 'mini' | 'large'
@@ -38,7 +37,7 @@ export default function PriceUnit({
       ) : (
         <>
           <div>
-            {Number.isNaN(Number(price)) ? '-' : formatPrice(price, locale)}{' '}
+            {Number.isNaN(price) ? '-' : formatPrice(price, locale)}{' '}
             <span className={styles.symbol}>{symbol}</span>
           </div>
           {conversion && <Conversion price={price} symbol={symbol} />}
diff --git a/src/components/@shared/Price/index.tsx b/src/components/@shared/Price/index.tsx
index cff963a6..f555f484 100644
--- a/src/components/@shared/Price/index.tsx
+++ b/src/components/@shared/Price/index.tsx
@@ -16,10 +16,11 @@ export default function Price({
 }): ReactElement {
   const isSupported =
     accessDetails?.type === 'fixed' || accessDetails?.type === 'free'
+  const price = `${orderPriceAndFees?.price || accessDetails?.price}`
 
   return isSupported ? (
     <PriceUnit
-      price={`${orderPriceAndFees?.price || accessDetails?.price}`}
+      price={Number(price)}
       symbol={accessDetails.baseToken?.symbol}
       className={className}
       size={size}
diff --git a/src/components/@shared/Publisher/Add.module.css b/src/components/@shared/Publisher/Add.module.css
deleted file mode 100644
index 3482d355..00000000
--- a/src/components/@shared/Publisher/Add.module.css
+++ /dev/null
@@ -1,7 +0,0 @@
-.add {
-  color: var(--brand-pink);
-}
-
-.linksExternal {
-  composes: linksExternal from './index.module.css';
-}
diff --git a/src/components/@shared/Publisher/Add.tsx b/src/components/@shared/Publisher/Add.tsx
deleted file mode 100644
index f40437fc..00000000
--- a/src/components/@shared/Publisher/Add.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import React, { ReactElement } from 'react'
-import External from '@images/external.svg'
-import styles from './Add.module.css'
-
-export default function Add(): ReactElement {
-  return (
-    <a
-      className={styles.add}
-      href="https://www.3box.io/hub"
-      target="_blank"
-      rel="noreferrer"
-    >
-      Add profile on 3Box <External className={styles.linksExternal} />
-    </a>
-  )
-}
diff --git a/src/components/@shared/Publisher/index.module.css b/src/components/@shared/Publisher/index.module.css
index 93592f59..0bddf6f8 100644
--- a/src/components/@shared/Publisher/index.module.css
+++ b/src/components/@shared/Publisher/index.module.css
@@ -7,10 +7,3 @@
     display: inline-block;
   }
 }
-
-.linksExternal {
-  width: 6px;
-  height: 6px;
-  display: inline-block;
-  fill: var(--color-secondary);
-}
diff --git a/src/components/@shared/Publisher/index.tsx b/src/components/@shared/Publisher/index.tsx
index 0eecd5fa..55589b5b 100644
--- a/src/components/@shared/Publisher/index.tsx
+++ b/src/components/@shared/Publisher/index.tsx
@@ -1,72 +1,47 @@
 import React, { ReactElement, useEffect, useState } from 'react'
 import styles from './index.module.css'
-import classNames from 'classnames/bind'
 import Link from 'next/link'
-import get3BoxProfile from '@utils/profile'
 import { accountTruncate } from '@utils/web3'
-import axios from 'axios'
 import { getEnsName } from '@utils/ens'
 import { useIsMounted } from '@hooks/useIsMounted'
 
-const cx = classNames.bind(styles)
+export interface PublisherProps {
+  account: string
+  minimal?: boolean
+  className?: string
+}
 
 export default function Publisher({
   account,
   minimal,
   className
-}: {
-  account: string
-  minimal?: boolean
-  className?: string
-}): ReactElement {
+}: PublisherProps): ReactElement {
   const isMounted = useIsMounted()
-  const [profile, setProfile] = useState<Profile>()
-  const [name, setName] = useState('')
-  const [accountEns, setAccountEns] = useState<string>()
+  const [name, setName] = useState(accountTruncate(account))
 
   useEffect(() => {
-    if (!account) return
+    if (!account || account === '') return
 
     // set default name on hook
     // to avoid side effect (UI not updating on account's change)
     setName(accountTruncate(account))
 
-    const source = axios.CancelToken.source()
-
     async function getExternalName() {
-      // ENS
       const accountEns = await getEnsName(account)
       if (accountEns && isMounted()) {
-        setAccountEns(accountEns)
         setName(accountEns)
       }
-
-      // 3box
-      const profile = await get3BoxProfile(account, source.token)
-      if (!profile) return
-      setProfile(profile)
-      const { name, emoji } = profile
-      name && setName(`${emoji || ''} ${name}`)
     }
     getExternalName()
-
-    return () => {
-      source.cancel()
-    }
   }, [account, isMounted])
 
-  const styleClasses = cx({
-    publisher: true,
-    [className]: className
-  })
-
   return (
-    <div className={styleClasses}>
+    <div className={`${styles.publisher} ${className || ''}`}>
       {minimal ? (
         name
       ) : (
         <>
-          <Link href={`/profile/${accountEns || account}`}>
+          <Link href={`/profile/${account}`}>
             <a title="Show profile page.">{name}</a>
           </Link>
         </>
diff --git a/src/components/@shared/atoms/Blockies/index.module.css b/src/components/@shared/atoms/Avatar/index.module.css
similarity index 93%
rename from src/components/@shared/atoms/Blockies/index.module.css
rename to src/components/@shared/atoms/Avatar/index.module.css
index 928123b1..26ddad81 100644
--- a/src/components/@shared/atoms/Blockies/index.module.css
+++ b/src/components/@shared/atoms/Avatar/index.module.css
@@ -1,4 +1,4 @@
-.blockies {
+.avatar {
   width: var(--font-size-large);
   height: var(--font-size-large);
   border-radius: 50%;
diff --git a/src/components/@shared/atoms/Avatar/index.stories.tsx b/src/components/@shared/atoms/Avatar/index.stories.tsx
new file mode 100644
index 00000000..eb3b25a3
--- /dev/null
+++ b/src/components/@shared/atoms/Avatar/index.stories.tsx
@@ -0,0 +1,31 @@
+import React from 'react'
+import { ComponentStory, ComponentMeta } from '@storybook/react'
+
+import Avatar, { AvatarProps } from '@shared/atoms/Avatar'
+
+export default {
+  title: 'Component/@shared/atoms/Avatar',
+  component: Avatar
+} as ComponentMeta<typeof Avatar>
+
+const Template: ComponentStory<typeof Avatar> = (args) => <Avatar {...args} />
+
+interface Props {
+  args: AvatarProps
+}
+
+export const DefaultWithBlockies: Props = Template.bind({})
+DefaultWithBlockies.args = {
+  accountId: '0x1234567890123456789012345678901234567890'
+}
+
+export const CustomSource: Props = Template.bind({})
+CustomSource.args = {
+  accountId: '0x1234567890123456789012345678901234567890',
+  src: 'http://placekitten.com/g/300/300'
+}
+
+export const Empty: Props = Template.bind({})
+Empty.args = {
+  accountId: null
+}
diff --git a/src/components/@shared/atoms/Avatar/index.tsx b/src/components/@shared/atoms/Avatar/index.tsx
new file mode 100644
index 00000000..436fbdc2
--- /dev/null
+++ b/src/components/@shared/atoms/Avatar/index.tsx
@@ -0,0 +1,24 @@
+import { toDataUrl } from 'myetherwallet-blockies'
+import React, { ReactElement } from 'react'
+import styles from './index.module.css'
+
+export interface AvatarProps {
+  accountId: string
+  src?: string
+  className?: string
+}
+
+export default function Avatar({
+  accountId,
+  src,
+  className
+}: AvatarProps): ReactElement {
+  return (
+    <img
+      className={`${className || ''} ${styles.avatar} `}
+      src={src || (accountId ? toDataUrl(accountId) : '')}
+      alt="Avatar"
+      aria-hidden="true"
+    />
+  )
+}
diff --git a/src/components/@shared/atoms/Blockies/index.stories.tsx b/src/components/@shared/atoms/Blockies/index.stories.tsx
deleted file mode 100644
index 12137bf5..00000000
--- a/src/components/@shared/atoms/Blockies/index.stories.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react'
-import { ComponentStory, ComponentMeta } from '@storybook/react'
-
-import Blockies, { BlockiesProps } from '@shared/atoms/Blockies'
-
-export default {
-  title: 'Component/@shared/atoms/Blockies',
-  component: Blockies
-} as ComponentMeta<typeof Blockies>
-
-const Template: ComponentStory<typeof Blockies> = (args) => (
-  <Blockies {...args} />
-)
-
-interface Props {
-  args: BlockiesProps
-}
-
-export const Default: Props = Template.bind({})
-Default.args = {
-  accountId: '0x1xxxxxxxxxx3Exxxxxx7xxxxxxxxxxxxF1fd'
-}
diff --git a/src/components/@shared/atoms/Blockies/index.tsx b/src/components/@shared/atoms/Blockies/index.tsx
deleted file mode 100644
index ba3a2307..00000000
--- a/src/components/@shared/atoms/Blockies/index.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { toDataUrl } from 'myetherwallet-blockies'
-import React, { ReactElement } from 'react'
-import styles from './index.module.css'
-
-export interface BlockiesProps {
-  accountId: string
-  className?: string
-  image?: string
-}
-
-export default function Blockies({
-  accountId,
-  className,
-  image
-}: BlockiesProps): ReactElement {
-  if (!accountId) return null
-
-  const blockies = toDataUrl(accountId)
-
-  return (
-    <img
-      className={`${className || ''} ${styles.blockies} `}
-      src={image || blockies}
-      alt="Blockies"
-      aria-hidden="true"
-    />
-  )
-}
diff --git a/src/components/Asset/AssetActions/AssetStats/index.tsx b/src/components/Asset/AssetActions/AssetStats/index.tsx
index 32fc9471..4ee04680 100644
--- a/src/components/Asset/AssetActions/AssetStats/index.tsx
+++ b/src/components/Asset/AssetActions/AssetStats/index.tsx
@@ -7,7 +7,9 @@ export default function AssetStats() {
 
   return (
     <footer className={styles.stats}>
-      {!asset || !asset?.stats || asset?.stats?.orders === 0 ? (
+      {!asset || !asset?.stats || asset?.stats?.orders < 0 ? (
+        'N/A'
+      ) : asset?.stats?.orders === 0 ? (
         'No sales yet'
       ) : (
         <>
diff --git a/src/components/Asset/AssetActions/Compute/PriceOutput.tsx b/src/components/Asset/AssetActions/Compute/PriceOutput.tsx
index f142d038..f8d1de62 100644
--- a/src/components/Asset/AssetActions/Compute/PriceOutput.tsx
+++ b/src/components/Asset/AssetActions/Compute/PriceOutput.tsx
@@ -45,7 +45,7 @@ function Row({
       <div className={styles.type}>{type}</div>
       <div>
         <PriceUnit
-          price={hasPreviousOrder || hasDatatoken ? '0' : `${price}`}
+          price={hasPreviousOrder || hasDatatoken ? 0 : Number(price)}
           symbol={symbol}
           size="small"
           className={styles.price}
@@ -81,7 +81,7 @@ export default function PriceOutput({
   return (
     <div className={styles.priceComponent}>
       You will pay{' '}
-      <PriceUnit price={`${totalPrice}`} symbol={symbol} size="small" />
+      <PriceUnit price={Number(totalPrice)} symbol={symbol} size="small" />
       <Tooltip
         content={
           <div className={styles.calculation}>
diff --git a/src/components/Header/Wallet/Account.tsx b/src/components/Header/Wallet/Account.tsx
index e81f4edd..d19a01f0 100644
--- a/src/components/Header/Wallet/Account.tsx
+++ b/src/components/Header/Wallet/Account.tsx
@@ -4,12 +4,13 @@ import { accountTruncate } from '@utils/web3'
 import Loader from '@shared/atoms/Loader'
 import styles from './Account.module.css'
 import { useWeb3 } from '@context/Web3'
-import Blockies from '@shared/atoms/Blockies'
+import Avatar from '@shared/atoms/Avatar'
 
 // Forward ref for Tippy.js
 // eslint-disable-next-line
 const Account = React.forwardRef((props, ref: any) => {
-  const { accountId, accountEns, web3Modal, connect } = useWeb3()
+  const { accountId, accountEns, accountEnsAvatar, web3Modal, connect } =
+    useWeb3()
 
   async function handleActivation(e: FormEvent<HTMLButtonElement>) {
     // prevent accidentially submitting a form the button might be in
@@ -30,7 +31,7 @@ const Account = React.forwardRef((props, ref: any) => {
       ref={ref}
       onClick={(e) => e.preventDefault()}
     >
-      <Blockies accountId={accountId} />
+      <Avatar accountId={accountId} src={accountEnsAvatar} />
       <span className={styles.address} title={accountId}>
         {accountTruncate(accountEns || accountId)}
       </span>
diff --git a/src/components/Header/Wallet/Details.tsx b/src/components/Header/Wallet/Details.tsx
index e6e55a36..5f0355a3 100644
--- a/src/components/Header/Wallet/Details.tsx
+++ b/src/components/Header/Wallet/Details.tsx
@@ -56,7 +56,7 @@ export default function Details(): ReactElement {
             </span>
             <Conversion
               className={styles.conversion}
-              price={value}
+              price={Number(value)}
               symbol={key}
             />
           </li>
diff --git a/src/components/@shared/AccountTeaser/AccountTeaser.module.css b/src/components/Home/TopSales/Account/index.module.css
similarity index 92%
rename from src/components/@shared/AccountTeaser/AccountTeaser.module.css
rename to src/components/Home/TopSales/Account/index.module.css
index e042e0f7..2e3353c5 100644
--- a/src/components/@shared/AccountTeaser/AccountTeaser.module.css
+++ b/src/components/Home/TopSales/Account/index.module.css
@@ -1,4 +1,4 @@
-.blockies {
+.avatar {
   aspect-ratio: 1/1;
   width: calc(var(--font-size-large) * 2) !important;
   height: calc(var(--font-size-large) * 2) !important;
@@ -8,7 +8,7 @@
 }
 
 .teaser {
-  composes: box from '../atoms/Box.module.css';
+  composes: box from '@shared/atoms/Box.module.css';
   padding: calc(var(--spacer) / 3) calc(var(--spacer) / 2);
   color: var(--color-secondary);
   position: relative;
diff --git a/src/components/Home/TopSales/Account/index.tsx b/src/components/Home/TopSales/Account/index.tsx
new file mode 100644
index 00000000..a5604820
--- /dev/null
+++ b/src/components/Home/TopSales/Account/index.tsx
@@ -0,0 +1,53 @@
+import React, { ReactElement, useEffect, useState } from 'react'
+import Dotdotdot from 'react-dotdotdot'
+import Link from 'next/link'
+import styles from './index.module.css'
+import { accountTruncate } from '@utils/web3'
+import Avatar from '../../../@shared/atoms/Avatar'
+import { getEnsProfile } from '@utils/ens'
+import { UserSales } from '@utils/aquarius'
+
+declare type AccountProps = {
+  account: UserSales
+  place?: number
+}
+
+export default function Account({
+  account,
+  place
+}: AccountProps): ReactElement {
+  const [profile, setProfile] = useState<Profile>()
+
+  useEffect(() => {
+    if (!account?.id) return
+
+    async function getProfileData() {
+      const profile = await getEnsProfile(account.id)
+      if (!profile) return
+      setProfile(profile)
+    }
+    getProfileData()
+  }, [account?.id])
+
+  return (
+    <Link href={`/profile/${profile?.name || account.id}`}>
+      <a className={styles.teaser}>
+        {place && <span className={styles.place}>{place}</span>}
+        <Avatar
+          accountId={account.id}
+          className={styles.avatar}
+          src={profile?.avatar}
+        />
+        <div>
+          <Dotdotdot tagName="h4" clamp={2} className={styles.name}>
+            {profile?.name ? profile?.name : accountTruncate(account.id)}
+          </Dotdotdot>
+          <p className={styles.sales}>
+            <span>{account.totalSales}</span>
+            {`${account.totalSales === 1 ? ' sale' : ' sales'}`}
+          </p>
+        </div>
+      </a>
+    </Link>
+  )
+}
diff --git a/src/components/Home/TopSales/AccountList/index.module.css b/src/components/Home/TopSales/AccountList/index.module.css
new file mode 100644
index 00000000..2a4b6a7a
--- /dev/null
+++ b/src/components/Home/TopSales/AccountList/index.module.css
@@ -0,0 +1,11 @@
+.list {
+  composes: assetList from '@shared/AssetList/index.module.css';
+}
+
+.loaderWrap {
+  composes: loaderWrap from '@shared/AssetList/index.module.css';
+}
+
+.empty {
+  composes: empty from '@shared/AssetList/index.module.css';
+}
diff --git a/src/components/Home/TopSales/AccountList/index.tsx b/src/components/Home/TopSales/AccountList/index.tsx
new file mode 100644
index 00000000..1cbc2f94
--- /dev/null
+++ b/src/components/Home/TopSales/AccountList/index.tsx
@@ -0,0 +1,43 @@
+import React, { ReactElement } from 'react'
+import styles from './index.module.css'
+import Loader from '../../../@shared/atoms/Loader'
+import { useUserPreferences } from '@context/UserPreferences'
+import Account from 'src/components/Home/TopSales/Account'
+import { UserSales } from '@utils/aquarius'
+
+function LoaderArea() {
+  return (
+    <div className={styles.loaderWrap}>
+      <Loader />
+    </div>
+  )
+}
+
+declare type AccountListProps = {
+  accounts: UserSales[]
+  isLoading: boolean
+  className?: string
+}
+
+export default function AccountList({
+  accounts,
+  isLoading
+}: AccountListProps): ReactElement {
+  const { chainIds } = useUserPreferences()
+  const emptyText =
+    chainIds.length === 0 ? 'No network selected.' : 'No results found.'
+
+  return isLoading ? (
+    <LoaderArea />
+  ) : (
+    <div className={styles.list}>
+      {accounts?.length > 0 ? (
+        accounts.map((account, index) => (
+          <Account account={account} key={index} place={index + 1} />
+        ))
+      ) : (
+        <div className={styles.empty}>{emptyText}</div>
+      )}
+    </div>
+  )
+}
diff --git a/src/components/Home/TopSales/index.module.css b/src/components/Home/TopSales/index.module.css
new file mode 100644
index 00000000..d176386d
--- /dev/null
+++ b/src/components/Home/TopSales/index.module.css
@@ -0,0 +1,3 @@
+.section {
+  composes: section from '../index.module.css';
+}
diff --git a/src/components/Home/PublishersWithMostSales.tsx b/src/components/Home/TopSales/index.tsx
similarity index 79%
rename from src/components/Home/PublishersWithMostSales.tsx
rename to src/components/Home/TopSales/index.tsx
index c36b7857..44eb3176 100644
--- a/src/components/Home/PublishersWithMostSales.tsx
+++ b/src/components/Home/TopSales/index.tsx
@@ -1,11 +1,11 @@
 import { useUserPreferences } from '@context/UserPreferences'
 import { LoggerInstance } from '@oceanprotocol/lib'
-import AccountList from '@shared/AccountList/AccountList'
-import { getTopAssetsPublishers } from '@utils/subgraph'
+import AccountList from 'src/components/Home/TopSales/AccountList'
+import { getTopAssetsPublishers, UserSales } from '@utils/aquarius'
 import React, { ReactElement, useEffect, useState } from 'react'
 import styles from './index.module.css'
 
-export default function PublishersWithMostSales({
+export default function TopSales({
   title,
   action
 }: {
@@ -13,14 +13,14 @@ export default function PublishersWithMostSales({
   action?: ReactElement
 }): ReactElement {
   const { chainIds } = useUserPreferences()
-  const [result, setResult] = useState<AccountTeaserVM[]>([])
+  const [result, setResult] = useState<UserSales[]>([])
   const [loading, setLoading] = useState<boolean>()
 
   useEffect(() => {
     async function init() {
       setLoading(true)
       if (chainIds.length === 0) {
-        const result: AccountTeaserVM[] = []
+        const result: UserSales[] = []
         setResult(result)
         setLoading(false)
       } else {
diff --git a/src/components/Home/index.tsx b/src/components/Home/index.tsx
index 8fdd8679..e256ee10 100644
--- a/src/components/Home/index.tsx
+++ b/src/components/Home/index.tsx
@@ -5,11 +5,11 @@ import Bookmarks from './Bookmarks'
 import { generateBaseQuery, queryMetadata } from '@utils/aquarius'
 import { Asset, LoggerInstance } from '@oceanprotocol/lib'
 import { useUserPreferences } from '@context/UserPreferences'
-import styles from './index.module.css'
 import { useIsMounted } from '@hooks/useIsMounted'
 import { useCancelToken } from '@hooks/useCancelToken'
 import { SortTermOptions } from '../../@types/aquarius/SearchQuery'
-import PublishersWithMostSales from './PublishersWithMostSales'
+import TopSales from './TopSales'
+import styles from './index.module.css'
 
 function sortElements(items: Asset[], sorted: string[]) {
   items.sort(function (a, b) {
@@ -136,7 +136,7 @@ export default function HomePage(): ReactElement {
         }
       />
 
-      <PublishersWithMostSales title="Publishers With Most Sales" />
+      <TopSales title="Publishers With Most Sales" />
     </>
   )
 }
diff --git a/src/components/Profile/Header/Account.tsx b/src/components/Profile/Header/Account.tsx
index bbf2a676..0aab2568 100644
--- a/src/components/Profile/Header/Account.tsx
+++ b/src/components/Profile/Header/Account.tsx
@@ -4,9 +4,10 @@ import ExplorerLink from '@shared/ExplorerLink'
 import NetworkName from '@shared/NetworkName'
 import Jellyfish from '@oceanprotocol/art/creatures/jellyfish/jellyfish-grid.svg'
 import Copy from '@shared/atoms/Copy'
-import Blockies from '@shared/atoms/Blockies'
+import Avatar from '@shared/atoms/Avatar'
 import styles from './Account.module.css'
 import { useProfile } from '@context/Profile'
+import { accountTruncate } from '@utils/web3'
 
 export default function Account({
   accountId
@@ -19,28 +20,27 @@ export default function Account({
   return (
     <div className={styles.account}>
       <figure className={styles.imageWrap}>
-        {profile?.image ? (
-          <img
-            src={profile?.image}
+        {accountId ? (
+          <Avatar
+            accountId={accountId}
+            src={profile?.avatar}
             className={styles.image}
-            width="96"
-            height="96"
           />
-        ) : accountId ? (
-          <Blockies accountId={accountId} className={styles.image} />
         ) : (
           <Jellyfish className={styles.image} />
         )}
       </figure>
 
       <div>
-        <h3 className={styles.name}>{profile?.name}</h3>
+        <h3 className={styles.name}>
+          {profile?.name || accountTruncate(accountId)}
+        </h3>
         {accountId && (
           <code
             className={styles.accountId}
-            title={profile?.accountEns ? accountId : null}
+            title={profile?.name ? accountId : null}
           >
-            {profile?.accountEns || accountId} <Copy text={accountId} />
+            {accountId} <Copy text={accountId} />
           </code>
         )}
         <p>
diff --git a/src/components/Profile/Header/PublisherLinks.module.css b/src/components/Profile/Header/PublisherLinks.module.css
index a7970a76..006de698 100644
--- a/src/components/Profile/Header/PublisherLinks.module.css
+++ b/src/components/Profile/Header/PublisherLinks.module.css
@@ -24,5 +24,8 @@
 }
 
 .linksExternal {
-  composes: linksExternal from '@shared/Publisher/index.module.css';
+  width: 6px;
+  height: 6px;
+  display: inline-block;
+  fill: var(--color-secondary);
 }
diff --git a/src/components/Profile/Header/PublisherLinks.tsx b/src/components/Profile/Header/PublisherLinks.tsx
index 023ea408..ca6f97b8 100644
--- a/src/components/Profile/Header/PublisherLinks.tsx
+++ b/src/components/Profile/Header/PublisherLinks.tsx
@@ -6,6 +6,39 @@ import { useProfile } from '@context/Profile'
 
 const cx = classNames.bind(styles)
 
+function getLinkData(link: ProfileLink): { href: string; label: string } {
+  let href, label
+
+  switch (link.key) {
+    case 'url':
+      href = link.value
+      label = 'Website'
+      break
+    case 'com.twitter':
+      href = `https://twitter.com/${link.value}`
+      label = 'Twitter'
+      break
+    case 'com.github':
+      href = `https://github.com/${link.value}`
+      label = 'GitHub'
+      break
+    case 'org.telegram':
+      href = `https://telegram.org/${link.value}`
+      label = 'Telegram'
+      break
+    case 'com.discord':
+      href = `https://discordapp.com/users/${link.value}`
+      label = 'Discord'
+      break
+    case 'com.reddit':
+      href = `https://reddit.com/u/${link.value}`
+      label = 'Reddit'
+      break
+  }
+
+  return { href, label }
+}
+
 export default function PublisherLinks({
   className
 }: {
@@ -21,22 +54,17 @@ export default function PublisherLinks({
   return (
     <div className={styleClasses}>
       {' — '}
-      {profile?.links?.map((link) => {
-        const href =
-          link.name === 'Twitter'
-            ? `https://twitter.com/${link.value}`
-            : link.name === 'GitHub'
-            ? `https://github.com/${link.value}`
-            : link.value.includes('http') // safeguard against urls without protocol defined
-            ? link.value
-            : `//${link.value}`
-
-        return (
-          <a href={href} key={link.name} target="_blank" rel="noreferrer">
-            {link.name} <External className={styles.linksExternal} />
-          </a>
-        )
-      })}
+      {profile?.links?.map((link) => (
+        <a
+          href={getLinkData(link).href}
+          key={link.key}
+          target="_blank"
+          rel="noreferrer"
+        >
+          {getLinkData(link).label}{' '}
+          <External className={styles.linksExternal} />
+        </a>
+      ))}
     </div>
   )
 }
diff --git a/src/components/Profile/Header/Stats.tsx b/src/components/Profile/Header/Stats.tsx
index ac8ba10e..e5a8e3ea 100644
--- a/src/components/Profile/Header/Stats.tsx
+++ b/src/components/Profile/Header/Stats.tsx
@@ -15,7 +15,7 @@ export default function Stats({
   const { chainIds } = useUserPreferences()
   const { assets, assetsTotal, sales } = useProfile()
 
-  const [totalSales, setTotalSales] = useState('0')
+  const [totalSales, setTotalSales] = useState(0)
 
   useEffect(() => {
     if (!assets || !accountId || !chainIds) return
@@ -30,7 +30,7 @@ export default function Stats({
               parseInt(priceInfo.accessDetails.price) * priceInfo.stats.orders
           }
         }
-        setTotalSales(JSON.stringify(count))
+        setTotalSales(count)
       } catch (error) {
         LoggerInstance.error(error.message)
       }
@@ -43,14 +43,21 @@ export default function Stats({
       <NumberUnit
         label="Total Sales"
         value={
-          <Conversion
-            price={totalSales}
-            symbol={'ocean'}
-            hideApproximateSymbol
-          />
+          totalSales > 0 ? (
+            <Conversion
+              price={totalSales}
+              symbol={'ocean'}
+              hideApproximateSymbol
+            />
+          ) : (
+            '0'
+          )
         }
       />
-      <NumberUnit label={`Sale${sales === 1 ? '' : 's'}`} value={sales} />
+      <NumberUnit
+        label={`Sale${sales === 1 ? '' : 's'}`}
+        value={sales < 0 ? 0 : sales}
+      />
       <NumberUnit label="Published" value={assetsTotal} />
     </div>
   )
diff --git a/src/components/Profile/Header/index.tsx b/src/components/Profile/Header/index.tsx
index 15afbe12..a0916560 100644
--- a/src/components/Profile/Header/index.tsx
+++ b/src/components/Profile/Header/index.tsx
@@ -43,8 +43,8 @@ export default function AccountHeader({
         {isDescriptionTextClamped() ? (
           <span className={styles.more} onClick={toogleShowMore}>
             <LinkExternal
-              url={`https://www.3box.io/${accountId}`}
-              text="Read more on 3box"
+              url={`https://app.ens.domains/name/${profile?.name}`}
+              text="Read more on ENS"
             />
           </span>
         ) : (
@@ -56,18 +56,9 @@ export default function AccountHeader({
       </div>
       <div className={styles.meta}>
         Profile data from{' '}
-        {profile?.accountEns && (
-          <>
-            <LinkExternal
-              url={`https://app.ens.domains/name/${profile.accountEns}`}
-              text="ENS"
-            />{' '}
-            &{' '}
-          </>
-        )}
         <LinkExternal
-          url={`https://www.3box.io/${accountId}`}
-          text="3Box Hub"
+          url={`https://app.ens.domains/name/${profile?.name}`}
+          text="ENS"
         />
       </div>
     </div>
diff --git a/src/components/Publish/index.tsx b/src/components/Publish/index.tsx
index 7035128b..9e3cc648 100644
--- a/src/components/Publish/index.tsx
+++ b/src/components/Publish/index.tsx
@@ -13,7 +13,7 @@ import Navigation from './Navigation'
 import { Steps } from './Steps'
 import { FormPublishData } from './_types'
 import { useUserPreferences } from '@context/UserPreferences'
-import useNftFactory from '@hooks/contracts/useNftFactory'
+import useNftFactory from '@hooks/useNftFactory'
 import { ProviderInstance, LoggerInstance, DDO } from '@oceanprotocol/lib'
 import { getOceanConfig } from '@utils/ocean'
 import { validationSchema } from './_validation'
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx
index 4bb1949b..d14b24f9 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/profile/index.tsx
@@ -28,7 +28,7 @@ export default function PageProfile(): ReactElement {
 
       const pathAccount = router.query.account as string
 
-      // Path has ETH addreess
+      // Path has ETH address
       if (web3.utils.isAddress(pathAccount)) {
         const finalAccountId = pathAccount || accountId
         setFinalAccountId(finalAccountId)
@@ -40,6 +40,11 @@ export default function PageProfile(): ReactElement {
         // Path has ENS name
         setFinalAccountEns(pathAccount)
         const resolvedAccountId = await getEnsAddress(pathAccount)
+        if (
+          !resolvedAccountId ||
+          resolvedAccountId === '0x0000000000000000000000000000000000000000'
+        )
+          return
         setFinalAccountId(resolvedAccountId)
       }
     }


Test patch:
diff --git a/src/@utils/ens.test.ts b/src/@utils/ens.test.ts
new file mode 100644
index 00000000..1cf27521
--- /dev/null
+++ b/src/@utils/ens.test.ts
@@ -0,0 +1,64 @@
+import { getEnsName, getEnsAddress, getEnsProfile } from './ens'
+
+describe('@utils/ens', () => {
+  jest.setTimeout(10000)
+  jest.retryTimes(2)
+
+  test('getEnsName', async () => {
+    const ensName = await getEnsName(
+      '0x99840Df5Cb42faBE0Feb8811Aaa4BC99cA6C84e0'
+    )
+    expect(ensName).toBe('jellymcjellyfish.eth')
+  })
+
+  test('getEnsName with invalid address', async () => {
+    const ensName = await getEnsName('0x123')
+    expect(ensName).toBeUndefined()
+  })
+
+  test('getEnsName with empty address', async () => {
+    const ensName = await getEnsName('')
+    expect(ensName).toBeUndefined()
+  })
+
+  test('getEnsName with undefined address', async () => {
+    const ensName = await getEnsName(undefined)
+    expect(ensName).toBeUndefined()
+  })
+
+  test('getEnsAddress', async () => {
+    const ensAddress = await getEnsAddress('jellymcjellyfish.eth')
+    expect(ensAddress).toBe('0x99840Df5Cb42faBE0Feb8811Aaa4BC99cA6C84e0')
+  })
+
+  test('getEnsAddress with invalid address', async () => {
+    const ensAddress = await getEnsAddress('0x123')
+    expect(ensAddress).toBeUndefined()
+  })
+
+  test('getEnsAddress with empty address', async () => {
+    const ensAddress = await getEnsAddress('')
+    expect(ensAddress).toBeUndefined()
+  })
+
+  test('getEnsProfile', async () => {
+    const ensProfile = await getEnsProfile(
+      '0x99840Df5Cb42faBE0Feb8811Aaa4BC99cA6C84e0'
+    )
+    expect(ensProfile).toEqual({
+      avatar:
+        'https://metadata.ens.domains/mainnet/avatar/jellymcjellyfish.eth',
+      links: [
+        { key: 'url', value: 'https://oceanprotocol.com' },
+        { key: 'com.twitter', value: 'oceanprotocol' },
+        { key: 'com.github', value: 'oceanprotocol' }
+      ],
+      name: 'jellymcjellyfish.eth'
+    })
+  })
+
+  test('getEnsProfile with empty address', async () => {
+    const ensProfile = await getEnsProfile('')
+    expect(ensProfile).toBeUndefined()
+  })
+})
diff --git a/src/@utils/url.test.ts b/src/@utils/url.test.ts
new file mode 100644
index 00000000..20afffdb
--- /dev/null
+++ b/src/@utils/url.test.ts
@@ -0,0 +1,9 @@
+import { sanitizeUrl } from './url'
+
+describe('@utils/url', () => {
+  test('sanitizeUrl', () => {
+    expect(sanitizeUrl('http://example.com')).toBe('http://example.com')
+    expect(sanitizeUrl('https://example.com')).toBe('https://example.com')
+    expect(sanitizeUrl('ftp://example.com')).toBe('about:blank')
+  })
+})
diff --git a/src/components/@shared/Publisher/index.test.tsx b/src/components/@shared/Publisher/index.test.tsx
new file mode 100644
index 00000000..ffe21a8d
--- /dev/null
+++ b/src/components/@shared/Publisher/index.test.tsx
@@ -0,0 +1,56 @@
+import React from 'react'
+import { render, screen } from '@testing-library/react'
+import * as axios from 'axios'
+import Publisher from './'
+
+const account = '0x0000000000000000000000000000000000000000'
+
+jest.mock('axios')
+
+describe('Publisher', () => {
+  test('should return correct markup by default', async () => {
+    ;(axios as any).get.mockImplementationOnce(() =>
+      Promise.resolve({ data: { name: 'jellymcjellyfish.eth' } })
+    )
+
+    render(<Publisher account={account} />)
+
+    const element = await screen.findByRole('link')
+    expect(element).toBeInTheDocument()
+    expect(element).toContainHTML('<a')
+    expect(element).toHaveAttribute('href', `/profile/${account}`)
+  })
+
+  test('should truncate account by default', async () => {
+    ;(axios as any).get.mockImplementationOnce(() =>
+      Promise.resolve({ data: { name: null } })
+    )
+
+    render(<Publisher account={account} />)
+
+    const element = await screen.findByText('0x…00000000')
+    expect(element).toBeInTheDocument()
+  })
+
+  test('should return correct markup in minimal state', async () => {
+    ;(axios as any).get.mockImplementationOnce(() =>
+      Promise.resolve({ data: { name: null } })
+    )
+
+    render(<Publisher minimal account={account} />)
+
+    const element = await screen.findByText('0x…00000000')
+    expect(element).not.toHaveAttribute('href')
+  })
+
+  test('should return markup with empty account', async () => {
+    ;(axios as any).get.mockImplementationOnce(() =>
+      Promise.resolve({ data: { name: null } })
+    )
+
+    render(<Publisher account={null} />)
+
+    const element = await screen.findByRole('link')
+    expect(element).toBeInTheDocument()
+  })
+})
diff --git a/src/components/@shared/atoms/Avatar/index.test.tsx b/src/components/@shared/atoms/Avatar/index.test.tsx
new file mode 100644
index 00000000..2d003043
--- /dev/null
+++ b/src/components/@shared/atoms/Avatar/index.test.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+import testRender from '../../../../../.jest/testRender'
+import Avatar from '@shared/atoms/Avatar'
+import { DefaultWithBlockies, CustomSource, Empty } from './index.stories'
+import { render } from '@testing-library/react'
+
+describe('Avatar', () => {
+  testRender(<Avatar {...DefaultWithBlockies.args} />)
+
+  it('renders without crashing with custom source', () => {
+    const { container } = render(<Avatar {...CustomSource.args} />)
+    expect(container.firstChild).toBeInTheDocument()
+  })
+
+  it('renders empty without crashing', () => {
+    const { container } = render(<Avatar {...Empty.args} />)
+    expect(container.firstChild).toBeInTheDocument()
+  })
+})
diff --git a/src/components/@shared/atoms/Blockies/index.test.tsx b/src/components/@shared/atoms/Blockies/index.test.tsx
deleted file mode 100644
index b0bd9443..00000000
--- a/src/components/@shared/atoms/Blockies/index.test.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react'
-import testRender from '../../../../../.jest/testRender'
-import Blockies from '@shared/atoms/Blockies'
-import { Default } from './index.stories'
-
-describe('Blockies', () => {
-  testRender(<Blockies {...Default.args} />)
-})