Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d0fbc18306 | ||
|
|
cbe9395225 | ||
|
|
22aa6319ec |
@@ -13,6 +13,7 @@ module.exports = {
|
||||
files: ['**/*'],
|
||||
rules: {
|
||||
'multiline-comment-style': ['error', 'separate-lines'],
|
||||
'rulesdir/enforce-retry-on-import': 'error',
|
||||
'rulesdir/no-undefined-or': 'error',
|
||||
},
|
||||
},
|
||||
|
||||
32
.github/actions/cache-on-main/action.yml
vendored
32
.github/actions/cache-on-main/action.yml
vendored
@@ -1,32 +0,0 @@
|
||||
name: Cache on main
|
||||
description: caches node_modules/.cache, but only saves from main
|
||||
inputs:
|
||||
path:
|
||||
description: 'A list of files, directories, and wildcard patterns to cache and store'
|
||||
required: true
|
||||
key:
|
||||
description: 'An explicit key for restoring and saving the cache'
|
||||
required: true
|
||||
restore-keys:
|
||||
description: 'An ordered list of keys to use for restoring stale cache if no cache hit occured for key. Note `cache-hit` returns false in this case.'
|
||||
required: false
|
||||
|
||||
# Many build steps have their own caches to improve subsequent build times.
|
||||
# Build tools are configured to cache to node_modules/.cache, so they are cached independently of node_modules.
|
||||
# Caches are saved every run *on main* (by keying on github.run_id), and the most recent available cache is loaded.
|
||||
# Caches are not saved on feature branches because they have limited utility, and extend the runtime of the workflow.
|
||||
# See https://jongleberry.medium.com/speed-up-your-ci-and-dx-with-node-modules-cache-ac8df82b7bb0.
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ inputs.key }}
|
||||
restore-keys: ${{ inputs.restore-keys }}
|
||||
- if: github.ref_name == 'main'
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ inputs.key }}
|
||||
7
.github/actions/setup/action.yml
vendored
7
.github/actions/setup/action.yml
vendored
@@ -10,7 +10,7 @@ runs:
|
||||
with:
|
||||
node-version: 18
|
||||
registry-url: https://registry.npmjs.org
|
||||
# cache is intentionally omitted, as it is faster with yarn v1 to cache node_modules.
|
||||
cache: 'yarn'
|
||||
|
||||
- uses: actions/cache@v3
|
||||
id: install-cache
|
||||
@@ -19,7 +19,7 @@ runs:
|
||||
path: |
|
||||
node_modules
|
||||
!node_modules/.cache
|
||||
key: ${{ runner.os }}-install-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-install-${{ hashFiles('**/yarn.lock') }}
|
||||
- if: steps.install-cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --frozen-lockfile --ignore-scripts
|
||||
shell: bash
|
||||
@@ -55,7 +55,8 @@ runs:
|
||||
# Messages are extracted from source.
|
||||
# A record of source file content hashes and catalogs is maintained in node_modules/.cache/lingui.
|
||||
# Messages are always extracted, but extraction may short-circuit from the custom extractor's cache.
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: i18n-extract-cache
|
||||
with:
|
||||
path: node_modules/.cache
|
||||
key: ${{ runner.os }}-i18n-extract-${{ github.run_id }}
|
||||
|
||||
17
.github/workflows/1-main-to-staging.yml
vendored
17
.github/workflows/1-main-to-staging.yml
vendored
@@ -14,21 +14,6 @@ jobs:
|
||||
environment:
|
||||
name: push/staging
|
||||
steps:
|
||||
- name: Check test status
|
||||
uses: actions/github-script@v6.4.1
|
||||
with:
|
||||
script: |
|
||||
const statuses = await github.rest.repos.listCommitStatusesForRef({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
ref: context.sha
|
||||
})
|
||||
const status = statuses.data.find(status => status.context === 'Test / promotion')?.state || 'missing'
|
||||
core.info('Status: ' + status)
|
||||
if (status !== 'success') {
|
||||
core.setFailed('"Test / promotion" must be successful before pushing')
|
||||
}
|
||||
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_SERVICE_ACCESS_TOKEN }}
|
||||
@@ -59,7 +44,7 @@ jobs:
|
||||
- name: Add translations
|
||||
run: |
|
||||
rm src/locales/en-US.po
|
||||
git add -f src/locales/*.po
|
||||
git add src/locales/*.po
|
||||
git commit -m 'ci(t9n): download translations from crowdin'
|
||||
|
||||
- name: Add CODEOWNERS
|
||||
|
||||
15
.github/workflows/2-deploy-to-staging.yml
vendored
15
.github/workflows/2-deploy-to-staging.yml
vendored
@@ -10,23 +10,23 @@ jobs:
|
||||
environment:
|
||||
name: deploy/staging
|
||||
steps:
|
||||
- uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
- name: Send Slack message that deploy is starting
|
||||
uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
continue-on-error: true
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"text": "Deploy _started_ for ${{ github.ref_name }}"
|
||||
"text": "Staging deploy started for branch: ${{ github.ref_name }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- run: yarn prepare
|
||||
- run: yarn build
|
||||
env:
|
||||
REACT_APP_STAGING: 1
|
||||
|
||||
- name: Update Cloudflare Pages deployment
|
||||
id: pages-deployment
|
||||
uses: cloudflare/pages-action@364c7ca09a4b57837c5967871d64a2c31adb8c0d
|
||||
@@ -38,19 +38,18 @@ jobs:
|
||||
githubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Cloudflare uses `main` as the default production branch, so we push using the `main` branch so that it can be aliased by a custom domain.
|
||||
branch: main
|
||||
|
||||
- uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
- name: Send Slack message about deployment outcome
|
||||
uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
continue-on-error: true
|
||||
if: always()
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"text": "Deploy *${{ steps.pages-deployment.outcome }}* for ${{ github.ref_name }}"
|
||||
"text": "Staging deploy **${{ steps.pages-deployment.outcome }}** for: ${{ github.ref_name }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
- name: Upload source maps to Sentry
|
||||
uses: getsentry/action-release@bd5f874fcda966ba48139b0140fb3ec0cb3aabdd
|
||||
continue-on-error: true
|
||||
|
||||
16
.github/workflows/4-deploy-to-prod.yml
vendored
16
.github/workflows/4-deploy-to-prod.yml
vendored
@@ -10,21 +10,21 @@ jobs:
|
||||
environment:
|
||||
name: deploy/prod
|
||||
steps:
|
||||
- uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
- name: Send Slack message that build is starting
|
||||
uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
continue-on-error: true
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"text": "Deploy _started_ for ${{ github.ref_name }}"
|
||||
"text": "Production deploy started for branch: ${{ github.ref_name }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- run: yarn prepare
|
||||
- run: yarn build
|
||||
|
||||
- name: Bump and tag
|
||||
id: github-tag-action
|
||||
uses: mathieudutour/github-tag-action@d745f2e74aaf1ee82e747b181f7a0967978abee0
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
with:
|
||||
cidv0: ${{ steps.pinata.outputs.hash }}
|
||||
|
||||
- name: Publish release
|
||||
- name: Release
|
||||
uses: actions/create-release@v1.1.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -86,18 +86,18 @@ jobs:
|
||||
# Cloudflare uses `main` as the default production branch, so we push using the `main` branch so that it can be aliased by a custom domain.
|
||||
branch: main
|
||||
|
||||
- uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
- name: Send Slack message about deployment outcome
|
||||
uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
continue-on-error: true
|
||||
if: always()
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"text": "Deploy *${{ steps.pages-deployment.outcome }}* for ${{ github.ref_name }}"
|
||||
"text": "Production deploy **${{ steps.pages-deployment.outcome }}** for: ${{ github.ref_name }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|
||||
|
||||
- name: Upload source maps to Sentry
|
||||
uses: getsentry/action-release@4744f6a65149f441c5f396d5b0877307c0db52c7
|
||||
continue-on-error: true
|
||||
|
||||
33
.github/workflows/crowdin-sync.yaml
vendored
Normal file
33
.github/workflows/crowdin-sync.yaml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Crowdin Download
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Download translations every hour.
|
||||
# This is not done as part of the build so that builds remain reproducible.
|
||||
- cron: '0 * * * *'
|
||||
# manual trigger
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
download-translations:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- run: yarn i18n:extract
|
||||
|
||||
- name: Download Crowdin translations
|
||||
uses: crowdin/github-action@3133cc916c35590475cf6705f482fb653d8e36e9
|
||||
with:
|
||||
upload_sources: false
|
||||
download_translations: true
|
||||
project_id: 458284
|
||||
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN_SECRET }}
|
||||
source: 'src/locales/en-US.po'
|
||||
translation: 'src/locales/%locale%.po'
|
||||
create_pull_request: true
|
||||
pull_request_title: 'chore(i18n): new Crowdin translations'
|
||||
localization_branch_name: l10n_crowdin
|
||||
commit_message: 'chore(i18n): synchronize translations from crowdin [skip ci]'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Slack notification on pushes to releases/*
|
||||
name: Slack notifications for releases/* merges
|
||||
|
||||
# This CI job will push notifications to Slack whenever code is merged into any releases/* branch
|
||||
#
|
||||
@@ -25,6 +25,7 @@ on:
|
||||
|
||||
jobs:
|
||||
notify-slack:
|
||||
name: 'Emit Slack notification(s)'
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: notify/releases
|
||||
@@ -44,7 +45,9 @@ jobs:
|
||||
| awk '{print substr($0,0,3000);}' \
|
||||
> /tmp/parsed_github_context
|
||||
echo "SLACK_COMMITS=$(cat /tmp/parsed_github_context)" >> "$GITHUB_OUTPUT"
|
||||
- uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
- name: Send custom JSON data to Slack workflow
|
||||
id: slack
|
||||
uses: slackapi/slack-github-action@007b2c3c751a190b6f0f040e47ed024deaa72844
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
|
||||
88
.github/workflows/test.yml
vendored
88
.github/workflows/test.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: Test
|
||||
|
||||
# Many build steps have their own caches, so each job has its own cache to improve subsequent build times.
|
||||
# Build tools are configured to cache to node_modules/.cache, so they are cached independently of node_modules.
|
||||
# Build tools are configured to cache cache to node_modules/.cache, so this is cached independently of node_modules.
|
||||
# Caches are saved every run (by keying on github.run_id), and the most recent available cache is loaded.
|
||||
# See https://jongleberry.medium.com/speed-up-your-ci-and-dx-with-node-modules-cache-ac8df82b7bb0.
|
||||
|
||||
@@ -9,8 +9,9 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/staging
|
||||
pull_request:
|
||||
# manual trigger
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
@@ -18,11 +19,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: eslint-cache
|
||||
with:
|
||||
path: node_modules/.cache
|
||||
key: ${{ runner.os }}-eslint-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-eslint-
|
||||
key: ${{ runner.os }}-eslint-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-eslint-${{ hashFiles('**/yarn.lock') }}-
|
||||
- run: yarn lint
|
||||
- if: failure() && github.ref_name == 'main'
|
||||
uses: ./.github/actions/report
|
||||
@@ -35,11 +37,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: tsc-cache
|
||||
with:
|
||||
path: node_modules/.cache
|
||||
key: ${{ runner.os }}-tsc-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-tsc-
|
||||
key: ${{ runner.os }}-tsc-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-tsc-${{ hashFiles('**/yarn.lock') }}-
|
||||
- run: yarn typecheck
|
||||
- if: failure() && github.ref_name == 'main'
|
||||
uses: ./.github/actions/report
|
||||
@@ -64,11 +67,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: jest-cache
|
||||
with:
|
||||
path: node_modules/.cache
|
||||
key: ${{ runner.os }}-jest-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-jest-
|
||||
key: ${{ runner.os }}-jest-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-jest-${{ hashFiles('**/yarn.lock') }}-
|
||||
- run: yarn test --coverage --maxWorkers=100%
|
||||
- uses: codecov/codecov-action@v3
|
||||
with:
|
||||
@@ -86,11 +90,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: build-e2e-cache
|
||||
with:
|
||||
path: node_modules/.cache
|
||||
key: ${{ runner.os }}-build-e2e-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-build-e2e-
|
||||
key: ${{ runner.os }}-build-e2e-${{ hashFiles('**/yarn.lock') }}-${{ github.run_id }}
|
||||
restore-keys: ${{ runner.os }}-build-e2e-${{ hashFiles('**/yarn.lock') }}-
|
||||
- run: yarn build:e2e
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=4096"
|
||||
@@ -109,6 +114,7 @@ jobs:
|
||||
cypress-test-matrix:
|
||||
needs: [build-e2e, cypress-rerun]
|
||||
runs-on: ubuntu-latest
|
||||
container: cypress/browsers:node-18.14.1-chrome-111.0.5563.64-1-ff-111.0-edge-111.0.1661.43-1
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -116,7 +122,8 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/actions/setup
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: cypress-cache
|
||||
with:
|
||||
path: /root/.cache/Cypress
|
||||
key: ${{ runner.os }}-cypress-${{ hashFiles('**/node_modules/cypress/package.json') }}
|
||||
@@ -129,7 +136,8 @@ jobs:
|
||||
name: build-e2e
|
||||
path: build
|
||||
|
||||
- uses: ./.github/actions/cache-on-main
|
||||
- uses: actions/cache@v3
|
||||
id: hardhat-cache
|
||||
with:
|
||||
path: cache
|
||||
key: ${{ runner.os }}-hardhat-${{ hashFiles('hardhat.config.js') }}-${{ github.run_id }}
|
||||
@@ -142,9 +150,8 @@ jobs:
|
||||
parallel: true
|
||||
start: yarn serve
|
||||
wait-on: 'http://localhost:3000'
|
||||
browser: electron
|
||||
browser: chrome
|
||||
group: e2e
|
||||
spec: ${{ github.ref_name == 'releases/staging' && 'cypress/{e2e,staging}/**/*.test.ts' || 'cypress/e2e/**/*.test.ts' }}
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -169,44 +176,11 @@ jobs:
|
||||
name: Cypress tests
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_TEST_REPORTER_WEBHOOK }}
|
||||
|
||||
pre:
|
||||
if: ${{ github.ref_name == 'main' || github.ref_name == 'releases/staging' }}
|
||||
# Included as a single job to check for cypress-test-matrix success, as a matrix cannot be checked.
|
||||
cypress-tests:
|
||||
if: always()
|
||||
needs: [cypress-test-matrix]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6.4.1
|
||||
with:
|
||||
script: |
|
||||
github.rest.repos.createCommitStatus({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
sha: context.sha,
|
||||
state: 'pending',
|
||||
context: 'Test / promotion',
|
||||
description: 'Running tests...',
|
||||
target_url: 'https://github.com/Uniswap/interface/actions/runs/' + context.runId
|
||||
})
|
||||
|
||||
post:
|
||||
if: ${{ github.ref_name == 'main' || github.ref_name == 'releases/staging' }}
|
||||
needs: [pre, lint, typecheck, deps-tests, unit-tests, cypress-test-matrix]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6.4.1
|
||||
with:
|
||||
script: |
|
||||
github.rest.repos.createCommitStatus({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
sha: context.sha,
|
||||
state: ${{ env.STATUS }} ? 'success' : 'failure',
|
||||
context: 'Test / promotion',
|
||||
description: ${{ env.STATUS }} ? 'All tests passed' : 'One or more tests failed and are blocking promotion',
|
||||
target_url: 'https://github.com/Uniswap/interface/actions/runs/' + context.runId
|
||||
})
|
||||
env:
|
||||
STATUS: |
|
||||
${{ needs.lint.result == 'success' }} &&
|
||||
${{ needs.typecheck.result == 'success' }} &&
|
||||
${{ needs.deps-tests.result == 'success' }} &&
|
||||
${{ needs.unit-tests.result == 'success' }} &&
|
||||
${{ needs.cypress-test-matrix.result == 'success' }}
|
||||
- if: needs.cypress-test-matrix.result != 'success'
|
||||
run: exit 1
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,7 +5,8 @@
|
||||
/src/types/v3
|
||||
/src/abis/types
|
||||
/src/locales/**/*.js
|
||||
/src/locales/**/*.po
|
||||
/src/locales/**/en-US.po
|
||||
/src/locales/**/pseudo.po
|
||||
|
||||
# generated files
|
||||
/src/**/__generated__
|
||||
|
||||
@@ -6,7 +6,6 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
const path = require('path')
|
||||
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin')
|
||||
const { DefinePlugin, IgnorePlugin, ProvidePlugin } = require('webpack')
|
||||
const { RetryChunkLoadPlugin } = require('webpack-retry-chunk-load-plugin')
|
||||
|
||||
const commitHash = execSync('git rev-parse HEAD').toString().trim()
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
@@ -94,16 +93,6 @@ module.exports = {
|
||||
// See https://vanilla-extract.style/documentation/integrations/webpack/#identifiers for docs.
|
||||
// See https://github.com/vanilla-extract-css/vanilla-extract/issues/771#issuecomment-1249524366.
|
||||
new VanillaExtractPlugin({ identifiers: 'short' }),
|
||||
new RetryChunkLoadPlugin({
|
||||
cacheBust: `function() {
|
||||
return 'cache-bust=' + Date.now();
|
||||
}`,
|
||||
// Retries with exponential backoff (500ms, 1000ms, 2000ms).
|
||||
retryDelay: `function(retryAttempt) {
|
||||
return 2 ** (retryAttempt - 1) * 500;
|
||||
}`,
|
||||
maxRetries: 3,
|
||||
}),
|
||||
],
|
||||
configure: (webpackConfig) => {
|
||||
// Configure webpack plugins:
|
||||
|
||||
@@ -25,9 +25,14 @@ export default defineConfig({
|
||||
}
|
||||
})
|
||||
|
||||
return config
|
||||
return {
|
||||
...config,
|
||||
// Only enable Chrome.
|
||||
// Electron (the default) has issues injecting window.ethereum before pageload, so it is not viable.
|
||||
browsers: config.browsers.filter(({ name }) => name === 'chrome'),
|
||||
}
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
specPattern: 'cypress/{e2e,staging}/**/*.test.ts',
|
||||
specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { getTestSelector } from '../utils'
|
||||
import { CONNECTED_WALLET_USER_STATE, DISCONNECTED_WALLET_USER_STATE } from '../utils/user-state'
|
||||
import { CONNECTED_WALLET_USER_STATE } from '../utils/user-state'
|
||||
|
||||
describe('Landing Page', () => {
|
||||
it('shows landing page when no user state exists', () => {
|
||||
cy.visit('/', { userState: DISCONNECTED_WALLET_USER_STATE })
|
||||
cy.visit('/', { userState: {} })
|
||||
cy.get(getTestSelector('landing-page'))
|
||||
cy.screenshot()
|
||||
})
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { MaxUint160, MaxUint256 } from '@uniswap/permit2-sdk'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
|
||||
import { DAI, USDC_MAINNET, USDT } from '../../src/constants/tokens'
|
||||
import { DAI, USDC_MAINNET } from '../../src/constants/tokens'
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
/** Initiates a swap. */
|
||||
@@ -15,26 +13,30 @@ function initiateSwap() {
|
||||
}
|
||||
|
||||
describe('Permit2', () => {
|
||||
function setupInputs(inputToken: Token, outputToken: Token) {
|
||||
// Sets up a swap between inputToken and outputToken.
|
||||
cy.visit(`/swap/?inputCurrency=${inputToken.address}&outputCurrency=${outputToken.address}`, {
|
||||
// The same tokens are used for all permit2 tests.
|
||||
const INPUT_TOKEN = DAI
|
||||
const OUTPUT_TOKEN = USDC_MAINNET
|
||||
|
||||
beforeEach(() => {
|
||||
// Sets up a swap between INPUT_TOKEN and OUTPUT_TOKEN.
|
||||
cy.visit(`/swap/?inputCurrency=${INPUT_TOKEN.address}&outputCurrency=${OUTPUT_TOKEN.address}`, {
|
||||
ethereum: 'hardhat',
|
||||
})
|
||||
cy.get('#swap-currency-input .token-amount-input').type('0.01')
|
||||
}
|
||||
})
|
||||
|
||||
/** Asserts permit2 has a max approval for spend of the input token on-chain. */
|
||||
function expectTokenAllowanceForPermit2ToBeMax(inputToken: Token) {
|
||||
function expectTokenAllowanceForPermit2ToBeMax() {
|
||||
// check token approval
|
||||
cy.hardhat()
|
||||
.then(({ approval, wallet }) => approval.getTokenAllowanceForPermit2({ owner: wallet, token: inputToken }))
|
||||
.then(({ approval, wallet }) => approval.getTokenAllowanceForPermit2({ owner: wallet, token: INPUT_TOKEN }))
|
||||
.should('deep.equal', MaxUint256)
|
||||
}
|
||||
|
||||
/** Asserts the universal router has a max permit2 approval for spend of the input token on-chain. */
|
||||
function expectPermit2AllowanceForUniversalRouterToBeMax(inputToken: Token) {
|
||||
function expectPermit2AllowanceForUniversalRouterToBeMax() {
|
||||
cy.hardhat()
|
||||
.then((hardhat) => hardhat.approval.getPermit2Allowance({ owner: hardhat.wallet, token: inputToken }))
|
||||
.then((hardhat) => hardhat.approval.getPermit2Allowance({ owner: hardhat.wallet, token: INPUT_TOKEN }))
|
||||
.then((allowance) => {
|
||||
cy.wrap(MaxUint160.eq(allowance.amount)).should('eq', true)
|
||||
// Asserts that the on-chain expiration is in 30 days, within a tolerance of 40 seconds.
|
||||
@@ -49,7 +51,6 @@ describe('Permit2', () => {
|
||||
beforeEach(() => cy.hardhat({ automine: false }))
|
||||
|
||||
it('swaps after completing full permit2 approval process', () => {
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
initiateSwap()
|
||||
|
||||
// verify that the modal retains its state when the window loses focus
|
||||
@@ -60,7 +61,7 @@ describe('Permit2', () => {
|
||||
cy.wait('@eth_sendRawTransaction')
|
||||
cy.hardhat().then((hardhat) => hardhat.mine())
|
||||
cy.get(getTestSelector('popups')).contains('Approved')
|
||||
expectTokenAllowanceForPermit2ToBeMax(DAI)
|
||||
expectTokenAllowanceForPermit2ToBeMax()
|
||||
|
||||
// Verify permit2 approval
|
||||
cy.contains('Allow DAI to be used for swapping')
|
||||
@@ -69,13 +70,12 @@ describe('Permit2', () => {
|
||||
cy.hardhat().then((hardhat) => hardhat.mine())
|
||||
cy.contains('Success')
|
||||
cy.get(getTestSelector('popups')).contains('Swapped')
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax(DAI)
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax()
|
||||
})
|
||||
|
||||
it('swaps with existing permit approval and missing token approval', () => {
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
cy.hardhat().then(async (hardhat) => {
|
||||
await hardhat.approval.setPermit2Allowance({ owner: hardhat.wallet, token: DAI })
|
||||
await hardhat.approval.setPermit2Allowance({ owner: hardhat.wallet, token: INPUT_TOKEN })
|
||||
await hardhat.mine()
|
||||
})
|
||||
initiateSwap()
|
||||
@@ -85,50 +85,7 @@ describe('Permit2', () => {
|
||||
cy.wait('@eth_sendRawTransaction')
|
||||
cy.hardhat().then((hardhat) => hardhat.mine())
|
||||
cy.get(getTestSelector('popups')).contains('Approved')
|
||||
expectTokenAllowanceForPermit2ToBeMax(DAI)
|
||||
|
||||
// Verify transaction
|
||||
cy.wait('@eth_sendRawTransaction')
|
||||
cy.hardhat().then((hardhat) => hardhat.mine())
|
||||
cy.contains('Success')
|
||||
cy.get(getTestSelector('popups')).contains('Swapped')
|
||||
})
|
||||
|
||||
/**
|
||||
* On mainnet, you have to revoke USDT approval before increasing it.
|
||||
* From the token contract:
|
||||
* To change the approve amount you first have to reduce the addresses`
|
||||
* allowance to zero by calling `approve(_spender, 0)` if it is not
|
||||
* already 0 to mitigate the race condition described here:
|
||||
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
*/
|
||||
it('swaps USDT with existing permit, and existing but insufficient token approval', () => {
|
||||
cy.hardhat().then(async (hardhat) => {
|
||||
await hardhat.fund(hardhat.wallet, CurrencyAmount.fromRawAmount(USDT, 2e6))
|
||||
await hardhat.mine()
|
||||
await hardhat.approval.setTokenAllowanceForPermit2({ owner: hardhat.wallet, token: USDT }, 1e6)
|
||||
await hardhat.mine()
|
||||
await hardhat.approval.setPermit2Allowance({ owner: hardhat.wallet, token: USDT })
|
||||
await hardhat.mine()
|
||||
})
|
||||
setupInputs(USDT, USDC_MAINNET)
|
||||
cy.get('#swap-currency-input .token-amount-input').clear().type('2')
|
||||
initiateSwap()
|
||||
|
||||
// Verify allowance revocation
|
||||
cy.contains('Reset USDT')
|
||||
cy.wait('@eth_sendRawTransaction')
|
||||
cy.hardhat().then((hardhat) => hardhat.mine())
|
||||
cy.hardhat()
|
||||
.then(({ approval, wallet }) => approval.getTokenAllowanceForPermit2({ owner: wallet, token: USDT }))
|
||||
.should('deep.equal', BigNumber.from(0))
|
||||
|
||||
// Verify token approval
|
||||
cy.contains('Enable spending USDT on Uniswap')
|
||||
cy.wait('@eth_sendRawTransaction')
|
||||
cy.hardhat().then((hardhat) => hardhat.mine())
|
||||
cy.get(getTestSelector('popups')).contains('Approved')
|
||||
expectTokenAllowanceForPermit2ToBeMax(USDT)
|
||||
expectTokenAllowanceForPermit2ToBeMax()
|
||||
|
||||
// Verify transaction
|
||||
cy.wait('@eth_sendRawTransaction')
|
||||
@@ -141,11 +98,10 @@ describe('Permit2', () => {
|
||||
it('swaps when user has already approved token and permit2', () => {
|
||||
cy.hardhat().then(({ approval, wallet }) =>
|
||||
Promise.all([
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: DAI }),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: DAI }),
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: INPUT_TOKEN }),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: INPUT_TOKEN }),
|
||||
])
|
||||
)
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
initiateSwap()
|
||||
|
||||
// Verify transaction
|
||||
@@ -154,7 +110,6 @@ describe('Permit2', () => {
|
||||
})
|
||||
|
||||
it('swaps after handling user rejection of both approval and signature', () => {
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
const USER_REJECTION = { code: 4001 }
|
||||
cy.hardhat().then((hardhat) => {
|
||||
// Reject token approval
|
||||
@@ -177,7 +132,7 @@ describe('Permit2', () => {
|
||||
|
||||
// Verify token approval
|
||||
cy.get(getTestSelector('popups')).contains('Approved')
|
||||
expectTokenAllowanceForPermit2ToBeMax(DAI)
|
||||
expectTokenAllowanceForPermit2ToBeMax()
|
||||
|
||||
// Verify permit2 approval rejection
|
||||
cy.wrap(permitApprovalStub).should('be.calledWith', 'eth_signTypedData_v4')
|
||||
@@ -190,32 +145,30 @@ describe('Permit2', () => {
|
||||
// Verify permit2 approval
|
||||
cy.contains('Success')
|
||||
cy.get(getTestSelector('popups')).contains('Swapped')
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax(DAI)
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax()
|
||||
})
|
||||
})
|
||||
|
||||
it('prompts token approval when existing approval amount is too low', () => {
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
cy.hardhat().then(({ approval, wallet }) =>
|
||||
Promise.all([
|
||||
approval.setPermit2Allowance({ owner: wallet, token: DAI }),
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: DAI }, 1),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: INPUT_TOKEN }),
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: INPUT_TOKEN }, 1),
|
||||
])
|
||||
)
|
||||
initiateSwap()
|
||||
|
||||
// Verify token approval
|
||||
cy.get(getTestSelector('popups')).contains('Approved')
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax(DAI)
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax()
|
||||
})
|
||||
|
||||
it('prompts signature when existing permit approval is expired', () => {
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
const expiredAllowance = { expiration: Math.floor((Date.now() - 1) / 1000) }
|
||||
cy.hardhat().then(({ approval, wallet }) =>
|
||||
Promise.all([
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: DAI }),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: DAI }, expiredAllowance),
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: INPUT_TOKEN }),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: INPUT_TOKEN }, expiredAllowance),
|
||||
])
|
||||
)
|
||||
initiateSwap()
|
||||
@@ -224,16 +177,15 @@ describe('Permit2', () => {
|
||||
cy.wait('@eth_signTypedData_v4')
|
||||
cy.contains('Success')
|
||||
cy.get(getTestSelector('popups')).contains('Swapped')
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax(DAI)
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax()
|
||||
})
|
||||
|
||||
it('prompts signature when existing permit approval amount is too low', () => {
|
||||
setupInputs(DAI, USDC_MAINNET)
|
||||
const smallAllowance = { amount: 1 }
|
||||
cy.hardhat().then(({ approval, wallet }) =>
|
||||
Promise.all([
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: DAI }),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: DAI }, smallAllowance),
|
||||
approval.setTokenAllowanceForPermit2({ owner: wallet, token: INPUT_TOKEN }),
|
||||
approval.setPermit2Allowance({ owner: wallet, token: INPUT_TOKEN }, smallAllowance),
|
||||
])
|
||||
)
|
||||
initiateSwap()
|
||||
@@ -242,6 +194,6 @@ describe('Permit2', () => {
|
||||
cy.wait('@eth_signTypedData_v4')
|
||||
cy.contains('Success')
|
||||
cy.get(getTestSelector('popups')).contains('Swapped')
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax(DAI)
|
||||
expectPermit2AllowanceForUniversalRouterToBeMax()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from '@uniswap/sdk-core'
|
||||
|
||||
import { DEFAULT_DEADLINE_FROM_NOW } from '../../../src/constants/misc'
|
||||
import { UNI, USDC_MAINNET } from '../../../src/constants/tokens'
|
||||
import { getBalance, getTestSelector } from '../../utils'
|
||||
|
||||
const UNI_MAINNET = UNI[ChainId.MAINNET]
|
||||
const UNI_MAINNET = UNI[SupportedChainId.MAINNET]
|
||||
|
||||
describe('Swap errors', () => {
|
||||
it('wallet rejection', () => {
|
||||
@@ -64,7 +64,7 @@ describe('Swap errors', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it.skip('slippage failure', () => {
|
||||
it('slippage failure', () => {
|
||||
cy.visit(`/swap?inputCurrency=ETH&outputCurrency=${UNI_MAINNET.address}`, { ethereum: 'hardhat' })
|
||||
cy.hardhat({ automine: false })
|
||||
getBalance(USDC_MAINNET).then((initialBalance) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from '@uniswap/sdk-core'
|
||||
|
||||
import { UNI, USDC_MAINNET } from '../../../src/constants/tokens'
|
||||
import { getBalance, getTestSelector } from '../../utils'
|
||||
|
||||
const UNI_MAINNET = UNI[ChainId.MAINNET]
|
||||
const UNI_MAINNET = UNI[SupportedChainId.MAINNET]
|
||||
|
||||
describe('Swap', () => {
|
||||
describe('Swap on main page', () => {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { ChainId, CurrencyAmount, WETH9 } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, SupportedChainId, WETH9 } from '@uniswap/sdk-core'
|
||||
|
||||
import { getBalance, getTestSelector } from '../../utils'
|
||||
|
||||
const WETH = WETH9[ChainId.MAINNET]
|
||||
const WETH = WETH9[SupportedChainId.MAINNET]
|
||||
|
||||
describe('Swap wrap', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ChainId, WETH9 } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId, WETH9 } from '@uniswap/sdk-core'
|
||||
|
||||
import { ARB, UNI } from '../../src/constants/tokens'
|
||||
import { UNI } from '../../src/constants/tokens'
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
const UNI_MAINNET = UNI[ChainId.MAINNET]
|
||||
const UNI_MAINNET = UNI[SupportedChainId.MAINNET]
|
||||
|
||||
const UNI_ADDRESS = '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984'
|
||||
|
||||
@@ -149,7 +149,7 @@ describe('Token details', () => {
|
||||
cy.get(getTestSelector('tokens-network-filter-selected')).click()
|
||||
cy.get(getTestSelector('tokens-network-filter-option-arbitrum')).click()
|
||||
cy.get(getTestSelector('tokens-network-filter-selected')).should('contain', 'Arbitrum')
|
||||
cy.get(getTestSelector(`token-table-row-${ARB.address.toLowerCase()}`)).click()
|
||||
cy.get(getTestSelector('token-table-row-ARB')).click()
|
||||
cy.get(`#swap-currency-output .token-symbol-container`).should('contain.text', 'ARB')
|
||||
cy.get(getTestSelector('open-settings-dialog-button')).should('be.disabled')
|
||||
cy.contains('Connect to Arbitrum').should('exist')
|
||||
|
||||
@@ -10,11 +10,11 @@ describe('Token explore', () => {
|
||||
cy.get(getTestSelectorStartsWith('token-table')).its('length').should('be.greaterThan', 0)
|
||||
// check sorted svg icon is present in volume cell, since tokens are sorted by volume by default
|
||||
cy.get(getTestSelector('header-row')).find(getTestSelector('volume-cell')).find('svg').should('exist')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE')).find(getTestSelector('name-cell')).should('include.text', 'Ether')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE')).find(getTestSelector('volume-cell')).should('include.text', '$')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE')).find(getTestSelector('price-cell')).should('include.text', '$')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE')).find(getTestSelector('tvl-cell')).should('include.text', '$')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE'))
|
||||
cy.get(getTestSelector('token-table-row-ETH')).find(getTestSelector('name-cell')).should('include.text', 'Ether')
|
||||
cy.get(getTestSelector('token-table-row-ETH')).find(getTestSelector('volume-cell')).should('include.text', '$')
|
||||
cy.get(getTestSelector('token-table-row-ETH')).find(getTestSelector('price-cell')).should('include.text', '$')
|
||||
cy.get(getTestSelector('token-table-row-ETH')).find(getTestSelector('tvl-cell')).should('include.text', '$')
|
||||
cy.get(getTestSelector('token-table-row-ETH'))
|
||||
.find(getTestSelector('percent-change-cell'))
|
||||
.should('include.text', '%')
|
||||
cy.get(getTestSelector('header-row')).find(getTestSelector('price-cell')).click()
|
||||
@@ -24,14 +24,14 @@ describe('Token explore', () => {
|
||||
it('should update when time window toggled', () => {
|
||||
cy.visit('/tokens/ethereum')
|
||||
cy.get(getTestSelector('time-selector')).should('contain', '1D')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE'))
|
||||
cy.get(getTestSelector('token-table-row-ETH'))
|
||||
.find(getTestSelector('volume-cell'))
|
||||
.then(function ($elem) {
|
||||
cy.wrap($elem.text()).as('dailyEthVol')
|
||||
})
|
||||
cy.get(getTestSelector('time-selector')).click()
|
||||
cy.get(getTestSelector('1Y')).click()
|
||||
cy.get(getTestSelector('token-table-row-NATIVE'))
|
||||
cy.get(getTestSelector('token-table-row-ETH'))
|
||||
.find(getTestSelector('volume-cell'))
|
||||
.then(function ($elem) {
|
||||
cy.wrap($elem.text()).as('yearlyEthVol')
|
||||
@@ -41,7 +41,7 @@ describe('Token explore', () => {
|
||||
|
||||
it('should navigate to token detail page when row clicked', () => {
|
||||
cy.visit('/tokens/ethereum')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE')).click()
|
||||
cy.get(getTestSelector('token-table-row-ETH')).click()
|
||||
cy.get(getTestSelector('token-details-about-section')).should('exist')
|
||||
cy.get(getTestSelector('token-details-stats')).should('exist')
|
||||
cy.get(getTestSelector('token-info-container')).should('exist')
|
||||
@@ -53,15 +53,13 @@ describe('Token explore', () => {
|
||||
it('should update when global network changed', () => {
|
||||
cy.visit('/tokens/ethereum')
|
||||
cy.get(getTestSelector('tokens-network-filter-selected')).should('contain', 'Ethereum')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE')).should('exist')
|
||||
cy.get(getTestSelector('token-table-row-ETH')).should('exist')
|
||||
|
||||
// note: cannot switch global chain via UI because we cannot approve the network switch
|
||||
// in metamask modal using plain cypress. this is a workaround.
|
||||
cy.visit('/tokens/polygon')
|
||||
cy.get(getTestSelector('tokens-network-filter-selected')).should('contain', 'Polygon')
|
||||
cy.get(getTestSelector('token-table-row-NATIVE'))
|
||||
.find(getTestSelector('name-cell'))
|
||||
.should('include.text', 'Polygon Matic')
|
||||
cy.get(getTestSelector('token-table-row-MATIC')).should('exist')
|
||||
})
|
||||
|
||||
it('should update when token explore table network changed', () => {
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
describe('Universal search bar', () => {
|
||||
beforeEach(() => {
|
||||
before(() => {
|
||||
cy.visit('/')
|
||||
cy.get('[data-cy="magnifying-icon"]').parent().eq(1).click()
|
||||
cy.get('[data-cy="magnifying-icon"]')
|
||||
.parent()
|
||||
.then(($navIcon) => {
|
||||
$navIcon.click()
|
||||
})
|
||||
})
|
||||
|
||||
it('should yield clickable result for regular token or nft collection search term', () => {
|
||||
@@ -13,7 +19,20 @@ describe('Universal search bar', () => {
|
||||
.and('contain.text', '$')
|
||||
.and('contain.text', '%')
|
||||
cy.get('[data-cy="searchbar-token-row-UNI"]').first().click()
|
||||
cy.location('hash').should('equal', '#/tokens/ethereum/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984')
|
||||
|
||||
cy.get('div').contains('Uniswap').should('exist')
|
||||
// Stats should have: TVL, 24H Volume, 52W low, 52W high.
|
||||
cy.get(getTestSelector('token-details-stats')).should('exist')
|
||||
cy.get(getTestSelector('token-details-stats')).within(() => {
|
||||
cy.get('[data-cy="tvl"]').should('include.text', '$')
|
||||
cy.get('[data-cy="volume-24h"]').should('include.text', '$')
|
||||
cy.get('[data-cy="52w-low"]').should('include.text', '$')
|
||||
cy.get('[data-cy="52w-high"]').should('include.text', '$')
|
||||
})
|
||||
|
||||
// About section should have description of token.
|
||||
cy.get(getTestSelector('token-details-about-section')).should('exist')
|
||||
cy.contains('UNI is the governance token for Uniswap').should('exist')
|
||||
})
|
||||
|
||||
it.skip('should show recent tokens and popular tokens with empty search term', () => {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getTestSelector } from '../../utils'
|
||||
import { DISCONNECTED_WALLET_USER_STATE } from '../../utils/user-state'
|
||||
|
||||
describe('disconnect wallet', () => {
|
||||
it('should clear state', () => {
|
||||
@@ -28,7 +27,7 @@ describe('disconnect wallet', () => {
|
||||
|
||||
describe('connect wallet', () => {
|
||||
it('should load state', () => {
|
||||
cy.visit('/swap', { ethereum: 'hardhat', userState: DISCONNECTED_WALLET_USER_STATE })
|
||||
cy.visit('/swap', { ethereum: 'hardhat', userState: {} })
|
||||
|
||||
// Connect the wallet
|
||||
cy.get(getTestSelector('navbar-connect-wallet')).contains('Connect').click()
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
import { createDeferredPromise } from '../../../src/test-utils/promise'
|
||||
import { getTestSelector } from '../../utils'
|
||||
|
||||
function waitsForActiveChain(chain: string) {
|
||||
cy.get(getTestSelector('chain-selector-logo')).invoke('attr', 'alt').should('eq', chain)
|
||||
}
|
||||
|
||||
function switchChain(chain: string) {
|
||||
cy.get(getTestSelector('chain-selector')).eq(1).click()
|
||||
cy.contains(chain).click()
|
||||
}
|
||||
|
||||
describe('network switching', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/swap', { ethereum: 'hardhat' })
|
||||
cy.get(getTestSelector('web3-status-connected'))
|
||||
})
|
||||
|
||||
function rejectsNetworkSwitchWith(rejection: unknown) {
|
||||
cy.hardhat().then((hardhat) => {
|
||||
// Reject network switch
|
||||
const sendStub = cy.stub(hardhat.provider, 'send').log(false).as('switch')
|
||||
sendStub.withArgs('wallet_switchEthereumChain').rejects(rejection)
|
||||
sendStub.callThrough() // allows other calls to return non-stubbed values
|
||||
})
|
||||
|
||||
switchChain('Polygon')
|
||||
|
||||
// Verify rejected network switch
|
||||
cy.get('@switch').should('have.been.calledWith', 'wallet_switchEthereumChain')
|
||||
waitsForActiveChain('Ethereum')
|
||||
cy.get(getTestSelector('web3-status-connected'))
|
||||
}
|
||||
|
||||
it('should not display message on user rejection', () => {
|
||||
const USER_REJECTION = { code: 4001 }
|
||||
rejectsNetworkSwitchWith(USER_REJECTION)
|
||||
cy.get(getTestSelector('popups')).should('not.contain', 'Failed to switch networks')
|
||||
})
|
||||
|
||||
it('should display message on unknown error', () => {
|
||||
rejectsNetworkSwitchWith(new Error('Unknown error'))
|
||||
cy.get(getTestSelector('popups')).contains('Failed to switch networks')
|
||||
})
|
||||
|
||||
it('should add missing chain', () => {
|
||||
cy.hardhat().then((hardhat) => {
|
||||
// https://docs.metamask.io/guide/rpc-api.html#unrestricted-methods
|
||||
const CHAIN_NOT_ADDED = { code: 4902 } // missing message in useSelectChain
|
||||
|
||||
// Reject network switch with CHAIN_NOT_ADDED
|
||||
const sendStub = cy.stub(hardhat.provider, 'send').log(false).as('switch')
|
||||
let added = false
|
||||
sendStub
|
||||
.withArgs('wallet_switchEthereumChain')
|
||||
.callsFake(() => (added ? Promise.resolve(null) : Promise.reject(CHAIN_NOT_ADDED)))
|
||||
sendStub.withArgs('wallet_addEthereumChain').callsFake(() => {
|
||||
added = true
|
||||
return Promise.resolve(null)
|
||||
})
|
||||
sendStub.callThrough() // allows other calls to return non-stubbed values
|
||||
})
|
||||
|
||||
switchChain('Polygon')
|
||||
|
||||
// Verify the network was added
|
||||
cy.get('@switch').should('have.been.calledWith', 'wallet_switchEthereumChain')
|
||||
cy.get('@switch').should('have.been.calledWith', 'wallet_addEthereumChain', [
|
||||
{
|
||||
blockExplorerUrls: ['https://polygonscan.com/'],
|
||||
chainId: '0x89',
|
||||
chainName: 'Polygon',
|
||||
nativeCurrency: { name: 'Polygon Matic', symbol: 'MATIC', decimals: 18 },
|
||||
rpcUrls: ['https://polygon-rpc.com/'],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
it('should not disconnect while switching', () => {
|
||||
const promise = createDeferredPromise()
|
||||
|
||||
cy.hardhat().then((hardhat) => {
|
||||
// Reject network switch with CHAIN_NOT_ADDED
|
||||
const sendStub = cy.stub(hardhat.provider, 'send').log(false).as('switch')
|
||||
sendStub.withArgs('wallet_switchEthereumChain').returns(promise)
|
||||
sendStub.callThrough() // allows other calls to return non-stubbed values
|
||||
})
|
||||
|
||||
switchChain('Polygon')
|
||||
|
||||
// Verify there is no disconnection
|
||||
cy.get('@switch').should('have.been.calledWith', 'wallet_switchEthereumChain')
|
||||
cy.contains('Connecting to Polygon')
|
||||
cy.get(getTestSelector('web3-status-connected')).should('be.disabled')
|
||||
promise.resolve()
|
||||
})
|
||||
|
||||
it('should switch networks', () => {
|
||||
// Select an output currency
|
||||
cy.get('#swap-currency-output .open-currency-select-button').click()
|
||||
cy.contains('USDC').click()
|
||||
|
||||
// Populate input/output fields
|
||||
cy.get('#swap-currency-input .token-amount-input').clear().type('1')
|
||||
cy.get('#swap-currency-output .token-amount-input').should('not.equal', '')
|
||||
|
||||
// Switch network
|
||||
switchChain('Polygon')
|
||||
|
||||
// Verify network switch
|
||||
cy.wait('@wallet_switchEthereumChain')
|
||||
waitsForActiveChain('Polygon')
|
||||
cy.get(getTestSelector('web3-status-connected'))
|
||||
|
||||
// Verify that the input/output fields were reset
|
||||
cy.get('#swap-currency-input .token-amount-input').should('have.value', '')
|
||||
cy.get(`#swap-currency-input .token-symbol-container`).should('contain.text', 'MATIC')
|
||||
cy.get(`#swap-currency-output .token-amount-input`).should('not.have.value')
|
||||
cy.get(`#swap-currency-output .token-symbol-container`).should('contain.text', 'Select token')
|
||||
})
|
||||
})
|
||||
|
||||
describe('network switching from URL param', () => {
|
||||
it('should switch network from URL param', () => {
|
||||
cy.visit('/swap?chain=polygon', { ethereum: 'hardhat' })
|
||||
cy.get(getTestSelector('web3-status-connected'))
|
||||
cy.wait('@wallet_switchEthereumChain')
|
||||
waitsForActiveChain('Polygon')
|
||||
})
|
||||
})
|
||||
@@ -1,8 +1,8 @@
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
describe('Wallet Dropdown', () => {
|
||||
function itChangesTheme() {
|
||||
it('should change theme', () => {
|
||||
function itShouldChangeTheTheme() {
|
||||
it('should change the theme', () => {
|
||||
cy.get(getTestSelector('theme-lightmode')).click()
|
||||
|
||||
cy.get(getTestSelector('theme-lightmode')).should('not.have.css', 'background-color', 'rgba(0, 0, 0, 0)')
|
||||
@@ -21,17 +21,13 @@ describe('Wallet Dropdown', () => {
|
||||
})
|
||||
}
|
||||
|
||||
function itChangesLocale() {
|
||||
it('should change locale', () => {
|
||||
cy.contains('Uniswap available in: English').should('not.exist')
|
||||
|
||||
cy.get(getTestSelector('wallet-language-item')).contains('Afrikaans').click({ force: true })
|
||||
cy.location('hash').should('match', /\?lng=af-ZA$/)
|
||||
cy.contains('Uniswap available in: English')
|
||||
|
||||
function itShouldChangeTheLanguage() {
|
||||
it('should select a language', () => {
|
||||
cy.get(getTestSelector('wallet-language-item')).contains('Deutsch').click({ force: true })
|
||||
cy.get(getTestSelector('wallet-header')).should('contain', 'Sprache')
|
||||
cy.get(getTestSelector('wallet-language-item')).contains('English').click({ force: true })
|
||||
cy.location('hash').should('match', /\?lng=en-US$/)
|
||||
cy.contains('Uniswap available in: English').should('not.exist')
|
||||
cy.get(getTestSelector('wallet-header')).should('contain', 'Language')
|
||||
cy.get(getTestSelector('wallet-back')).click()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -41,8 +37,8 @@ describe('Wallet Dropdown', () => {
|
||||
cy.get(getTestSelector('web3-status-connected')).click()
|
||||
cy.get(getTestSelector('wallet-settings')).click()
|
||||
})
|
||||
itChangesTheme()
|
||||
itChangesLocale()
|
||||
itShouldChangeTheTheme()
|
||||
itShouldChangeTheLanguage()
|
||||
})
|
||||
|
||||
describe('testnet toggle', () => {
|
||||
@@ -72,8 +68,8 @@ describe('Wallet Dropdown', () => {
|
||||
cy.get(getTestSelector('wallet-disconnect')).click()
|
||||
cy.get(getTestSelector('wallet-settings')).click()
|
||||
})
|
||||
itChangesTheme()
|
||||
itChangesLocale()
|
||||
itShouldChangeTheTheme()
|
||||
itShouldChangeTheLanguage()
|
||||
})
|
||||
|
||||
describe('with color theme', () => {
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { getTestSelector } from '../utils'
|
||||
|
||||
describe('translations', () => {
|
||||
it('loads locale from the query param', () => {
|
||||
cy.visit('/?lng=fr-FR')
|
||||
cy.contains('Échanger')
|
||||
cy.contains('Uniswap disponible en : English')
|
||||
})
|
||||
|
||||
it('loads locale from menu', () => {
|
||||
cy.visit('/')
|
||||
cy.get(getTestSelector('web3-status-connected')).click()
|
||||
cy.get(getTestSelector('wallet-settings')).click()
|
||||
cy.get(getTestSelector('wallet-language-item')).contains('français').click({ force: true })
|
||||
cy.location('hash').should('match', /\?lng=fr-FR$/)
|
||||
cy.contains('Échanger')
|
||||
cy.contains('Uniswap disponible en : English')
|
||||
})
|
||||
})
|
||||
@@ -58,7 +58,7 @@ Cypress.Commands.overwrite(
|
||||
// Set initial user state.
|
||||
win.localStorage.setItem(
|
||||
'redux_localstorage_simple_user', // storage key for the user reducer using 'redux-localstorage-simple'
|
||||
JSON.stringify({ ...CONNECTED_WALLET_USER_STATE, ...(options?.userState ?? {}) })
|
||||
JSON.stringify(options?.userState ?? CONNECTED_WALLET_USER_STATE)
|
||||
)
|
||||
|
||||
// Set feature flags, if configured.
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
*/
|
||||
|
||||
import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { JsonRpcProvider } from '@ethersproject/providers'
|
||||
import { Wallet } from '@ethersproject/wallet'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
|
||||
import { SupportedChainId } from '../../src/constants/chains'
|
||||
|
||||
// todo: figure out how env vars actually work in CI
|
||||
// const TEST_PRIVATE_KEY = Cypress.env('INTEGRATION_TEST_PRIVATE_KEY')
|
||||
@@ -13,7 +15,7 @@ const TEST_PRIVATE_KEY = '0xe580410d7c37d26c6ad1a837bbae46bc27f9066a466fb3a66e77
|
||||
|
||||
// address of the above key
|
||||
const TEST_ADDRESS_NEVER_USE = new Wallet(TEST_PRIVATE_KEY).address
|
||||
const CHAIN_ID = ChainId.GOERLI
|
||||
const CHAIN_ID = SupportedChainId.GOERLI
|
||||
const HEXLIFIED_CHAIN_ID = `0x${CHAIN_ID.toString(16)}`
|
||||
|
||||
const provider = new JsonRpcProvider('https://goerli.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847', 5)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { UserState } from '../../src/state/user/reducer'
|
||||
|
||||
export const CONNECTED_WALLET_USER_STATE: Partial<UserState> = { selectedWallet: 'INJECTED' }
|
||||
|
||||
export const DISCONNECTED_WALLET_USER_STATE: Partial<UserState> = { selectedWallet: undefined }
|
||||
|
||||
36
eslint_rules/enforce-retry-on-import.js
Normal file
36
eslint_rules/enforce-retry-on-import.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/* eslint-env node */
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'enforce use of retry() for dynamic imports',
|
||||
category: 'Best Practices',
|
||||
recommended: false,
|
||||
},
|
||||
schema: [],
|
||||
},
|
||||
create(context) {
|
||||
return {
|
||||
ImportExpression(node) {
|
||||
const grandParent = node.parent.parent
|
||||
if (
|
||||
!(
|
||||
grandParent &&
|
||||
grandParent.type === 'CallExpression' &&
|
||||
// Technically, we are only checking that a function named `retry` wraps the dynamic import.
|
||||
// We do not go as far as enforcing that it is import('utils/retry').retry
|
||||
grandParent.callee.name === 'retry' &&
|
||||
grandParent.arguments.length === 1 &&
|
||||
grandParent.arguments[0].type === 'ArrowFunctionExpression'
|
||||
)
|
||||
) {
|
||||
context.report({
|
||||
node,
|
||||
message: 'Dynamic import should be wrapped in retry (see `utils/retry.ts`): `retry(() => import(...))`',
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export const presets = ['@babel/preset-env']
|
||||
@@ -1,9 +0,0 @@
|
||||
import { setup } from 'jest-dev-server'
|
||||
|
||||
module.exports = async function globalSetup() {
|
||||
globalThis.servers = await setup({
|
||||
command: `yarn start:cloud`,
|
||||
port: 3000,
|
||||
launchTimeout: 50000,
|
||||
})
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import { teardown } from 'jest-dev-server'
|
||||
|
||||
module.exports = async function globalTeardown() {
|
||||
await teardown(globalThis.servers)
|
||||
}
|
||||
6
functions/global.d.ts
vendored
6
functions/global.d.ts
vendored
@@ -1,6 +0,0 @@
|
||||
import { setup } from 'jest-dev-server'
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
var servers: Awaited<ReturnType<typeof setup>>
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"globalSetup": "<rootDir>/global-setup.ts",
|
||||
"globalTeardown": "<rootDir>/global-teardown.ts",
|
||||
"preset": "ts-jest",
|
||||
"transform": {
|
||||
"'^.+\\.(ts|tsx)?$'": "ts-jest",
|
||||
"^.+\\.(js|jsx)$": "babel-jest"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
test('example', async () => {
|
||||
expect(true).toBe(true)
|
||||
})
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"incremental": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"noEmit": true,
|
||||
"strict": true,
|
||||
"target": "ES6",
|
||||
"tsBuildInfoFile": "../node_modules/.cache/tsbuildinfo/functions", // avoid clobbering the build tsbuildinfo
|
||||
"types": ["jest", "node"],
|
||||
"jsx": "react",
|
||||
"moduleResolution": "NodeNext",
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["**/*.ts"],
|
||||
"watchOptions": {
|
||||
"excludeDirectories": ["node_modules"]
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ const config: CodegenConfig = {
|
||||
withHooks: true,
|
||||
// This avoid all generated schemas being wrapped in Maybe https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#maybevalue-string-default-value-t--null
|
||||
maybeValue: 'T',
|
||||
immutableTypes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
|
||||
/* eslint-env node */
|
||||
require('dotenv').config()
|
||||
|
||||
@@ -7,33 +5,20 @@ require('dotenv').config()
|
||||
// The only requirement is that all infrastructure under test (eg Permit2 contracts) are already deployed.
|
||||
// TODO(WEB-2187): Make more dynamic to avoid manually updating
|
||||
const BLOCK_NUMBER = 17388567
|
||||
const POLYGON_BLOCK_NUMBER = 43600000
|
||||
|
||||
const forkingConfig = {
|
||||
const mainnetFork = {
|
||||
url: `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_KEY}`,
|
||||
blockNumber: BLOCK_NUMBER,
|
||||
httpHeaders: {
|
||||
Origin: 'localhost:3000', // infura allowlists requests by origin
|
||||
},
|
||||
}
|
||||
|
||||
const forks = {
|
||||
[ChainId.MAINNET]: {
|
||||
url: `https://mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_KEY}`,
|
||||
blockNumber: BLOCK_NUMBER,
|
||||
...forkingConfig,
|
||||
},
|
||||
[ChainId.POLYGON]: {
|
||||
url: `https://polygon-mainnet.infura.io/v3/${process.env.REACT_APP_INFURA_KEY}`,
|
||||
blockNumber: POLYGON_BLOCK_NUMBER,
|
||||
...forkingConfig,
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
forks,
|
||||
networks: {
|
||||
hardhat: {
|
||||
chainId: ChainId.MAINNET,
|
||||
forking: forks[ChainId.MAINNET],
|
||||
chainId: 1,
|
||||
forking: mainnetFork,
|
||||
accounts: {
|
||||
count: 2,
|
||||
},
|
||||
|
||||
@@ -115,11 +115,13 @@ const linguiConfig = {
|
||||
'vi-VN',
|
||||
'zh-CN',
|
||||
'zh-TW',
|
||||
'pseudo',
|
||||
],
|
||||
orderBy: 'messageId',
|
||||
rootDir: '.',
|
||||
runtimeConfigModule: ['@lingui/core', 'i18n'],
|
||||
sourceLocale: 'en-US',
|
||||
pseudoLocale: 'pseudo',
|
||||
extractors: [cachingExtractor],
|
||||
}
|
||||
|
||||
|
||||
29
package.json
29
package.json
@@ -15,11 +15,11 @@
|
||||
"graphql:generate": "yarn graphql:generate:data && yarn graphql:generate:thegraph",
|
||||
"graphql": "yarn graphql:fetch && yarn graphql:generate",
|
||||
"i18n:extract": "lingui extract --locale en-US",
|
||||
"i18n:pseudo": "lingui extract --locale pseudo",
|
||||
"i18n:compile": "lingui compile",
|
||||
"i18n": "yarn i18n:extract --clean && yarn i18n:compile",
|
||||
"prepare": "concurrently \"npm:ajv\" \"npm:contracts\" \"npm:graphql\" \"npm:i18n\"",
|
||||
"start": "craco start",
|
||||
"start:cloud": "NODE_OPTIONS=--dns-result-order=ipv4first PORT=3001 npx wrangler pages dev --proxy=3001 --port=3000 -- yarn start",
|
||||
"build": "craco build",
|
||||
"build:e2e": "REACT_APP_CSP_ALLOW_UNSAFE_EVAL=true REACT_APP_ADD_COVERAGE_INSTRUMENTATION=true craco build",
|
||||
"analyze": "source-map-explorer 'build/static/js/*.js' --only-mapped",
|
||||
@@ -27,7 +27,6 @@
|
||||
"lint": "yarn eslint --ignore-path .gitignore --cache --cache-location node_modules/.cache/eslint/ .",
|
||||
"typecheck": "tsc",
|
||||
"test": "craco test",
|
||||
"test:cloud": "NODE_OPTIONS=--experimental-vm-modules yarn jest functions --watch --config=functions/jest.config.json",
|
||||
"cypress:open": "cypress open --browser chrome --e2e",
|
||||
"cypress:run": "cypress run --browser chrome --e2e",
|
||||
"deduplicate": "yarn-deduplicate --strategy=highest"
|
||||
@@ -68,8 +67,6 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.22.7",
|
||||
"@cloudflare/workers-types": "^4.20230518.0",
|
||||
"@craco/craco": "^7.1.0",
|
||||
"@ethersproject/experimental": "^5.4.0",
|
||||
"@lingui/cli": "^3.9.0",
|
||||
@@ -101,42 +98,35 @@
|
||||
"@types/ua-parser-js": "^0.7.36",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/wcag-contrast": "^3.0.0",
|
||||
"@uniswap/default-token-list": "^11.2.0",
|
||||
"@uniswap/default-token-list": "^9.6.0",
|
||||
"@uniswap/eslint-config": "^1.2.0",
|
||||
"@vanilla-extract/babel-plugin": "^1.1.7",
|
||||
"@vanilla-extract/jest-transform": "^1.1.1",
|
||||
"@vanilla-extract/webpack-plugin": "^2.1.11",
|
||||
"@walletconnect/types": "^2.8.6",
|
||||
"babel-jest": "^29.6.1",
|
||||
"babel-plugin-istanbul": "^6.1.1",
|
||||
"buffer": "^6.0.3",
|
||||
"concurrently": "^8.0.1",
|
||||
"cypress": "12.12.0",
|
||||
"cypress-hardhat": "^2.4.2",
|
||||
"cypress-hardhat": "^2.3.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"eslint": "^7.11.0",
|
||||
"eslint-plugin-import": "^2.27",
|
||||
"eslint-plugin-rulesdir": "^0.2.2",
|
||||
"hardhat": "^2.14.0",
|
||||
"jest": "^29.6.1",
|
||||
"jest-dev-server": "^9.0.0",
|
||||
"jest-fail-on-console": "^3.1.1",
|
||||
"jest-fetch-mock": "^3.0.3",
|
||||
"jest-styled-components": "^7.0.8",
|
||||
"ms.macro": "^2.0.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier": "^2.7.1",
|
||||
"process": "^0.11.10",
|
||||
"react-scripts": "^5.0.1",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"serve": "^11.3.2",
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"ts-jest": "^29.1.1",
|
||||
"ts-transform-graphql-tag": "^0.2.1",
|
||||
"typechain": "^5.0.0",
|
||||
"typescript": "^4.4.3",
|
||||
"wrangler": "https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/4925945367/npm-package-wrangler-3048",
|
||||
"webpack-retry-chunk-load-plugin": "^3.1.1",
|
||||
"yarn-deduplicate": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -175,10 +165,10 @@
|
||||
"@uniswap/permit2-sdk": "1.2.0",
|
||||
"@uniswap/redux-multicall": "^1.1.8",
|
||||
"@uniswap/router-sdk": "^1.3.0",
|
||||
"@uniswap/sdk-core": "^3.2.6",
|
||||
"@uniswap/smart-order-router": "3.13.5",
|
||||
"@uniswap/sdk-core": "^3.2.3",
|
||||
"@uniswap/smart-order-router": "^3.12.1",
|
||||
"@uniswap/token-lists": "^1.0.0-beta.31",
|
||||
"@uniswap/universal-router-sdk": "^1.5.3",
|
||||
"@uniswap/universal-router-sdk": "^1.5.1",
|
||||
"@uniswap/v2-core": "1.0.0",
|
||||
"@uniswap/v2-periphery": "^1.1.0-beta.0",
|
||||
"@uniswap/v2-sdk": "^3.0.1",
|
||||
@@ -200,12 +190,13 @@
|
||||
"@web3-react/core": "^8.2.0",
|
||||
"@web3-react/eip1193": "^8.2.0",
|
||||
"@web3-react/empty": "^8.2.0",
|
||||
"@web3-react/gnosis-safe": "^8.2.1",
|
||||
"@web3-react/gnosis-safe": "^8.2.0",
|
||||
"@web3-react/metamask": "^8.2.0",
|
||||
"@web3-react/network": "^8.2.0",
|
||||
"@web3-react/types": "^8.2.0",
|
||||
"@web3-react/url": "^8.2.0",
|
||||
"@web3-react/walletconnect-v2": "^8.3.7",
|
||||
"@web3-react/walletconnect": "^8.2.0",
|
||||
"@web3-react/walletconnect-v2": "^8.3.3",
|
||||
"ajv": "^8.11.0",
|
||||
"ajv-formats": "^2.1.1",
|
||||
"array.prototype.flat": "^1.2.4",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
@uniswap/web-admins
|
||||
@@ -19,9 +19,9 @@
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
<% if (process.env.REACT_APP_CSP_ALLOW_UNSAFE_EVAL) { %>
|
||||
content="script-src 'self' 'unsafe-inline' 'unsafe-eval'"
|
||||
content="script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com 'unsafe-inline' 'unsafe-eval'"
|
||||
<% } else { %>
|
||||
content="script-src 'self' 'unsafe-inline'"
|
||||
content="script-src 'self' https://www.google-analytics.com https://www.googletagmanager.com 'unsafe-inline'"
|
||||
<% } %>
|
||||
/>
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
|
||||
<link rel="preconnect" href="https://www.google-analytics.com/" />
|
||||
|
||||
<link rel="preload" href="%PUBLIC_URL%/fonts/Inter-roman.var.woff2" as="font" type="font/woff2" crossorigin />
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_13871_12533)">
|
||||
<path d="M12.9341 2.74118H3.05524V11.7259H12.9341V2.74118Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9947 8C15.9947 12.4154 12.4154 15.9947 7.99999 15.9947C3.58465 15.9947 0.00531006 12.4154 0.00531006 8C0.00531006 3.58466 3.58465 0.00532532 7.99999 0.00532532C12.4154 0.00532532 15.9947 3.58466 15.9947 8ZM5.73452 11.1815H4.18298C3.85696 11.1815 3.69591 11.1815 3.59772 11.1187C3.49166 11.0499 3.42685 10.936 3.41899 10.8103C3.4131 10.6945 3.49363 10.553 3.65467 10.2702L7.48562 3.51761C7.64864 3.23086 7.73112 3.08749 7.83521 3.03447C7.94715 2.97751 8.08071 2.97751 8.19266 3.03447C8.29675 3.08749 8.37924 3.23086 8.54224 3.51761L9.32981 4.89239L9.33382 4.89941C9.50989 5.20703 9.59917 5.36303 9.63815 5.52675C9.68135 5.70548 9.68135 5.89402 9.63815 6.07274C9.59887 6.23771 9.51049 6.39484 9.33177 6.70711L7.31946 10.2643L7.31426 10.2734C7.13703 10.5836 7.04722 10.7408 6.92274 10.8594C6.78722 10.989 6.62421 11.0832 6.44549 11.1363C6.28247 11.1815 6.09983 11.1815 5.73452 11.1815ZM9.65268 11.1815H11.8759C12.2038 11.1815 12.3689 11.1815 12.4671 11.1168C12.5731 11.048 12.6399 10.9321 12.6458 10.8064C12.6515 10.6943 12.5727 10.5584 12.4184 10.292C12.413 10.283 12.4077 10.2737 12.4023 10.2643L11.2887 8.35928L11.276 8.33783C11.1195 8.07321 11.0405 7.93958 10.9391 7.88793C10.8272 7.83096 10.6955 7.83096 10.5836 7.88793C10.4815 7.94095 10.399 8.0804 10.236 8.36124L9.12633 10.2663L9.12253 10.2729C8.96009 10.5533 8.87891 10.6934 8.88477 10.8084C8.89262 10.9341 8.95743 11.0499 9.06348 11.1187C9.15973 11.1815 9.3247 11.1815 9.65268 11.1815Z" fill="#E84142"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_13871_12533">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,11 +0,0 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_298_130193)">
|
||||
<path d="M12.9346 2.74121H3.05566V11.7259H12.9346V2.74121Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9998 0C15.9998 4.41538 15.9998 15.9947 15.9998 15.9947C11.5844 15.9947 0.00590861 15.9947 0.00590861 15.9947L0.00488281 5.43594e-05C4.42027 5.43594e-05 15.9998 0 15.9998 0ZM5.73493 11.1815H4.18339C3.85736 11.1815 3.69632 11.1815 3.59813 11.1187C3.49207 11.0499 3.42726 10.936 3.4194 10.8103C3.41351 10.6945 3.49404 10.553 3.65508 10.2702L7.48603 3.51765C7.64905 3.2309 7.73153 3.08753 7.83562 3.03451C7.94756 2.97755 8.08112 2.97755 8.19307 3.03451C8.29716 3.08753 8.37965 3.2309 8.54265 3.51765L9.33022 4.89243L9.33423 4.89945C9.51029 5.20707 9.59958 5.36307 9.63856 5.52679C9.68176 5.70552 9.68176 5.89406 9.63856 6.07278C9.59928 6.23775 9.5109 6.39488 9.33218 6.70715L7.31987 10.2643L7.31466 10.2734C7.13744 10.5836 7.04762 10.7408 6.92315 10.8594C6.78763 10.9891 6.62462 11.0833 6.44589 11.1364C6.28288 11.1815 6.10024 11.1815 5.73493 11.1815ZM9.65309 11.1815H11.8763C12.2043 11.1815 12.3693 11.1815 12.4675 11.1168C12.5735 11.048 12.6403 10.9321 12.6463 10.8065C12.6519 10.6944 12.5731 10.5584 12.4188 10.2921C12.4134 10.283 12.4081 10.2738 12.4027 10.2644L11.2891 8.35932L11.2764 8.33787C11.1199 8.07325 11.0409 7.93962 10.9395 7.88797C10.8276 7.831 10.6959 7.831 10.584 7.88797C10.4819 7.94099 10.3994 8.08044 10.2364 8.36128L9.12674 10.2663L9.12294 10.2729C8.9605 10.5533 8.87932 10.6934 8.88518 10.8084C8.89303 10.9341 8.95784 11.0499 9.06389 11.1187C9.16014 11.1815 9.32511 11.1815 9.65309 11.1815Z" fill="#E84142"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_298_130193">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
24
src/assets/wallets/phantom-icon.svg
Normal file
24
src/assets/wallets/phantom-icon.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_13571_129912)">
|
||||
<rect width="40" height="40" fill="url(#paint0_linear_13571_129912)"/>
|
||||
<path d="M20 40C31.0457 40 40 31.0457 40 20C40 8.9543 31.0457 0 20 0C8.9543 0 0 8.9543 0 20C0 31.0457 8.9543 40 20 40Z" fill="url(#paint1_linear_13571_129912)"/>
|
||||
<path d="M34.5575 20.2857H30.9819C30.9819 13.0516 25.0541 7.1875 17.7414 7.1875C10.5191 7.1875 4.64737 12.908 4.50368 20.0182C4.35499 27.3678 11.3253 33.75 18.7558 33.75H19.6904C26.2413 33.75 35.0216 28.6771 36.3934 22.4961C36.6469 21.3567 35.7369 20.2857 34.5575 20.2857ZM12.4278 20.6079C12.4278 21.5753 11.628 22.3665 10.6501 22.3665C9.67215 22.3665 8.87237 21.575 8.87237 20.6079V17.7629C8.87237 16.7955 9.67215 16.0043 10.6501 16.0043C11.628 16.0043 12.4278 16.7955 12.4278 17.7629V20.6079ZM18.6007 20.6079C18.6007 21.5753 17.801 22.3665 16.8231 22.3665C15.8451 22.3665 15.0453 21.575 15.0453 20.6079V17.7629C15.0453 16.7955 15.8455 16.0043 16.8231 16.0043C17.801 16.0043 18.6007 16.7955 18.6007 17.7629V20.6079Z" fill="url(#paint2_linear_13571_129912)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_13571_129912" x1="20" y1="0" x2="20" y2="40" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#534BB1"/>
|
||||
<stop offset="1" stop-color="#551BF9"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_13571_129912" x1="20" y1="0" x2="20" y2="40" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#534BB1"/>
|
||||
<stop offset="1" stop-color="#551BF9"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_13571_129912" x1="20.4687" y1="7.1875" x2="20.4687" y2="33.75" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0.82"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_13571_129912">
|
||||
<rect width="40" height="40" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -1,6 +1,5 @@
|
||||
import { TraceEvent } from '@uniswap/analytics'
|
||||
import { BrowserEvent, InterfaceElementName, SharedEventName } from '@uniswap/analytics-events'
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import styled from 'styled-components/macro'
|
||||
import { BREAKPOINTS, ExternalLink, StyledRouterLink } from 'theme'
|
||||
import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
||||
@@ -138,7 +137,6 @@ const LogoSectionContent = () => {
|
||||
}
|
||||
|
||||
export const AboutFooter = () => {
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
return (
|
||||
<Footer>
|
||||
<LogoSectionLeft>
|
||||
@@ -150,7 +148,7 @@ export const AboutFooter = () => {
|
||||
<LinkGroupTitle>App</LinkGroupTitle>
|
||||
<TextLink to="/swap">Swap</TextLink>
|
||||
<TextLink to="/tokens">Tokens</TextLink>
|
||||
{!shouldDisableNFTRoutes && <TextLink to="/nfts">NFTs</TextLink>}
|
||||
<TextLink to="/nfts">NFTs</TextLink>
|
||||
<TextLink to="/pools">Pools</TextLink>
|
||||
</LinkGroup>
|
||||
<LinkGroup>
|
||||
|
||||
@@ -12,14 +12,14 @@ import { formatDelta } from 'components/Tokens/TokenDetails/PriceChart'
|
||||
import Tooltip from 'components/Tooltip'
|
||||
import { getConnection } from 'connection'
|
||||
import { usePortfolioBalancesQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { GQL_MAINNET_CHAINS } from 'graphql/data/util'
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { useProfilePageState, useSellAsset, useWalletCollections } from 'nft/hooks'
|
||||
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
|
||||
import { ProfilePageStateType } from 'nft/types'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { ArrowDownRight, ArrowUpRight, CreditCard, IconProps, Info, LogOut, Settings } from 'react-feather'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
|
||||
import { useAppDispatch } from 'state/hooks'
|
||||
import { updateSelectedWallet } from 'state/user/reducer'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
@@ -40,7 +40,6 @@ const AuthenticatedHeaderWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
`
|
||||
|
||||
const HeaderButton = styled(ThemeButton)`
|
||||
@@ -105,6 +104,7 @@ const StatusWrapper = styled.div`
|
||||
display: inline-block;
|
||||
width: 70%;
|
||||
max-width: 70%;
|
||||
overflow: hidden;
|
||||
padding-right: 14px;
|
||||
display: inline-flex;
|
||||
`
|
||||
@@ -171,7 +171,7 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
|
||||
const clearCollectionFilters = useWalletCollections((state) => state.clearCollectionFilters)
|
||||
const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable)
|
||||
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
|
||||
|
||||
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
|
||||
const isUnclaimed = useUserHasAvailableClaim(account)
|
||||
@@ -227,10 +227,9 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
|
||||
const closeFiatOnrampUnavailableTooltip = useCallback(() => setShow(false), [setShow])
|
||||
|
||||
const { data: portfolioBalances } = usePortfolioBalancesQuery({
|
||||
variables: { ownerAddress: account ?? '', chains: GQL_MAINNET_CHAINS },
|
||||
variables: { ownerAddress: account ?? '' },
|
||||
fetchPolicy: 'cache-only', // PrefetchBalancesWrapper handles balance fetching/staleness; this component only reads from cache
|
||||
})
|
||||
|
||||
const portfolio = portfolioBalances?.portfolios?.[0]
|
||||
const totalBalance = portfolio?.tokensTotalDenominatedValue?.value
|
||||
const absoluteChange = portfolio?.tokensTotalDenominatedValueChange?.absolute?.value
|
||||
@@ -241,7 +240,7 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
|
||||
<AuthenticatedHeaderWrapper>
|
||||
<HeaderWrapper>
|
||||
<StatusWrapper>
|
||||
<StatusIcon account={account} connection={connection} size={40} />
|
||||
<StatusIcon connection={connection} size={40} />
|
||||
{account && (
|
||||
<AccountNamesWrapper>
|
||||
<ThemedText.SubHeader>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChainId, Token, TradeType as MockTradeType } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId, Token, TradeType as MockTradeType } from '@uniswap/sdk-core'
|
||||
import { PERMIT2_ADDRESS } from '@uniswap/universal-router-sdk'
|
||||
import { DAI as MockDAI, nativeOnChain, USDC_MAINNET as MockUSDC_MAINNET, USDT as MockUSDT } from 'constants/tokens'
|
||||
import { TransactionStatus as MockTxStatus } from 'graphql/data/__generated__/types-and-hooks'
|
||||
@@ -46,7 +46,7 @@ function mockSwapInfo(
|
||||
|
||||
const mockAccount1 = '0x000000000000000000000000000000000000000001'
|
||||
const mockAccount2 = '0x000000000000000000000000000000000000000002'
|
||||
const mockChainId = ChainId.MAINNET
|
||||
const mockChainId = SupportedChainId.MAINNET
|
||||
const mockSpenderAddress = PERMIT2_ADDRESS[mockChainId]
|
||||
const mockCurrencyAmountRaw = '1000000000000000000'
|
||||
const mockCurrencyAmountRawUSDC = '1000000'
|
||||
@@ -246,7 +246,7 @@ describe('parseLocalActivity', () => {
|
||||
status: 1,
|
||||
},
|
||||
} as TransactionDetails
|
||||
const chainId = ChainId.MAINNET
|
||||
const chainId = SupportedChainId.MAINNET
|
||||
expect(parseLocalActivity(details, chainId, mockTokenAddressMap)).toEqual({
|
||||
chainId: 1,
|
||||
currencies: [MockUSDC_MAINNET, MockDAI],
|
||||
@@ -287,7 +287,7 @@ describe('parseLocalActivity', () => {
|
||||
status: 1,
|
||||
},
|
||||
} as TransactionDetails
|
||||
const chainId = ChainId.MAINNET
|
||||
const chainId = SupportedChainId.MAINNET
|
||||
expect(parseLocalActivity(details, chainId, mockTokenAddressMap)).toMatchObject({
|
||||
chainId: 1,
|
||||
currencies: [MockUSDC_MAINNET, MockDAI],
|
||||
@@ -311,7 +311,7 @@ describe('parseLocalActivity', () => {
|
||||
status: 1,
|
||||
},
|
||||
} as TransactionDetails
|
||||
const chainId = ChainId.MAINNET
|
||||
const chainId = SupportedChainId.MAINNET
|
||||
const tokens = {} as ChainTokenMap
|
||||
expect(parseLocalActivity(details, chainId, tokens)).toMatchObject({
|
||||
chainId: 1,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { t } from '@lingui/macro'
|
||||
import { formatCurrencyAmount } from '@uniswap/conedison/format'
|
||||
import { ChainId, Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core'
|
||||
import { nativeOnChain } from '@uniswap/smart-order-router'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { TransactionStatus } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { ChainTokenMap, useAllTokensMultichain } from 'hooks/Tokens'
|
||||
import { useMemo } from 'react'
|
||||
@@ -25,7 +26,7 @@ import {
|
||||
import { getActivityTitle } from '../constants'
|
||||
import { Activity, ActivityMap } from './types'
|
||||
|
||||
function getCurrency(currencyId: string, chainId: ChainId, tokens: ChainTokenMap): Currency | undefined {
|
||||
function getCurrency(currencyId: string, chainId: SupportedChainId, tokens: ChainTokenMap): Currency | undefined {
|
||||
return currencyId === 'ETH' ? nativeOnChain(chainId) : tokens[chainId]?.[currencyId]
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ function buildCurrencyDescriptor(
|
||||
|
||||
function parseSwap(
|
||||
swap: ExactInputSwapTransactionInfo | ExactOutputSwapTransactionInfo,
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
tokens: ChainTokenMap
|
||||
): Partial<Activity> {
|
||||
const tokenIn = getCurrency(swap.inputCurrencyId, chainId, tokens)
|
||||
@@ -61,7 +62,7 @@ function parseSwap(
|
||||
}
|
||||
}
|
||||
|
||||
function parseWrap(wrap: WrapTransactionInfo, chainId: ChainId, status: TransactionStatus): Partial<Activity> {
|
||||
function parseWrap(wrap: WrapTransactionInfo, chainId: SupportedChainId, status: TransactionStatus): Partial<Activity> {
|
||||
const native = nativeOnChain(chainId)
|
||||
const wrapped = native.wrapped
|
||||
const [input, output] = wrap.unwrapped ? [wrapped, native] : [native, wrapped]
|
||||
@@ -75,7 +76,7 @@ function parseWrap(wrap: WrapTransactionInfo, chainId: ChainId, status: Transact
|
||||
|
||||
function parseApproval(
|
||||
approval: ApproveTransactionInfo,
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
tokens: ChainTokenMap,
|
||||
status: TransactionStatus
|
||||
): Partial<Activity> {
|
||||
@@ -96,7 +97,7 @@ type GenericLPInfo = Omit<
|
||||
AddLiquidityV3PoolTransactionInfo | RemoveLiquidityV3TransactionInfo | AddLiquidityV2PoolTransactionInfo,
|
||||
'type'
|
||||
>
|
||||
function parseLP(lp: GenericLPInfo, chainId: ChainId, tokens: ChainTokenMap): Partial<Activity> {
|
||||
function parseLP(lp: GenericLPInfo, chainId: SupportedChainId, tokens: ChainTokenMap): Partial<Activity> {
|
||||
const baseCurrency = getCurrency(lp.baseCurrencyId, chainId, tokens)
|
||||
const quoteCurrency = getCurrency(lp.quoteCurrencyId, chainId, tokens)
|
||||
const [baseRaw, quoteRaw] = [lp.expectedAmountBaseRaw, lp.expectedAmountQuoteRaw]
|
||||
@@ -107,7 +108,7 @@ function parseLP(lp: GenericLPInfo, chainId: ChainId, tokens: ChainTokenMap): Pa
|
||||
|
||||
function parseCollectFees(
|
||||
collect: CollectFeesTransactionInfo,
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
tokens: ChainTokenMap
|
||||
): Partial<Activity> {
|
||||
// Adapts CollectFeesTransactionInfo to generic LP type
|
||||
@@ -122,7 +123,7 @@ function parseCollectFees(
|
||||
|
||||
function parseMigrateCreateV3(
|
||||
lp: MigrateV2LiquidityToV3TransactionInfo | CreateV3PoolTransactionInfo,
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
tokens: ChainTokenMap
|
||||
): Partial<Activity> {
|
||||
const baseCurrency = getCurrency(lp.baseCurrencyId, chainId, tokens)
|
||||
@@ -136,7 +137,7 @@ function parseMigrateCreateV3(
|
||||
|
||||
export function parseLocalActivity(
|
||||
details: TransactionDetails,
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
tokens: ChainTokenMap
|
||||
): Activity | undefined {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { t } from '@lingui/macro'
|
||||
import { formatFiatPrice, formatNumberOrString, NumberType } from '@uniswap/conedison/format'
|
||||
import { ChainId, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, UNI_ADDRESSES } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from '@uniswap/sdk-core'
|
||||
import moonpayLogoSrc from 'assets/svg/moonpay.svg'
|
||||
import { NONFUNGIBLE_POSITION_MANAGER_ADDRESSES, UNI_ADDRESS } from 'constants/addresses'
|
||||
import { nativeOnChain } from 'constants/tokens'
|
||||
import {
|
||||
ActivityType,
|
||||
@@ -13,7 +14,7 @@ import {
|
||||
TokenApprovalPartsFragment,
|
||||
TokenTransferPartsFragment,
|
||||
} from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { logSentryErrorForUnsupportedChain, supportedChainIdFromGQLChain } from 'graphql/data/util'
|
||||
import { fromGraphQLChain } from 'graphql/data/util'
|
||||
import ms from 'ms.macro'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { isAddress } from 'utils'
|
||||
@@ -37,7 +38,7 @@ const ENS_IMG =
|
||||
'https://464911102-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/collections%2F2TjMAeHSzwlQgcOdL48E%2Ficon%2FKWP0gk2C6bdRPliWIA6o%2Fens%20transparent%20background.png?alt=media&token=bd28b063-5a75-4971-890c-97becea09076'
|
||||
|
||||
const COMMON_CONTRACTS: { [key: string]: Partial<Activity> | undefined } = {
|
||||
[UNI_ADDRESSES[ChainId.MAINNET].toLowerCase()]: {
|
||||
[UNI_ADDRESS[SupportedChainId.MAINNET].toLowerCase()]: {
|
||||
title: t`UNI Governance`,
|
||||
descriptor: t`Contract Interaction`,
|
||||
logos: [UNI_IMG],
|
||||
@@ -75,9 +76,10 @@ function isSameAddress(a?: string, b?: string) {
|
||||
}
|
||||
|
||||
function callsPositionManagerContract(assetActivity: AssetActivityPartsFragment) {
|
||||
const supportedChain = supportedChainIdFromGQLChain(assetActivity.chain)
|
||||
if (!supportedChain) return false
|
||||
return isSameAddress(assetActivity.transaction.to, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[supportedChain])
|
||||
return isSameAddress(
|
||||
assetActivity.transaction.to,
|
||||
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES[fromGraphQLChain(assetActivity.chain)]
|
||||
)
|
||||
}
|
||||
|
||||
// Gets counts for number of NFTs in each collection present
|
||||
@@ -91,24 +93,15 @@ function getCollectionCounts(nftTransfers: NftTransferPartsFragment[]): { [key:
|
||||
}, {} as { [key: string]: number | undefined })
|
||||
}
|
||||
|
||||
function getSwapTitle(sent: TokenTransferPartsFragment, received: TokenTransferPartsFragment): string | undefined {
|
||||
const supportedSentChain = supportedChainIdFromGQLChain(sent.asset.chain)
|
||||
const supportedReceivedChain = supportedChainIdFromGQLChain(received.asset.chain)
|
||||
if (!supportedSentChain || !supportedReceivedChain) {
|
||||
logSentryErrorForUnsupportedChain({
|
||||
extras: { sentAsset: sent.asset, receivedAsset: received.asset },
|
||||
errorMessage: 'Invalid activity from unsupported chain received from GQL',
|
||||
})
|
||||
return undefined
|
||||
}
|
||||
function getSwapTitle(sent: TokenTransferPartsFragment, received: TokenTransferPartsFragment) {
|
||||
if (
|
||||
sent.tokenStandard === 'NATIVE' &&
|
||||
isSameAddress(nativeOnChain(supportedSentChain).wrapped.address, received.asset.address)
|
||||
isSameAddress(nativeOnChain(fromGraphQLChain(sent.asset.chain)).wrapped.address, received.asset.address)
|
||||
)
|
||||
return t`Wrapped`
|
||||
else if (
|
||||
received.tokenStandard === 'NATIVE' &&
|
||||
isSameAddress(nativeOnChain(supportedReceivedChain).wrapped.address, received.asset.address)
|
||||
isSameAddress(nativeOnChain(fromGraphQLChain(received.asset.chain)).wrapped.address, received.asset.address)
|
||||
) {
|
||||
return t`Unwrapped`
|
||||
} else {
|
||||
@@ -276,17 +269,9 @@ function parseRemoteActivity(assetActivity: AssetActivityPartsFragment): Activit
|
||||
},
|
||||
{ NftTransfer: [], TokenTransfer: [], TokenApproval: [], NftApproval: [], NftApproveForAll: [] }
|
||||
)
|
||||
const supportedChain = supportedChainIdFromGQLChain(assetActivity.chain)
|
||||
if (!supportedChain) {
|
||||
logSentryErrorForUnsupportedChain({
|
||||
extras: { assetActivity },
|
||||
errorMessage: 'Invalid activity from unsupported chain received from GQL',
|
||||
})
|
||||
return undefined
|
||||
}
|
||||
const defaultFields = {
|
||||
hash: assetActivity.transaction.hash,
|
||||
chainId: supportedChain,
|
||||
chainId: fromGraphQLChain(assetActivity.chain),
|
||||
status: assetActivity.transaction.status,
|
||||
timestamp: assetActivity.timestamp,
|
||||
logos: getLogoSrcs(changes),
|
||||
@@ -304,7 +289,7 @@ function parseRemoteActivity(assetActivity: AssetActivityPartsFragment): Activit
|
||||
}
|
||||
}
|
||||
|
||||
export function parseRemoteActivities(assetActivities?: readonly AssetActivityPartsFragment[]) {
|
||||
export function parseRemoteActivities(assetActivities?: AssetActivityPartsFragment[]) {
|
||||
return assetActivities?.reduce((acc: { [hash: string]: Activity }, assetActivity) => {
|
||||
const activity = parseRemoteActivity(assetActivity)
|
||||
if (activity) acc[activity.hash] = activity
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { AssetActivityPartsFragment, TransactionStatus } from 'graphql/data/__generated__/types-and-hooks'
|
||||
|
||||
type Receipt = AssetActivityPartsFragment['transaction']
|
||||
|
||||
export type Activity = {
|
||||
hash: string
|
||||
chainId: ChainId
|
||||
chainId: SupportedChainId
|
||||
status: TransactionStatus
|
||||
timestamp: number
|
||||
title: string
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ChainId, Token } from '@uniswap/sdk-core'
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import { Pool, Position } from '@uniswap/v3-sdk'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { useAllTokensMultichain } from 'hooks/Tokens'
|
||||
import { atom, useAtom } from 'jotai'
|
||||
import { atomWithStorage } from 'jotai/utils'
|
||||
@@ -15,7 +16,7 @@ import { useInterfaceMulticallContracts } from './hooks'
|
||||
|
||||
export type PositionInfo = {
|
||||
owner: string
|
||||
chainId: ChainId
|
||||
chainId: SupportedChainId
|
||||
position: Position
|
||||
pool: Pool
|
||||
details: PositionDetails
|
||||
@@ -58,7 +59,7 @@ export function useCachedPositions(account: string): UseCachedPositionsReturnTyp
|
||||
return [cachedPositions[account], setPositionsAndStaleTimeout]
|
||||
}
|
||||
|
||||
const poolAddressKey = (details: PositionDetails, chainId: ChainId) =>
|
||||
const poolAddressKey = (details: PositionDetails, chainId: SupportedChainId) =>
|
||||
`${chainId}-${details.token0}-${details.token1}-${details.fee}`
|
||||
|
||||
type PoolAddressMap = { [key: string]: string | undefined }
|
||||
@@ -70,11 +71,11 @@ const poolAddressCacheAtom = atomWithStorage<PoolAddressMap>('poolCache', {})
|
||||
export function usePoolAddressCache() {
|
||||
const [cache, updateCache] = useAtom(poolAddressCacheAtom)
|
||||
const get = useCallback(
|
||||
(details: PositionDetails, chainId: ChainId) => cache[poolAddressKey(details, chainId)],
|
||||
(details: PositionDetails, chainId: SupportedChainId) => cache[poolAddressKey(details, chainId)],
|
||||
[cache]
|
||||
)
|
||||
const set = useCallback(
|
||||
(details: PositionDetails, chainId: ChainId, address: string) =>
|
||||
(details: PositionDetails, chainId: SupportedChainId, address: string) =>
|
||||
updateCache((c) => ({ ...c, [poolAddressKey(details, chainId)]: address })),
|
||||
[updateCache]
|
||||
)
|
||||
@@ -103,8 +104,8 @@ function useTokenCache() {
|
||||
return { get, set }
|
||||
}
|
||||
|
||||
type TokenGetterFn = (addresses: string[], chainId: ChainId) => Promise<{ [key: string]: Token | undefined }>
|
||||
export function useGetCachedTokens(chains: ChainId[]): TokenGetterFn {
|
||||
type TokenGetterFn = (addresses: string[], chainId: SupportedChainId) => Promise<{ [key: string]: Token | undefined }>
|
||||
export function useGetCachedTokens(chains: SupportedChainId[]): TokenGetterFn {
|
||||
const allTokens = useAllTokensMultichain()
|
||||
const multicallContracts = useInterfaceMulticallContracts(chains)
|
||||
const tokenCache = useTokenCache()
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ChainId, Token } from '@uniswap/sdk-core'
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import ERC20_ABI from 'abis/erc20.json'
|
||||
import { Erc20Interface } from 'abis/types/Erc20'
|
||||
import { Erc20Bytes32Interface } from 'abis/types/Erc20Bytes32'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { DEFAULT_ERC20_DECIMALS } from 'constants/tokens'
|
||||
import { Interface } from 'ethers/lib/utils'
|
||||
import { UniswapInterfaceMulticall } from 'types/v3'
|
||||
@@ -37,7 +38,7 @@ async function fetchChunk(multicall: UniswapInterfaceMulticall, chunk: Call[]):
|
||||
}
|
||||
}
|
||||
|
||||
function tryParseToken(address: string, chainId: ChainId, data: CallResult[]) {
|
||||
function tryParseToken(address: string, chainId: SupportedChainId, data: CallResult[]) {
|
||||
try {
|
||||
const [nameData, symbolData, decimalsData, nameDataBytes32, symbolDataBytes32] = data
|
||||
|
||||
@@ -60,7 +61,7 @@ function tryParseToken(address: string, chainId: ChainId, data: CallResult[]) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseTokens(addresses: string[], chainId: ChainId, returnData: CallResult[]) {
|
||||
function parseTokens(addresses: string[], chainId: SupportedChainId, returnData: CallResult[]) {
|
||||
const tokenDataSlices = arrayToSlices(returnData, 5)
|
||||
|
||||
return tokenDataSlices.reduce((acc: TokenMap, slice, index) => {
|
||||
@@ -89,7 +90,7 @@ const TokenPromiseCache: { [key: CurrencyKey]: Promise<Token | undefined> | unde
|
||||
// Returns tokens using a single RPC call to the multicall contract
|
||||
export async function getTokensAsync(
|
||||
addresses: string[],
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
multicall: UniswapInterfaceMulticall
|
||||
): Promise<TokenMap> {
|
||||
if (addresses.length === 0) return {}
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import {
|
||||
ChainId,
|
||||
MULTICALL_ADDRESSES,
|
||||
NONFUNGIBLE_POSITION_MANAGER_ADDRESSES as V3NFT_ADDRESSES,
|
||||
Token,
|
||||
} from '@uniswap/sdk-core'
|
||||
import { Token } from '@uniswap/sdk-core'
|
||||
import { AddressMap } from '@uniswap/smart-order-router'
|
||||
import MulticallJSON from '@uniswap/v3-periphery/artifacts/contracts/lens/UniswapInterfaceMulticall.sol/UniswapInterfaceMulticall.json'
|
||||
import NFTPositionManagerJSON from '@uniswap/v3-periphery/artifacts/contracts/NonfungiblePositionManager.sol/NonfungiblePositionManager.json'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { isSupportedChain } from 'constants/chains'
|
||||
import { MULTICALL_ADDRESS, NONFUNGIBLE_POSITION_MANAGER_ADDRESSES as V3NFT_ADDRESSES } from 'constants/addresses'
|
||||
import { isSupportedChain, SupportedChainId } from 'constants/chains'
|
||||
import { RPC_PROVIDERS } from 'constants/providers'
|
||||
import { BaseContract } from 'ethers/lib/ethers'
|
||||
import { ContractInput, useUniswapPricesQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||
@@ -27,7 +23,7 @@ type ContractMap<T extends BaseContract> = { [key: number]: T }
|
||||
function useContractMultichain<T extends BaseContract>(
|
||||
addressMap: AddressMap,
|
||||
ABI: any,
|
||||
chainIds?: ChainId[]
|
||||
chainIds?: SupportedChainId[]
|
||||
): ContractMap<T> {
|
||||
const { chainId: walletChainId, provider: walletProvider } = useWeb3React()
|
||||
|
||||
@@ -39,26 +35,19 @@ function useContractMultichain<T extends BaseContract>(
|
||||
.filter(isSupportedChain)
|
||||
|
||||
return relevantChains.reduce((acc: ContractMap<T>, chainId) => {
|
||||
const provider =
|
||||
walletProvider && walletChainId === chainId
|
||||
? walletProvider
|
||||
: isSupportedChain(chainId)
|
||||
? RPC_PROVIDERS[chainId]
|
||||
: undefined
|
||||
if (provider) {
|
||||
acc[chainId] = getContract(addressMap[chainId] ?? '', ABI, provider) as T
|
||||
}
|
||||
const provider = walletProvider && walletChainId === chainId ? walletProvider : RPC_PROVIDERS[chainId]
|
||||
acc[chainId] = getContract(addressMap[chainId], ABI, provider) as T
|
||||
return acc
|
||||
}, {})
|
||||
}, [ABI, addressMap, chainIds, walletChainId, walletProvider])
|
||||
}
|
||||
|
||||
export function useV3ManagerContracts(chainIds: ChainId[]): ContractMap<NonfungiblePositionManager> {
|
||||
export function useV3ManagerContracts(chainIds: SupportedChainId[]): ContractMap<NonfungiblePositionManager> {
|
||||
return useContractMultichain<NonfungiblePositionManager>(V3NFT_ADDRESSES, NFTPositionManagerJSON.abi, chainIds)
|
||||
}
|
||||
|
||||
export function useInterfaceMulticallContracts(chainIds: ChainId[]): ContractMap<UniswapInterfaceMulticall> {
|
||||
return useContractMultichain<UniswapInterfaceMulticall>(MULTICALL_ADDRESSES, MulticallJSON.abi, chainIds)
|
||||
export function useInterfaceMulticallContracts(chainIds: SupportedChainId[]): ContractMap<UniswapInterfaceMulticall> {
|
||||
return useContractMultichain<UniswapInterfaceMulticall>(MULTICALL_ADDRESS, MulticallJSON.abi, chainIds)
|
||||
}
|
||||
|
||||
type PriceMap = { [key: CurrencyKey]: number | undefined }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { ChainId, WETH9 } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId, WETH9 } from '@uniswap/sdk-core'
|
||||
import { FeeAmount, Pool, Position } from '@uniswap/v3-sdk'
|
||||
import { USDC_MAINNET } from 'constants/tokens'
|
||||
import { mocked } from 'test-utils/mocked'
|
||||
@@ -10,13 +10,11 @@ import useMultiChainPositions from './useMultiChainPositions'
|
||||
|
||||
jest.mock('./useMultiChainPositions')
|
||||
|
||||
jest.spyOn(console, 'warn').mockImplementation()
|
||||
|
||||
const owner = '0xf5b6bb25f5beaea03dd014c6ef9fa9f3926bf36c'
|
||||
|
||||
const pool = new Pool(
|
||||
USDC_MAINNET,
|
||||
WETH9[ChainId.MAINNET],
|
||||
WETH9[SupportedChainId.MAINNET],
|
||||
FeeAmount.MEDIUM,
|
||||
'1851127709498178402383049949138810',
|
||||
'7076437181775065414',
|
||||
@@ -34,7 +32,7 @@ const details = {
|
||||
tokenId: BigNumber.from('0'),
|
||||
operator: '0x0',
|
||||
token0: USDC_MAINNET.address,
|
||||
token1: WETH9[ChainId.MAINNET].address,
|
||||
token1: WETH9[SupportedChainId.MAINNET].address,
|
||||
fee: FeeAmount.MEDIUM,
|
||||
tickLower: -100,
|
||||
tickUpper: 100,
|
||||
@@ -48,7 +46,7 @@ const useMultiChainPositionsReturnValue = {
|
||||
positions: [
|
||||
{
|
||||
owner,
|
||||
chainId: ChainId.MAINNET,
|
||||
chainId: SupportedChainId.MAINNET,
|
||||
position,
|
||||
pool,
|
||||
details,
|
||||
|
||||
@@ -8,12 +8,12 @@ import { useToggleAccountDrawer } from 'components/AccountDrawer'
|
||||
import Row from 'components/Row'
|
||||
import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { useFilterPossiblyMaliciousPositions } from 'hooks/useFilterPossiblyMaliciousPositions'
|
||||
import { useSwitchChain } from 'hooks/useSwitchChain'
|
||||
import { EmptyWalletModule } from 'nft/components/profile/view/EmptyWalletContent'
|
||||
import { useCallback, useMemo, useReducer } from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ThemedText } from 'theme'
|
||||
import { switchChain } from 'utils/switchChain'
|
||||
|
||||
import { ExpandoRow } from '../ExpandoRow'
|
||||
import { PortfolioLogo } from '../PortfolioLogo'
|
||||
@@ -126,12 +126,11 @@ function PositionListItem({ positionInfo }: { positionInfo: PositionInfo }) {
|
||||
const navigate = useNavigate()
|
||||
const toggleWalletDrawer = useToggleAccountDrawer()
|
||||
const { chainId: walletChainId, connector } = useWeb3React()
|
||||
const switchChain = useSwitchChain()
|
||||
const onClick = useCallback(async () => {
|
||||
if (walletChainId !== chainId) await switchChain(connector, chainId)
|
||||
toggleWalletDrawer()
|
||||
navigate('/pool/' + details.tokenId)
|
||||
}, [walletChainId, chainId, switchChain, connector, toggleWalletDrawer, navigate, details.tokenId])
|
||||
}, [walletChainId, chainId, connector, toggleWalletDrawer, navigate, details.tokenId])
|
||||
const analyticsEventProperties = useMemo(
|
||||
() => ({
|
||||
chain_id: chainId,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { ChainId, CurrencyAmount, Token, V3_CORE_FACTORY_ADDRESSES } from '@uniswap/sdk-core'
|
||||
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
|
||||
import IUniswapV3PoolStateJSON from '@uniswap/v3-core/artifacts/contracts/interfaces/pool/IUniswapV3PoolState.sol/IUniswapV3PoolState.json'
|
||||
import { computePoolAddress, Pool, Position } from '@uniswap/v3-sdk'
|
||||
import { V3_CORE_FACTORY_ADDRESSES } from 'constants/addresses'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { DEFAULT_ERC20_DECIMALS } from 'constants/tokens'
|
||||
import { BigNumber } from 'ethers/lib/ethers'
|
||||
import { Interface } from 'ethers/lib/utils'
|
||||
import { useFilterChainsForAvalanche } from 'featureFlags/flags/avalanche'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { PositionDetails } from 'types/position'
|
||||
import { NonfungiblePositionManager, UniswapInterfaceMulticall } from 'types/v3'
|
||||
@@ -17,7 +18,7 @@ import { useInterfaceMulticallContracts, usePoolPriceMap, useV3ManagerContracts
|
||||
|
||||
function createPositionInfo(
|
||||
owner: string,
|
||||
chainId: ChainId,
|
||||
chainId: SupportedChainId,
|
||||
details: PositionDetails,
|
||||
slot0: any,
|
||||
tokenA: Token,
|
||||
@@ -41,13 +42,11 @@ type FeeAmounts = [BigNumber, BigNumber]
|
||||
const MAX_UINT128 = BigNumber.from(2).pow(128).sub(1)
|
||||
|
||||
const DEFAULT_CHAINS = [
|
||||
ChainId.MAINNET,
|
||||
ChainId.ARBITRUM_ONE,
|
||||
ChainId.OPTIMISM,
|
||||
ChainId.POLYGON,
|
||||
ChainId.CELO,
|
||||
ChainId.BNB,
|
||||
ChainId.AVALANCHE,
|
||||
SupportedChainId.MAINNET,
|
||||
SupportedChainId.ARBITRUM_ONE,
|
||||
SupportedChainId.OPTIMISM,
|
||||
SupportedChainId.POLYGON,
|
||||
SupportedChainId.CELO,
|
||||
]
|
||||
|
||||
type UseMultiChainPositionsData = { positions?: PositionInfo[]; loading: boolean }
|
||||
@@ -62,11 +61,10 @@ type UseMultiChainPositionsData = { positions?: PositionInfo[]; loading: boolean
|
||||
* @returns positions, fees
|
||||
*/
|
||||
export default function useMultiChainPositions(account: string, chains = DEFAULT_CHAINS): UseMultiChainPositionsData {
|
||||
const gatedChains = useFilterChainsForAvalanche(chains)
|
||||
const pms = useV3ManagerContracts(gatedChains)
|
||||
const multicalls = useInterfaceMulticallContracts(gatedChains)
|
||||
const pms = useV3ManagerContracts(chains)
|
||||
const multicalls = useInterfaceMulticallContracts(chains)
|
||||
|
||||
const getTokens = useGetCachedTokens(gatedChains)
|
||||
const getTokens = useGetCachedTokens(chains)
|
||||
const poolAddressCache = usePoolAddressCache()
|
||||
|
||||
const [cachedPositions, setPositions] = useCachedPositions(account)
|
||||
@@ -119,7 +117,7 @@ export default function useMultiChainPositions(account: string, chains = DEFAULT
|
||||
|
||||
// Combines PositionDetails with Pool data to build our return type
|
||||
const fetchPositionInfo = useCallback(
|
||||
async (positionDetails: PositionDetails[], chainId: ChainId, multicall: UniswapInterfaceMulticall) => {
|
||||
async (positionDetails: PositionDetails[], chainId: SupportedChainId, multicall: UniswapInterfaceMulticall) => {
|
||||
const poolInterface = new Interface(IUniswapV3PoolStateJSON.abi) as UniswapV3PoolInterface
|
||||
const tokens = await getTokens(
|
||||
positionDetails.flatMap((details) => [details.token0, details.token1]),
|
||||
@@ -160,7 +158,7 @@ export default function useMultiChainPositions(account: string, chains = DEFAULT
|
||||
)
|
||||
|
||||
const fetchPositionsForChain = useCallback(
|
||||
async (chainId: ChainId): Promise<PositionInfo[]> => {
|
||||
async (chainId: SupportedChainId): Promise<PositionInfo[]> => {
|
||||
try {
|
||||
const pm = pms[chainId]
|
||||
const multicall = multicalls[chainId]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from '@uniswap/sdk-core'
|
||||
import { DAI_ARBITRUM } from '@uniswap/smart-order-router'
|
||||
import { BRIDGED_USDC_ARBITRUM, DAI, USDC_MAINNET } from 'constants/tokens'
|
||||
import { render } from 'test-utils/render'
|
||||
@@ -7,13 +7,13 @@ import { PortfolioLogo } from './PortfolioLogo'
|
||||
|
||||
describe('PortfolioLogo', () => {
|
||||
it('renders without L2 icon', () => {
|
||||
const { container } = render(<PortfolioLogo chainId={ChainId.MAINNET} currencies={[DAI, USDC_MAINNET]} />)
|
||||
const { container } = render(<PortfolioLogo chainId={SupportedChainId.MAINNET} currencies={[DAI, USDC_MAINNET]} />)
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders with L2 icon', () => {
|
||||
const { container } = render(
|
||||
<PortfolioLogo chainId={ChainId.ARBITRUM_ONE} currencies={[DAI_ARBITRUM, BRIDGED_USDC_ARBITRUM]} />
|
||||
<PortfolioLogo chainId={SupportedChainId.ARBITRUM_ONE} currencies={[DAI_ARBITRUM, BRIDGED_USDC_ARBITRUM]} />
|
||||
)
|
||||
expect(container).toMatchSnapshot()
|
||||
})
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import blankTokenUrl from 'assets/svg/blank_token.svg'
|
||||
import { ReactComponent as UnknownStatus } from 'assets/svg/contract-interaction.svg'
|
||||
import { LogoImage, MissingImageLogo } from 'components/Logo/AssetLogo'
|
||||
import { Unicon } from 'components/Unicon'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import useTokenLogoSource from 'hooks/useAssetLogoSource'
|
||||
import useENSAvatar from 'hooks/useENSAvatar'
|
||||
import React from 'react'
|
||||
@@ -36,7 +37,7 @@ const DoubleLogoContainer = styled.div`
|
||||
`
|
||||
|
||||
type MultiLogoProps = {
|
||||
chainId: ChainId
|
||||
chainId: SupportedChainId
|
||||
accountAddress?: string
|
||||
currencies?: Array<Currency | undefined>
|
||||
images?: (string | undefined)[]
|
||||
@@ -84,7 +85,7 @@ const L2LogoContainer = styled.div<{ $backgroundColor?: string }>`
|
||||
* Renders an image by prioritizing a list of sources, and then eventually a fallback triangle alert
|
||||
*/
|
||||
export function PortfolioLogo({
|
||||
chainId = ChainId.MAINNET,
|
||||
chainId = SupportedChainId.MAINNET,
|
||||
accountAddress,
|
||||
currencies,
|
||||
images,
|
||||
@@ -141,7 +142,7 @@ export function PortfolioLogo({
|
||||
}
|
||||
|
||||
const L2Logo =
|
||||
chainId !== ChainId.MAINNET && chainLogo ? (
|
||||
chainId !== SupportedChainId.MAINNET && chainLogo ? (
|
||||
<L2LogoContainer $backgroundColor={squareLogoUrl ? theme.backgroundSurface : theme.textPrimary}>
|
||||
{squareLogoUrl ? (
|
||||
<SquareChainLogo src={chainLogo} alt="chainLogo" />
|
||||
|
||||
@@ -4,12 +4,7 @@ import { formatNumber, NumberType } from '@uniswap/conedison/format'
|
||||
import Row from 'components/Row'
|
||||
import { formatDelta } from 'components/Tokens/TokenDetails/PriceChart'
|
||||
import { PortfolioBalancesQuery, usePortfolioBalancesQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import {
|
||||
getTokenDetailsURL,
|
||||
GQL_MAINNET_CHAINS,
|
||||
gqlToCurrency,
|
||||
logSentryErrorForUnsupportedChain,
|
||||
} from 'graphql/data/util'
|
||||
import { getTokenDetailsURL, gqlToCurrency } from 'graphql/data/util'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { EmptyWalletModule } from 'nft/components/profile/view/EmptyWalletContent'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
@@ -36,7 +31,7 @@ export default function Tokens({ account }: { account: string }) {
|
||||
const [showHiddenTokens, setShowHiddenTokens] = useState(false)
|
||||
|
||||
const { data } = usePortfolioBalancesQuery({
|
||||
variables: { ownerAddress: account, chains: GQL_MAINNET_CHAINS },
|
||||
variables: { ownerAddress: account },
|
||||
fetchPolicy: 'cache-only', // PrefetchBalancesWrapper handles balance fetching/staleness; this component only reads from cache
|
||||
errorPolicy: 'all',
|
||||
})
|
||||
@@ -108,13 +103,6 @@ function TokenRow({ token, quantity, denominatedValue, tokenProjectMarket }: Tok
|
||||
}, [navigate, token, toggleWalletDrawer])
|
||||
|
||||
const currency = gqlToCurrency(token)
|
||||
if (!currency) {
|
||||
logSentryErrorForUnsupportedChain({
|
||||
extras: { token },
|
||||
errorMessage: 'Token from unsupported chain received from Mini Portfolio Token Balance Query',
|
||||
})
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<TraceEvent
|
||||
events={[BrowserEvent.onClick]}
|
||||
|
||||
@@ -4,12 +4,13 @@ import { BrowserEvent, InterfaceElementName, InterfaceSectionName, SharedEventNa
|
||||
import Column from 'components/Column'
|
||||
import { LoaderV2 } from 'components/Icons/LoadingSpinner'
|
||||
import { AutoRow } from 'components/Row'
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { useIsNftPage } from 'hooks/useIsNftPage'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
|
||||
import { useHasPendingTransactions } from 'state/transactions/hooks'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { BREAKPOINTS, ThemedText } from 'theme'
|
||||
import { ThemedText } from 'theme'
|
||||
|
||||
import { ActivityTab } from './Activity'
|
||||
import NFTs from './NFTs'
|
||||
@@ -24,10 +25,6 @@ const Wrapper = styled(Column)`
|
||||
height: 100%;
|
||||
gap: 12px;
|
||||
|
||||
@media screen and (max-width: ${BREAKPOINTS.sm}px) {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
|
||||
${PortfolioRowWrapper} {
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.hoverDefault};
|
||||
@@ -98,8 +95,8 @@ export default function MiniPortfolio({ account }: { account: string }) {
|
||||
const isNftPage = useIsNftPage()
|
||||
const theme = useTheme()
|
||||
const [currentPage, setCurrentPage] = useState(isNftPage ? 1 : 0)
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
const [activityUnread, setActivityUnread] = useState(false)
|
||||
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
|
||||
|
||||
const { component: Page, key: currentKey } = Pages[currentPage]
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { usePortfolioBalancesLazyQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { GQL_MAINNET_CHAINS } from 'graphql/data/util'
|
||||
import usePrevious from 'hooks/usePrevious'
|
||||
import { PropsWithChildren, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useAllTransactions } from 'state/transactions/hooks'
|
||||
@@ -45,7 +44,7 @@ export default function PrefetchBalancesWrapper({ children }: PropsWithChildren)
|
||||
const [hasUnfetchedBalances, setHasUnfetchedBalances] = useState(true)
|
||||
const fetchBalances = useCallback(() => {
|
||||
if (account) {
|
||||
prefetchPortfolioBalances({ variables: { ownerAddress: account, chains: GQL_MAINNET_CHAINS } })
|
||||
prefetchPortfolioBalances({ variables: { ownerAddress: account } })
|
||||
setHasUnfetchedBalances(false)
|
||||
}
|
||||
}, [account, prefetchPortfolioBalances])
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { sendAnalyticsEvent } from '@uniswap/analytics'
|
||||
import { InterfaceElementName } from '@uniswap/analytics-events'
|
||||
import { WalletConnect as WalletConnectv2 } from '@web3-react/walletconnect-v2'
|
||||
import { WalletConnect } from '@web3-react/walletconnect'
|
||||
import Column, { AutoColumn } from 'components/Column'
|
||||
import Modal from 'components/Modal'
|
||||
import { RowBetween } from 'components/Row'
|
||||
import { uniwalletWCV2ConnectConnection } from 'connection'
|
||||
import { uniwalletConnectConnection } from 'connection'
|
||||
import { ActivationStatus, useActivationState } from 'connection/activate'
|
||||
import { ConnectionType } from 'connection/types'
|
||||
import { UniwalletConnect as UniwalletConnectV2 } from 'connection/WalletConnectV2'
|
||||
import { UniwalletConnect } from 'connection/WalletConnect'
|
||||
import { QRCodeSVG } from 'qrcode.react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
@@ -44,14 +44,16 @@ export default function UniwalletModal() {
|
||||
// Displays the modal if a Uniswap Wallet Connection is pending & qrcode URI is available
|
||||
const open =
|
||||
activationState.status === ActivationStatus.PENDING &&
|
||||
activationState.connection.type === ConnectionType.UNISWAP_WALLET_V2 &&
|
||||
activationState.connection.type === ConnectionType.UNISWAP_WALLET &&
|
||||
!!uri
|
||||
|
||||
useEffect(() => {
|
||||
const connectorV2 = uniwalletWCV2ConnectConnection.connector as WalletConnectv2
|
||||
connectorV2.events.addListener(UniwalletConnectV2.UNI_URI_AVAILABLE, (uri: string) => {
|
||||
uri && setUri(uri)
|
||||
})
|
||||
;(uniwalletConnectConnection.connector as WalletConnect).events.addListener(
|
||||
UniwalletConnect.UNI_URI_AVAILABLE,
|
||||
(uri) => {
|
||||
uri && setUri(uri)
|
||||
}
|
||||
)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import type { TransactionResponse } from '@ethersproject/providers'
|
||||
import { UNISWAP_NFT_AIRDROP_CLAIM_ADDRESS } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import uniswapNftAirdropClaim from 'abis/uniswap-nft-airdrop-claim.json'
|
||||
import airdropBackgroundv2 from 'assets/images/airdopBackground.png'
|
||||
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
|
||||
import { OpacityHoverState } from 'components/Common'
|
||||
import Loader from 'components/Icons/LoadingSpinner'
|
||||
import { UNISWAP_NFT_AIRDROP_CLAIM_ADDRESS } from 'constants/addresses'
|
||||
import { useContract } from 'hooks/useContract'
|
||||
import { ChevronRightIcon } from 'nft/components/icons'
|
||||
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { TraceEvent } from '@uniswap/analytics'
|
||||
import { BrowserEvent, InterfaceElementName, SwapEventName } from '@uniswap/analytics-events'
|
||||
import { formatCurrencyAmount, NumberType } from '@uniswap/conedison/format'
|
||||
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
|
||||
import { Pair } from '@uniswap/v2-sdk'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
@@ -14,6 +13,7 @@ import { ReactNode, useCallback, useState } from 'react'
|
||||
import { Lock } from 'react-feather'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
|
||||
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
|
||||
import { useCurrencyBalance } from '../../state/connection/hooks'
|
||||
@@ -323,7 +323,7 @@ export default function SwapCurrencyInputPanel({
|
||||
renderBalance ? (
|
||||
renderBalance(selectedCurrencyBalance)
|
||||
) : (
|
||||
<Trans>Balance: {formatCurrencyAmount(selectedCurrencyBalance, NumberType.TokenNonTx)}</Trans>
|
||||
<Trans>Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)}</Trans>
|
||||
)
|
||||
) : null}
|
||||
</ThemedText.DeprecatedBody>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { BaseVariant, FeatureFlag, featureFlagSettings, useUpdateFlag } from 'featureFlags'
|
||||
import { useAvalancheFlag } from 'featureFlags/flags/avalanche'
|
||||
import { DetailsV2Variant, useDetailsV2Flag } from 'featureFlags/flags/nftDetails'
|
||||
import { useRoutingAPIForPriceFlag } from 'featureFlags/flags/priceRoutingApi'
|
||||
import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/traceJsonRpc'
|
||||
import { UnifiedRouterVariant, useRoutingAPIV2Flag } from 'featureFlags/flags/unifiedRouter'
|
||||
import { useWalletConnectV2Flag } from 'featureFlags/flags/walletConnectV2'
|
||||
import { useUpdateAtom } from 'jotai/utils'
|
||||
import { Children, PropsWithChildren, ReactElement, ReactNode, useCallback, useState } from 'react'
|
||||
import { X } from 'react-feather'
|
||||
@@ -209,6 +210,12 @@ export default function FeatureFlagModal() {
|
||||
featureFlag={FeatureFlag.detailsV2}
|
||||
label="Use the new details page for nfts"
|
||||
/>
|
||||
<FeatureFlagOption
|
||||
variant={UnifiedRouterVariant}
|
||||
value={useRoutingAPIV2Flag()}
|
||||
featureFlag={FeatureFlag.uraEnabled}
|
||||
label="Enable the Unified Routing API"
|
||||
/>
|
||||
<FeatureFlagOption
|
||||
variant={BaseVariant}
|
||||
value={useRoutingAPIForPriceFlag()}
|
||||
@@ -217,9 +224,9 @@ export default function FeatureFlagModal() {
|
||||
/>
|
||||
<FeatureFlagOption
|
||||
variant={BaseVariant}
|
||||
value={useAvalancheFlag()}
|
||||
featureFlag={FeatureFlag.avalanche}
|
||||
label="Enable Avalanche chain"
|
||||
value={useWalletConnectV2Flag()}
|
||||
featureFlag={FeatureFlag.walletConnectV2}
|
||||
label="Uses WalletConnect V2 as default wallet connect connection"
|
||||
/>
|
||||
<FeatureFlagGroup name="Debug">
|
||||
<FeatureFlagOption
|
||||
|
||||
@@ -1,40 +1,39 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId, SUPPORTED_CHAINS } from '@uniswap/sdk-core'
|
||||
import { FeeAmount } from '@uniswap/v3-sdk'
|
||||
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
export const FEE_AMOUNT_DETAIL: Record<
|
||||
FeeAmount,
|
||||
{ label: string; description: ReactNode; supportedChains: readonly ChainId[] }
|
||||
{ label: string; description: ReactNode; supportedChains: SupportedChainId[] }
|
||||
> = {
|
||||
[FeeAmount.LOWEST]: {
|
||||
label: '0.01',
|
||||
description: <Trans>Best for very stable pairs.</Trans>,
|
||||
supportedChains: [
|
||||
ChainId.ARBITRUM_ONE,
|
||||
ChainId.BNB,
|
||||
ChainId.CELO,
|
||||
ChainId.CELO_ALFAJORES,
|
||||
ChainId.MAINNET,
|
||||
ChainId.OPTIMISM,
|
||||
ChainId.POLYGON,
|
||||
ChainId.POLYGON_MUMBAI,
|
||||
ChainId.AVALANCHE,
|
||||
SupportedChainId.ARBITRUM_ONE,
|
||||
SupportedChainId.BNB,
|
||||
SupportedChainId.CELO,
|
||||
SupportedChainId.CELO_ALFAJORES,
|
||||
SupportedChainId.MAINNET,
|
||||
SupportedChainId.OPTIMISM,
|
||||
SupportedChainId.POLYGON,
|
||||
SupportedChainId.POLYGON_MUMBAI,
|
||||
],
|
||||
},
|
||||
[FeeAmount.LOW]: {
|
||||
label: '0.05',
|
||||
description: <Trans>Best for stable pairs.</Trans>,
|
||||
supportedChains: SUPPORTED_CHAINS,
|
||||
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
|
||||
},
|
||||
[FeeAmount.MEDIUM]: {
|
||||
label: '0.3',
|
||||
description: <Trans>Best for most pairs.</Trans>,
|
||||
supportedChains: SUPPORTED_CHAINS,
|
||||
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
|
||||
},
|
||||
[FeeAmount.HIGH]: {
|
||||
label: '1',
|
||||
description: <Trans>Best for exotic pairs.</Trans>,
|
||||
supportedChains: SUPPORTED_CHAINS,
|
||||
supportedChains: ALL_SUPPORTED_CHAIN_IDS,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import { render } from 'test-utils/render'
|
||||
|
||||
import StatusIcon from './StatusIcon'
|
||||
|
||||
const ACCOUNT = '0x0'
|
||||
|
||||
jest.mock('../../hooks/useSocksBalance', () => ({
|
||||
useHasSocks: () => true,
|
||||
}))
|
||||
@@ -15,15 +13,15 @@ describe('StatusIcon', () => {
|
||||
describe('with no account', () => {
|
||||
it('renders children in correct order', () => {
|
||||
const supportedConnections = getConnections()
|
||||
const injectedConnection = supportedConnections[2]
|
||||
const component = render(<StatusIcon account={ACCOUNT} connection={injectedConnection} />)
|
||||
const injectedConnection = supportedConnections[1]
|
||||
const component = render(<StatusIcon connection={injectedConnection} />)
|
||||
expect(component.getByTestId('StatusIconRoot')).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders without mini icons', () => {
|
||||
const supportedConnections = getConnections()
|
||||
const injectedConnection = supportedConnections[2]
|
||||
const component = render(<StatusIcon account={ACCOUNT} connection={injectedConnection} showMiniIcons={false} />)
|
||||
const injectedConnection = supportedConnections[1]
|
||||
const component = render(<StatusIcon connection={injectedConnection} showMiniIcons={false} />)
|
||||
expect(component.getByTestId('StatusIconRoot').children.length).toEqual(0)
|
||||
})
|
||||
})
|
||||
@@ -38,16 +36,16 @@ describe('StatusIcon', () => {
|
||||
|
||||
it('renders children in correct order', () => {
|
||||
const supportedConnections = getConnections()
|
||||
const injectedConnection = supportedConnections[2]
|
||||
const component = render(<StatusIcon account={ACCOUNT} connection={injectedConnection} />)
|
||||
const injectedConnection = supportedConnections[1]
|
||||
const component = render(<StatusIcon connection={injectedConnection} />)
|
||||
expect(component.getByTestId('StatusIconRoot')).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('renders without mini icons', () => {
|
||||
const supportedConnections = getConnections()
|
||||
const injectedConnection = supportedConnections[2]
|
||||
const component = render(<StatusIcon account={ACCOUNT} connection={injectedConnection} showMiniIcons={false} />)
|
||||
expect(component.getByTestId('StatusIconRoot').children.length).toEqual(0)
|
||||
const injectedConnection = supportedConnections[1]
|
||||
const component = render(<StatusIcon connection={injectedConnection} showMiniIcons={false} />)
|
||||
expect(component.getByTestId('StatusIconRoot').children.length).toEqual(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { Unicon } from 'components/Unicon'
|
||||
import { Connection, ConnectionType } from 'connection/types'
|
||||
import useENSAvatar from 'hooks/useENSAvatar'
|
||||
@@ -66,25 +67,24 @@ const MiniWalletIcon = ({ connection, side }: { connection: Connection; side: 'l
|
||||
)
|
||||
}
|
||||
|
||||
const MainWalletIcon = ({ account, connection, size }: { account: string; connection: Connection; size: number }) => {
|
||||
const MainWalletIcon = ({ connection, size }: { connection: Connection; size: number }) => {
|
||||
const { account } = useWeb3React()
|
||||
const { avatar } = useENSAvatar(account ?? undefined)
|
||||
|
||||
if (!account) {
|
||||
return null
|
||||
} else if (avatar || (connection.type === ConnectionType.INJECTED && connection.getName() === 'MetaMask')) {
|
||||
return <Identicon account={account} size={size} />
|
||||
return <Identicon size={size} />
|
||||
} else {
|
||||
return <Unicon address={account} size={size} />
|
||||
}
|
||||
}
|
||||
|
||||
export default function StatusIcon({
|
||||
account,
|
||||
connection,
|
||||
size = 16,
|
||||
showMiniIcons = true,
|
||||
}: {
|
||||
account: string
|
||||
connection: Connection
|
||||
size?: number
|
||||
showMiniIcons?: boolean
|
||||
@@ -93,7 +93,7 @@ export default function StatusIcon({
|
||||
|
||||
return (
|
||||
<IconWrapper size={size} data-testid="StatusIconRoot">
|
||||
<MainWalletIcon account={account} connection={connection} size={size} />
|
||||
<MainWalletIcon connection={connection} size={size} />
|
||||
{showMiniIcons && <MiniWalletIcon connection={connection} side="right" />}
|
||||
{hasSocks && showMiniIcons && <Socks />}
|
||||
</IconWrapper>
|
||||
|
||||
@@ -108,13 +108,155 @@ exports[`StatusIcon with account renders children in correct order 1`] = `
|
||||
data-testid="StatusIconRoot"
|
||||
size="16"
|
||||
>
|
||||
<div
|
||||
style="height: 16px; width: 16px; position: relative;"
|
||||
>
|
||||
<div
|
||||
style="height: 16px; width: 16px; overflow: visible; position: absolute;"
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<defs>
|
||||
<defs>
|
||||
<mask
|
||||
id="container-mask0x52270d8234b864dcAC9947f510CE9275A8a116Db16"
|
||||
>
|
||||
<rect
|
||||
fill="white"
|
||||
height="100%"
|
||||
width="100%"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<g
|
||||
transform="scale(0.4444444444444444)
|
||||
translate(0, 0)"
|
||||
>
|
||||
<path
|
||||
d="M18.1309 3.25957C9.91898 3.40293 3.14567 10.1762 3.00231 18.3882C2.85896 26.6001 9.39985 33.141 17.6118 32.9977C25.8238 32.8543 32.5971 26.081 32.7404 17.8691L33 3L18.1309 3.25957Z"
|
||||
fill="black"
|
||||
/>
|
||||
</g>
|
||||
</mask>
|
||||
<mask
|
||||
id="shape-mask0x52270d8234b864dcAC9947f510CE9275A8a116Db16"
|
||||
>
|
||||
<rect
|
||||
fill="white"
|
||||
height="100%"
|
||||
width="100%"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<g
|
||||
transform="scale(0.4444444444444444)
|
||||
translate(10, 10)"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M13.6569 13.6568C12.0059 10.0663 12.0059 5.93368 13.6569 2.34314C10.0663 3.99414 5.93368 3.99414 2.34315 2.34314C3.99414 5.93368 3.99414 10.0663 2.34315 13.6568C5.93368 12.0059 10.0663 12.0059 13.6569 13.6568ZM8 11C9.65685 11 11 9.65686 11 8.00001C11 6.34315 9.65685 5.00001 8 5.00001C6.34315 5.00001 5 6.34315 5 8.00001C5 9.65686 6.34315 11 8 11Z"
|
||||
fill="black"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</g>
|
||||
</mask>
|
||||
<mask
|
||||
id="mask0x52270d8234b864dcAC9947f510CE9275A8a116Db16"
|
||||
>
|
||||
<g
|
||||
fill="white"
|
||||
>
|
||||
<g
|
||||
mask="url(#shape-mask0x52270d8234b864dcAC9947f510CE9275A8a116Db16)"
|
||||
>
|
||||
<g
|
||||
transform="scale(0.4444444444444444)"
|
||||
>
|
||||
<path
|
||||
d="M18.1309 3.25957C9.91898 3.40293 3.14567 10.1762 3.00231 18.3882C2.85896 26.6001 9.39985 33.141 17.6118 32.9977C25.8238 32.8543 32.5971 26.081 32.7404 17.8691L33 3L18.1309 3.25957Z"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
mask="url(#container-mask0x52270d8234b864dcAC9947f510CE9275A8a116Db16)"
|
||||
>
|
||||
<g
|
||||
transform="scale(0.4444444444444444)
|
||||
translate(10, 10)"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M13.6569 13.6568C12.0059 10.0663 12.0059 5.93368 13.6569 2.34314C10.0663 3.99414 5.93368 3.99414 2.34315 2.34314C3.99414 5.93368 3.99414 10.0663 2.34315 13.6568C5.93368 12.0059 10.0663 12.0059 13.6569 13.6568ZM8 11C9.65685 11 11 9.65686 11 8.00001C11 6.34315 9.65685 5.00001 8 5.00001C6.34315 5.00001 5 6.34315 5 8.00001C5 9.65686 6.34315 11 8 11Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</mask>
|
||||
</defs>
|
||||
<lineargradient
|
||||
id="gradient0x52270d8234b864dcAC9947f510CE9275A8a116Db16"
|
||||
>
|
||||
<stop
|
||||
offset="0%"
|
||||
stop-color="#36DBFF"
|
||||
/>
|
||||
<stop
|
||||
offset="100%"
|
||||
stop-color="#B8C3B7"
|
||||
/>
|
||||
</lineargradient>
|
||||
<filter
|
||||
height="200%"
|
||||
id="blur0x52270d8234b864dcAC9947f510CE9275A8a116Db16"
|
||||
width="200%"
|
||||
x="-50%"
|
||||
y="-50%"
|
||||
>
|
||||
<fegaussianblur
|
||||
in="SourceGraphic"
|
||||
stdDeviation="5.333333333333333"
|
||||
/>
|
||||
</filter>
|
||||
</defs>
|
||||
<g
|
||||
mask="url(#mask0x52270d8234b864dcAC9947f510CE9275A8a116Db16)"
|
||||
>
|
||||
<rect
|
||||
fill="url(#gradient0x52270d8234b864dcAC9947f510CE9275A8a116Db16)"
|
||||
height="100%"
|
||||
width="100%"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="black"
|
||||
height="100%"
|
||||
opacity="0.08"
|
||||
width="100%"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<ellipse
|
||||
cx="8"
|
||||
cy="0"
|
||||
fill="#9D99F5"
|
||||
filter="url(#blur0x52270d8234b864dcAC9947f510CE9275A8a116Db16)"
|
||||
rx="8"
|
||||
ry="8"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="c1"
|
||||
>
|
||||
<img
|
||||
alt="WalletConnect icon"
|
||||
alt="Install MetaMask icon"
|
||||
class="c2"
|
||||
src="walletconnect-icon.svg"
|
||||
src="metamask-icon.svg"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
@@ -240,9 +382,9 @@ exports[`StatusIcon with no account renders children in correct order 1`] = `
|
||||
class="c1"
|
||||
>
|
||||
<img
|
||||
alt="WalletConnect icon"
|
||||
alt="Install MetaMask icon"
|
||||
class="c2"
|
||||
src="walletconnect-icon.svg"
|
||||
src="metamask-icon.svg"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import jazzicon from '@metamask/jazzicon'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import useENSAvatar from 'hooks/useENSAvatar'
|
||||
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
@@ -17,7 +18,8 @@ const StyledAvatar = styled.img`
|
||||
border-radius: inherit;
|
||||
`
|
||||
|
||||
export default function Identicon({ account, size }: { account: string; size?: number }) {
|
||||
export default function Identicon({ size }: { size?: number }) {
|
||||
const { account } = useWeb3React()
|
||||
const { avatar } = useENSAvatar(account ?? undefined)
|
||||
const [fetchable, setFetchable] = useState(true)
|
||||
const iconSize = size ?? 24
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import useTokenLogoSource from 'hooks/useAssetLogoSource'
|
||||
import React from 'react'
|
||||
import styled, { css } from 'styled-components/macro'
|
||||
@@ -63,7 +63,7 @@ const L2NetworkLogo = styled.div<{ networkUrl?: string; parentSize: string }>`
|
||||
export default function AssetLogo({
|
||||
isNative,
|
||||
address,
|
||||
chainId = ChainId.MAINNET,
|
||||
chainId = SupportedChainId.MAINNET,
|
||||
symbol,
|
||||
backupImg,
|
||||
size = '24px',
|
||||
|
||||
@@ -3,7 +3,7 @@ import { TokenStandard } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { SearchToken } from 'graphql/data/SearchTokens'
|
||||
import { TokenQueryData } from 'graphql/data/Token'
|
||||
import { TopToken } from 'graphql/data/TopTokens'
|
||||
import { supportedChainIdFromGQLChain } from 'graphql/data/util'
|
||||
import { CHAIN_NAME_TO_CHAIN_ID } from 'graphql/data/util'
|
||||
|
||||
import AssetLogo, { AssetLogoBaseProps } from './AssetLogo'
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function QueryTokenLogo(
|
||||
token?: TopToken | TokenQueryData | SearchToken
|
||||
}
|
||||
) {
|
||||
const chainId = props.token?.chain ? supportedChainIdFromGQLChain(props.token?.chain) : undefined
|
||||
const chainId = props.token?.chain ? CHAIN_NAME_TO_CHAIN_ID[props.token?.chain] : undefined
|
||||
|
||||
return (
|
||||
<AssetLogo
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { t } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { WalletConnect } from '@web3-react/walletconnect-v2'
|
||||
import { showTestnetsAtom } from 'components/AccountDrawer/TestnetsToggle'
|
||||
import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { getConnection } from 'connection'
|
||||
import { ConnectionType } from 'connection/types'
|
||||
import { WalletConnectV2 } from 'connection/WalletConnectV2'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { L1_CHAIN_IDS, L2_CHAIN_IDS, TESTNET_CHAIN_IDS, UniWalletSupportedChains } from 'constants/chains'
|
||||
import { useIsAvalancheEnabled } from 'featureFlags/flags/avalanche'
|
||||
import {
|
||||
L1_CHAIN_IDS,
|
||||
L2_CHAIN_IDS,
|
||||
SupportedChainId,
|
||||
TESTNET_CHAIN_IDS,
|
||||
UniWalletSupportedChains,
|
||||
} from 'constants/chains'
|
||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||
import useSelectChain from 'hooks/useSelectChain'
|
||||
import useSyncChainQuery from 'hooks/useSyncChainQuery'
|
||||
@@ -17,10 +21,9 @@ import { Box } from 'nft/components/Box'
|
||||
import { Portal } from 'nft/components/common/Portal'
|
||||
import { Column, Row } from 'nft/components/Flex'
|
||||
import { useIsMobile } from 'nft/hooks'
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather'
|
||||
import { useTheme } from 'styled-components/macro'
|
||||
import { getSupportedChainIdsFromWalletConnectSession } from 'utils/getSupportedChainIdsFromWalletConnectSession'
|
||||
|
||||
import * as styles from './ChainSelector.css'
|
||||
import ChainSelectorRow from './ChainSelectorRow'
|
||||
@@ -32,15 +35,26 @@ interface ChainSelectorProps {
|
||||
leftAlign?: boolean
|
||||
}
|
||||
|
||||
function useWalletSupportedChains(): ChainId[] {
|
||||
// accounts is an array of strings in the format of "eip155:<chainId>:<address>"
|
||||
function getChainsFromEIP155Accounts(accounts?: string[]): SupportedChainId[] {
|
||||
if (!accounts) return []
|
||||
return accounts
|
||||
.map((account) => {
|
||||
const splitAccount = account.split(':')
|
||||
return splitAccount[1] ? parseInt(splitAccount[1]) : undefined
|
||||
})
|
||||
.filter((x) => x !== undefined) as SupportedChainId[]
|
||||
}
|
||||
|
||||
function useWalletSupportedChains() {
|
||||
const { connector } = useWeb3React()
|
||||
|
||||
const connectionType = getConnection(connector).type
|
||||
|
||||
switch (connectionType) {
|
||||
case ConnectionType.WALLET_CONNECT_V2:
|
||||
return getSupportedChainIdsFromWalletConnectSession((connector as WalletConnectV2).provider?.session)
|
||||
case ConnectionType.UNISWAP_WALLET_V2:
|
||||
return getChainsFromEIP155Accounts((connector as WalletConnect).provider?.session?.namespaces.eip155.accounts)
|
||||
case ConnectionType.UNISWAP_WALLET:
|
||||
return UniWalletSupportedChains
|
||||
default:
|
||||
return NETWORK_SELECTOR_CHAINS
|
||||
@@ -51,30 +65,13 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
||||
const { chainId } = useWeb3React()
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||
const isMobile = useIsMobile()
|
||||
const isAvalancheEnabled = useIsAvalancheEnabled()
|
||||
|
||||
const theme = useTheme()
|
||||
|
||||
const showTestnets = useAtomValue(showTestnetsAtom)
|
||||
const walletSupportsChain = useWalletSupportedChains()
|
||||
|
||||
const [supportedChains, unsupportedChains] = useMemo(() => {
|
||||
const { supported, unsupported } = NETWORK_SELECTOR_CHAINS.filter(
|
||||
(chain: number) =>
|
||||
(showTestnets || !TESTNET_CHAIN_IDS.includes(chain)) && (isAvalancheEnabled || chain !== ChainId.AVALANCHE)
|
||||
).reduce(
|
||||
(acc, chain) => {
|
||||
if (walletSupportsChain.includes(chain)) {
|
||||
acc.supported.push(chain)
|
||||
} else {
|
||||
acc.unsupported.push(chain)
|
||||
}
|
||||
return acc
|
||||
},
|
||||
{ supported: [], unsupported: [] } as Record<string, ChainId[]>
|
||||
)
|
||||
return [supported, unsupported]
|
||||
}, [isAvalancheEnabled, showTestnets, walletSupportsChain])
|
||||
const chains = showTestnets
|
||||
? NETWORK_SELECTOR_CHAINS
|
||||
: NETWORK_SELECTOR_CHAINS.filter((chain) => !TESTNET_CHAIN_IDS.has(chain))
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const modalRef = useRef<HTMLDivElement>(null)
|
||||
@@ -85,10 +82,10 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
||||
const selectChain = useSelectChain()
|
||||
useSyncChainQuery()
|
||||
|
||||
const [pendingChainId, setPendingChainId] = useState<ChainId | undefined>(undefined)
|
||||
const [pendingChainId, setPendingChainId] = useState<SupportedChainId | undefined>(undefined)
|
||||
|
||||
const onSelectChain = useCallback(
|
||||
async (targetChainId: ChainId) => {
|
||||
async (targetChainId: SupportedChainId) => {
|
||||
setPendingChainId(targetChainId)
|
||||
await selectChain(targetChainId)
|
||||
setPendingChainId(undefined)
|
||||
@@ -97,16 +94,18 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
||||
[selectChain, setIsOpen]
|
||||
)
|
||||
|
||||
const walletSupportsChain = useWalletSupportedChains()
|
||||
|
||||
if (!chainId) {
|
||||
return null
|
||||
}
|
||||
|
||||
const isSupported = !!info && (isAvalancheEnabled || chainId !== ChainId.AVALANCHE)
|
||||
const isSupported = !!info
|
||||
|
||||
const dropdown = (
|
||||
<NavDropdown top="56" left={leftAlign ? '0' : 'auto'} right={leftAlign ? 'auto' : '0'} ref={modalRef}>
|
||||
<Column paddingX="8" data-testid="chain-selector-options">
|
||||
{supportedChains.map((selectorChain) => (
|
||||
{chains.map((selectorChain: SupportedChainId) => (
|
||||
<ChainSelectorRow
|
||||
disabled={!walletSupportsChain.includes(selectorChain)}
|
||||
onSelectChain={onSelectChain}
|
||||
@@ -115,15 +114,6 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
||||
isPending={selectorChain === pendingChainId}
|
||||
/>
|
||||
))}
|
||||
{unsupportedChains.map((selectorChain) => (
|
||||
<ChainSelectorRow
|
||||
disabled
|
||||
onSelectChain={() => undefined}
|
||||
targetChain={selectorChain}
|
||||
key={selectorChain}
|
||||
isPending={false}
|
||||
/>
|
||||
))}
|
||||
</Column>
|
||||
</NavDropdown>
|
||||
)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import Loader from 'components/Icons/LoadingSpinner'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { CheckMarkIcon } from 'nft/components/icons'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
|
||||
@@ -18,7 +18,7 @@ const Container = styled.button<{ disabled: boolean }>`
|
||||
display: grid;
|
||||
grid-template-columns: min-content 1fr min-content;
|
||||
justify-content: space-between;
|
||||
line-height: 20px;
|
||||
line-height: 24px;
|
||||
opacity: ${({ disabled }) => (disabled ? 0.6 : 1)};
|
||||
padding: 10px 8px;
|
||||
text-align: left;
|
||||
@@ -63,7 +63,7 @@ const Logo = styled.img`
|
||||
`
|
||||
interface ChainSelectorRowProps {
|
||||
disabled?: boolean
|
||||
targetChain: ChainId
|
||||
targetChain: SupportedChainId
|
||||
onSelectChain: (targetChain: number) => void
|
||||
isPending: boolean
|
||||
}
|
||||
@@ -80,6 +80,7 @@ export default function ChainSelectorRow({ disabled, targetChain, onSelectChain,
|
||||
onClick={() => {
|
||||
if (!disabled) onSelectChain(targetChain)
|
||||
}}
|
||||
data-testid={`chain-selector-option-${label.toLowerCase()}`}
|
||||
>
|
||||
<Logo src={logoUrl} alt={label} />
|
||||
<Label>{label}</Label>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { NATIVE_CHAIN_ID, nativeOnChain } from 'constants/tokens'
|
||||
import { Chain, NftCollection, useRecentlySearchedAssetsQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { SearchToken } from 'graphql/data/SearchTokens'
|
||||
import { logSentryErrorForUnsupportedChain, supportedChainIdFromGQLChain } from 'graphql/data/util'
|
||||
import { CHAIN_NAME_TO_CHAIN_ID } from 'graphql/data/util'
|
||||
import { useAtom } from 'jotai'
|
||||
import { atomWithStorage, useAtomValue } from 'jotai/utils'
|
||||
import { GenieCollection } from 'nft/types'
|
||||
@@ -85,15 +86,7 @@ export function useRecentlySearchedAssets() {
|
||||
shortenedHistory.forEach((asset) => {
|
||||
if (asset.address === 'NATIVE') {
|
||||
// Handles special case where wMATIC data needs to be used for MATIC
|
||||
const chain = supportedChainIdFromGQLChain(asset.chain)
|
||||
if (!chain) {
|
||||
logSentryErrorForUnsupportedChain({
|
||||
extras: { asset },
|
||||
errorMessage: 'Invalid chain retrieved from Seach Token/Collection Query',
|
||||
})
|
||||
return
|
||||
}
|
||||
const native = nativeOnChain(chain)
|
||||
const native = nativeOnChain(CHAIN_NAME_TO_CHAIN_ID[asset.chain] ?? SupportedChainId.MAINNET)
|
||||
const queryAddress = getQueryAddress(asset.chain)?.toLowerCase() ?? `NATIVE-${asset.chain}`
|
||||
const result = resultsMap[queryAddress]
|
||||
if (result) data.push({ ...result, address: 'NATIVE', ...native })
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { useIsMobile, useIsTablet } from 'nft/hooks'
|
||||
import { useIsNavSearchInputVisible } from 'nft/hooks/useIsNavSearchInputVisible'
|
||||
import { mocked } from 'test-utils/mocked'
|
||||
import { render, screen } from 'test-utils/render'
|
||||
|
||||
import { SearchBar } from './SearchBar'
|
||||
|
||||
jest.mock('hooks/useDisableNFTRoutes')
|
||||
jest.mock('nft/hooks')
|
||||
jest.mock('nft/hooks/useIsNavSearchInputVisible')
|
||||
|
||||
describe('disable nft on searchbar', () => {
|
||||
beforeEach(() => {
|
||||
mocked(useIsMobile).mockReturnValue(false)
|
||||
mocked(useIsTablet).mockReturnValue(false)
|
||||
mocked(useIsNavSearchInputVisible).mockReturnValue(true)
|
||||
})
|
||||
|
||||
it('should render text with nfts', () => {
|
||||
mocked(useDisableNFTRoutes).mockReturnValue(false)
|
||||
const { container } = render(<SearchBar />)
|
||||
expect(container).toMatchSnapshot()
|
||||
expect(screen.queryByPlaceholderText('Search tokens and NFT collections')).toBeVisible()
|
||||
})
|
||||
it('should render text without nfts', () => {
|
||||
mocked(useDisableNFTRoutes).mockReturnValue(true)
|
||||
const { container } = render(<SearchBar />)
|
||||
expect(container).toMatchSnapshot()
|
||||
expect(screen.queryByPlaceholderText('Search tokens')).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { t } from '@lingui/macro'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { sendAnalyticsEvent, Trace, TraceEvent, useTrace } from '@uniswap/analytics'
|
||||
import { BrowserEvent, InterfaceElementName, InterfaceEventName, InterfaceSectionName } from '@uniswap/analytics-events'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
@@ -7,7 +7,6 @@ import clsx from 'clsx'
|
||||
import { useCollectionSearch } from 'graphql/data/nft/CollectionSearch'
|
||||
import { useSearchTokens } from 'graphql/data/SearchTokens'
|
||||
import useDebounce from 'hooks/useDebounce'
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { useIsNftPage } from 'hooks/useIsNftPage'
|
||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||
import { organizeSearchResults } from 'lib/utils/searchBar'
|
||||
@@ -51,7 +50,6 @@ export const SearchBar = () => {
|
||||
const isMobile = useIsMobile()
|
||||
const isTablet = useIsTablet()
|
||||
const isNavSearchInputVisible = useIsNavSearchInputVisible()
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
|
||||
useOnClickOutside(searchRef, () => {
|
||||
isOpen && toggleOpen()
|
||||
@@ -104,16 +102,8 @@ export const SearchBar = () => {
|
||||
...trace,
|
||||
}
|
||||
const placeholderText = useMemo(() => {
|
||||
if (isMobileOrTablet) {
|
||||
return t`Search`
|
||||
} else {
|
||||
if (shouldDisableNFTRoutes) {
|
||||
return t`Search tokens`
|
||||
} else {
|
||||
return t`Search tokens and NFT collections`
|
||||
}
|
||||
}
|
||||
}, [isMobileOrTablet, shouldDisableNFTRoutes])
|
||||
return isMobileOrTablet ? `Search` : `Search tokens and NFT collections`
|
||||
}, [isMobileOrTablet])
|
||||
|
||||
const handleKeyPress = useCallback(
|
||||
(event: any) => {
|
||||
@@ -184,19 +174,26 @@ export const SearchBar = () => {
|
||||
element={InterfaceElementName.NAVBAR_SEARCH_INPUT}
|
||||
properties={{ ...trace }}
|
||||
>
|
||||
<Box
|
||||
as="input"
|
||||
data-cy="search-bar-input"
|
||||
placeholder={placeholderText}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
!isOpen && toggleOpen()
|
||||
setSearchValue(event.target.value)
|
||||
}}
|
||||
onBlur={() => sendAnalyticsEvent(InterfaceEventName.NAVBAR_SEARCH_EXITED, navbarSearchEventProperties)}
|
||||
className={`${styles.searchBarInput} ${styles.searchContentLeftAlign}`}
|
||||
value={searchValue}
|
||||
ref={inputRef}
|
||||
width="full"
|
||||
<Trans
|
||||
id={placeholderText}
|
||||
render={({ translation }) => (
|
||||
<Box
|
||||
as="input"
|
||||
data-cy="search-bar-input"
|
||||
placeholder={translation as string}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
!isOpen && toggleOpen()
|
||||
setSearchValue(event.target.value)
|
||||
}}
|
||||
onBlur={() =>
|
||||
sendAnalyticsEvent(InterfaceEventName.NAVBAR_SEARCH_EXITED, navbarSearchEventProperties)
|
||||
}
|
||||
className={`${styles.searchBarInput} ${styles.searchContentLeftAlign}`}
|
||||
value={searchValue}
|
||||
ref={inputRef}
|
||||
width="full"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</TraceEvent>
|
||||
{!isOpen && <KeyShortCut>/</KeyShortCut>}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { mocked } from 'test-utils/mocked'
|
||||
import { render } from 'test-utils/render'
|
||||
|
||||
import { SearchBarDropdown } from './SearchBarDropdown'
|
||||
|
||||
jest.mock('hooks/useDisableNFTRoutes')
|
||||
|
||||
const SearchBarDropdownProps = {
|
||||
toggleOpen: () => void 0,
|
||||
tokens: [],
|
||||
collections: [],
|
||||
queryText: '',
|
||||
hasInput: false,
|
||||
isLoading: false,
|
||||
}
|
||||
|
||||
describe('disable nft on searchbar dropdown', () => {
|
||||
it('should render popular nft collections', () => {
|
||||
mocked(useDisableNFTRoutes).mockReturnValue(false)
|
||||
const { container } = render(<SearchBarDropdown {...SearchBarDropdownProps} />)
|
||||
expect(container).toMatchSnapshot()
|
||||
expect(container).toHaveTextContent('Popular NFT collections')
|
||||
})
|
||||
it('should not render popular nft collections', () => {
|
||||
mocked(useDisableNFTRoutes).mockReturnValue(true)
|
||||
const { container } = render(<SearchBarDropdown {...SearchBarDropdownProps} />)
|
||||
expect(container).toMatchSnapshot()
|
||||
expect(container).not.toHaveTextContent('Popular NFT collections')
|
||||
expect(container).not.toHaveTextContent('NFT')
|
||||
})
|
||||
})
|
||||
@@ -1,18 +1,14 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { useTrace } from '@uniswap/analytics'
|
||||
import { InterfaceSectionName, NavBarSearchTypes } from '@uniswap/analytics-events'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import clsx from 'clsx'
|
||||
import Badge from 'components/Badge'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { useFilterChainsForAvalanche } from 'featureFlags/flags/avalanche'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { HistoryDuration, SafetyLevel } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { useTrendingCollections } from 'graphql/data/nft/TrendingCollections'
|
||||
import { SearchToken } from 'graphql/data/SearchTokens'
|
||||
import useTrendingTokens from 'graphql/data/TrendingTokens'
|
||||
import { BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS } from 'graphql/data/util'
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { useIsNftPage } from 'hooks/useIsNftPage'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Column, Row } from 'nft/components/Flex'
|
||||
@@ -23,6 +19,7 @@ import { useLocation } from 'react-router-dom'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ThemedText } from 'theme'
|
||||
|
||||
import BnbLogoURI from '../../assets/svg/bnb-logo.svg'
|
||||
import { ClockIcon, TrendingArrow } from '../../nft/components/icons'
|
||||
import { useRecentlySearchedAssets } from './RecentlySearchedAssets'
|
||||
import * as styles from './SearchBar.css'
|
||||
@@ -106,12 +103,12 @@ function isKnownToken(token: SearchToken) {
|
||||
return token.project?.safetyLevel == SafetyLevel.Verified || token.project?.safetyLevel == SafetyLevel.MediumWarning
|
||||
}
|
||||
|
||||
const ChainLogo = styled.img`
|
||||
const BNBLogo = styled.img`
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 8px;
|
||||
`
|
||||
const ChainComingSoonBadge = styled(Badge)`
|
||||
const BNBComingSoonBadge = styled(Badge)`
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.backgroundModule};
|
||||
color: ${({ theme }) => theme.textSecondary};
|
||||
@@ -151,7 +148,6 @@ export const SearchBarDropdown = ({
|
||||
const isNFTPage = useIsNftPage()
|
||||
const isTokenPage = pathname.includes('/tokens')
|
||||
const [resultsState, setResultsState] = useState<ReactNode>()
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
|
||||
const { data: trendingCollections, loading: trendingCollectionsAreLoading } = useTrendingCollections(
|
||||
3,
|
||||
@@ -315,7 +311,7 @@ export const SearchBarDropdown = ({
|
||||
isLoading={!trendingTokenData}
|
||||
/>
|
||||
)}
|
||||
{Boolean(!isTokenPage && !shouldDisableNFTRoutes) && (
|
||||
{!isTokenPage && (
|
||||
<SearchBarDropdownSection
|
||||
hoveredIndex={hoveredIndex}
|
||||
startingIndex={shortenedHistory.length + (isNFTPage ? 0 : trendingTokens?.length ?? 0)}
|
||||
@@ -355,36 +351,23 @@ export const SearchBarDropdown = ({
|
||||
trace,
|
||||
searchHistory,
|
||||
trendingCollectionsAreLoading,
|
||||
shouldDisableNFTRoutes,
|
||||
])
|
||||
const gatedUnsupportedChains = useFilterChainsForAvalanche([...BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS])
|
||||
const showChainComingSoonBadge = chainId && gatedUnsupportedChains.includes(chainId) && !isLoading
|
||||
const logoUri = getChainInfo(chainId)?.logoUrl
|
||||
|
||||
const showBNBComingSoonBadge = chainId === SupportedChainId.BNB && !isLoading
|
||||
|
||||
return (
|
||||
<Column overflow="hidden" className={clsx(styles.searchBarDropdownNft, styles.searchBarScrollable)}>
|
||||
<Box opacity={isLoading ? '0.3' : '1'} transition="125">
|
||||
{resultsState}
|
||||
{showChainComingSoonBadge && (
|
||||
<ChainComingSoonBadge>
|
||||
<ChainLogo src={logoUri} />
|
||||
{showBNBComingSoonBadge && (
|
||||
<BNBComingSoonBadge>
|
||||
<BNBLogo src={BnbLogoURI} />
|
||||
<ThemedText.BodySmall color="textSecondary" fontSize="14px" fontWeight="400" lineHeight="20px">
|
||||
<ComingSoonText chainId={chainId} />
|
||||
<Trans>Coming soon: search and explore tokens on BNB Chain</Trans>
|
||||
</ThemedText.BodySmall>
|
||||
</ChainComingSoonBadge>
|
||||
</BNBComingSoonBadge>
|
||||
)}
|
||||
</Box>
|
||||
</Column>
|
||||
)
|
||||
}
|
||||
|
||||
function ComingSoonText({ chainId }: { chainId: ChainId }) {
|
||||
switch (chainId) {
|
||||
case ChainId.BNB:
|
||||
return <Trans>Coming soon: search and explore tokens on BNB Chain</Trans>
|
||||
case ChainId.AVALANCHE:
|
||||
return <Trans>Coming soon: search and explore tokens on Avalanche Chain</Trans>
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`disable nft on searchbar should render text with nfts 1`] = `
|
||||
.c0 {
|
||||
background-color: #ADBCFF3d;
|
||||
color: #7780A0;
|
||||
padding: 0px 8px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 16px;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
opacity: 0.6;
|
||||
-webkit-backdrop-filter: blur(60px);
|
||||
backdrop-filter: blur(60px);
|
||||
}
|
||||
|
||||
<div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_position_relative_sm__rgw6ez491 sprinkles_width_auto_sm__rgw6ez17v sprinkles_width_auto_md__rgw6ez17w SearchBar_searchBarContainerNft__1fbf9sz4 SearchBar__1fbf9sz3 sprinkles_right_0_sm__rgw6ez39p sprinkles_top_0_sm__rgw6ez3f7 sprinkles_zIndex_3_sm__rgw6ez3qj sprinkles_display_flex_sm__rgw6ez44v sprinkles_maxHeight_searchResultsMaxHeight_sm__rgw6ez1zd sprinkles_overflow_hidden_default__rgw6ez7m3 searchBarContainerDisableBlur"
|
||||
data-cy="search-bar"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_borderRadius_12_default__rgw6ez7bj sprinkles_borderBottomWidth_1px_default__rgw6ez7kj sprinkles_backgroundColor_searchBackground_default__rgw6ez6d1 sprinkles_gap_12_sm__rgw6ez3tj SearchBar_nftSearchBar__1fbf9sz9 SearchBar_baseSearchNftStyle__1fbf9sz2 SearchBar_baseSearchStyle__1fbf9sz1 SearchBar__1fbf9sz0 sprinkles_paddingTop_12_sm__rgw6ez2ov sprinkles_paddingBottom_12_sm__rgw6ez28d sprinkles_width_viewWidth_sm__rgw6ez17p sprinkles_borderStyle_solid_default__rgw6ez7ab sprinkles_borderWidth_1px_default__rgw6ez7jr sprinkles_borderColor_searchOutline_default__rgw6ez51v SearchBar__1fbf9sz8 sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_color_textSecondary_default__rgw6ez4ep common_magicalGradientOnHover__127l8hdb common_magicalGradient__127l8hda"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_searchContentLeftAlign__1fbf9sz10"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_none_sm__rgw6ez44j sprinkles_display_flex_md__rgw6ez44w"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M15 15L11.2439 11.2439M12.3821 6.69106C12.3821 9.83414 9.83414 12.3821 6.69106 12.3821C3.54797 12.3821 1 9.83414 1 6.69106C1 3.54797 3.54797 1 6.69106 1C9.83414 1 12.3821 3.54797 12.3821 6.69106Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.5"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_display_none_md__rgw6ez44k sprinkles_color_textTertiary_default__rgw6ez4ev"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="16"
|
||||
viewBox="0 0 8 16"
|
||||
width="8"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7 1L1 7L7 13"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
class="reset_base__1klryar0 reset_input__1klryar8 reset_field__1klryar5 reset_appearance__1klryar4 sprinkles_width_full_sm__rgw6ez16v SearchBar_searchBarInput__1fbf9szb SearchBar__1fbf9sza sprinkles_padding_0_sm__rgw6ez2t7 sprinkles_fontWeight_normal_sm__rgw6ezcp sprinkles_fontSize_16_sm__rgw6ezb1 sprinkles_color_textPrimary_default__rgw6ez4ej sprinkles_color_textSecondary_placeholder__rgw6ez4eu sprinkles_border_none_default__rgw6ez7iz sprinkles_background_none_default__rgw6ez4sj sprinkles_lineHeight_24_sm__rgw6ezed sprinkles_height_full_sm__rgw6ez1dv SearchBar_searchContentLeftAlign__1fbf9sz10"
|
||||
data-cy="search-bar-input"
|
||||
placeholder="Search tokens and NFT collections"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
class="c0"
|
||||
>
|
||||
/
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_overflow_hidden_default__rgw6ez7m3 SearchBar_hidden__1fbf9szx SearchBar__1fbf9szw sprinkles_visibility_hidden_sm__rgw6ez46v sprinkles_opacity_0_sm__rgw6ez4ad sprinkles_padding_0_sm__rgw6ez2t7 sprinkles_height_0_sm__rgw6ez187"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`disable nft on searchbar should render text without nfts 1`] = `
|
||||
.c0 {
|
||||
background-color: #ADBCFF3d;
|
||||
color: #7780A0;
|
||||
padding: 0px 8px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 16px;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
opacity: 0.6;
|
||||
-webkit-backdrop-filter: blur(60px);
|
||||
backdrop-filter: blur(60px);
|
||||
}
|
||||
|
||||
<div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_position_relative_sm__rgw6ez491 sprinkles_width_auto_sm__rgw6ez17v sprinkles_width_auto_md__rgw6ez17w SearchBar_searchBarContainerNft__1fbf9sz4 SearchBar__1fbf9sz3 sprinkles_right_0_sm__rgw6ez39p sprinkles_top_0_sm__rgw6ez3f7 sprinkles_zIndex_3_sm__rgw6ez3qj sprinkles_display_flex_sm__rgw6ez44v sprinkles_maxHeight_searchResultsMaxHeight_sm__rgw6ez1zd sprinkles_overflow_hidden_default__rgw6ez7m3 searchBarContainerDisableBlur"
|
||||
data-cy="search-bar"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_borderRadius_12_default__rgw6ez7bj sprinkles_borderBottomWidth_1px_default__rgw6ez7kj sprinkles_backgroundColor_searchBackground_default__rgw6ez6d1 sprinkles_gap_12_sm__rgw6ez3tj SearchBar_nftSearchBar__1fbf9sz9 SearchBar_baseSearchNftStyle__1fbf9sz2 SearchBar_baseSearchStyle__1fbf9sz1 SearchBar__1fbf9sz0 sprinkles_paddingTop_12_sm__rgw6ez2ov sprinkles_paddingBottom_12_sm__rgw6ez28d sprinkles_width_viewWidth_sm__rgw6ez17p sprinkles_borderStyle_solid_default__rgw6ez7ab sprinkles_borderWidth_1px_default__rgw6ez7jr sprinkles_borderColor_searchOutline_default__rgw6ez51v SearchBar__1fbf9sz8 sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_color_textSecondary_default__rgw6ez4ep common_magicalGradientOnHover__127l8hdb common_magicalGradient__127l8hda"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_searchContentLeftAlign__1fbf9sz10"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_none_sm__rgw6ez44j sprinkles_display_flex_md__rgw6ez44w"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M15 15L11.2439 11.2439M12.3821 6.69106C12.3821 9.83414 9.83414 12.3821 6.69106 12.3821C3.54797 12.3821 1 9.83414 1 6.69106C1 3.54797 3.54797 1 6.69106 1C9.83414 1 12.3821 3.54797 12.3821 6.69106Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.5"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_display_none_md__rgw6ez44k sprinkles_color_textTertiary_default__rgw6ez4ev"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="16"
|
||||
viewBox="0 0 8 16"
|
||||
width="8"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7 1L1 7L7 13"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
class="reset_base__1klryar0 reset_input__1klryar8 reset_field__1klryar5 reset_appearance__1klryar4 sprinkles_width_full_sm__rgw6ez16v SearchBar_searchBarInput__1fbf9szb SearchBar__1fbf9sza sprinkles_padding_0_sm__rgw6ez2t7 sprinkles_fontWeight_normal_sm__rgw6ezcp sprinkles_fontSize_16_sm__rgw6ezb1 sprinkles_color_textPrimary_default__rgw6ez4ej sprinkles_color_textSecondary_placeholder__rgw6ez4eu sprinkles_border_none_default__rgw6ez7iz sprinkles_background_none_default__rgw6ez4sj sprinkles_lineHeight_24_sm__rgw6ezed sprinkles_height_full_sm__rgw6ez1dv SearchBar_searchContentLeftAlign__1fbf9sz10"
|
||||
data-cy="search-bar-input"
|
||||
placeholder="Search tokens"
|
||||
value=""
|
||||
/>
|
||||
<div
|
||||
class="c0"
|
||||
>
|
||||
/
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_overflow_hidden_default__rgw6ez7m3 SearchBar_hidden__1fbf9szx SearchBar__1fbf9szw sprinkles_visibility_hidden_sm__rgw6ez46v sprinkles_opacity_0_sm__rgw6ez4ad sprinkles_padding_0_sm__rgw6ez2t7 sprinkles_height_0_sm__rgw6ez187"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -1,344 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`disable nft on searchbar dropdown should not render popular nft collections 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_overflow_hidden_default__rgw6ez7m3 SearchBar_searchBarDropdownNft__1fbf9szd SearchBar_baseSearchNftStyle__1fbf9sz2 SearchBar_baseSearchStyle__1fbf9sz1 SearchBar__1fbf9sz0 sprinkles_paddingTop_12_sm__rgw6ez2ov sprinkles_paddingBottom_12_sm__rgw6ez28d sprinkles_width_viewWidth_sm__rgw6ez17p sprinkles_borderStyle_solid_default__rgw6ez7ab sprinkles_borderWidth_1px_default__rgw6ez7jr sprinkles_borderColor_searchOutline_default__rgw6ez51v SearchBar__1fbf9szc sprinkles_borderBottomLeftRadius_12_default__rgw6ez7g7 sprinkles_borderBottomRightRadius_12_default__rgw6ez7hr sprinkles_height_viewHeight_sm__rgw6ez1ej sprinkles_height_auto_md__rgw6ez1ew sprinkles_backgroundColor_backgroundSurface_default__rgw6ez6cj SearchBar__1fbf9sze sprinkles_overflowY_auto_default__rgw6ez7nn"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_opacity_1_sm__rgw6ez4b7 sprinkles_transition_125_default__rgw6ez7oj"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_20_sm__rgw6ez3u7"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_12_sm__rgw6ez3tj"
|
||||
data-cy="searchbar-dropdown"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_4_sm__rgw6ez2o7 sprinkles_paddingBottom_4_sm__rgw6ez27p sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_gap_8_sm__rgw6ez3t7 sprinkles_color_gray300_default__rgw6ez4k1 common__127l8hd4 sprinkles_fontWeight_medium_sm__rgw6ezcv sprinkles_fontSize_14_sm__rgw6ezav sprinkles_lineHeight_14_sm__rgw6ezdv"
|
||||
style="line-height: 20px;"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17.5 5.8335H18.25C18.25 5.41928 17.9142 5.0835 17.5 5.0835V5.8335ZM11.0227 12.4307L10.4876 12.9562C10.6286 13.0998 10.8214 13.1807 11.0227 13.1807C11.224 13.1807 11.4169 13.0998 11.5579 12.9562L11.0227 12.4307ZM7.61364 8.9585L8.14881 8.43305C8.00778 8.28941 7.81493 8.2085 7.61364 8.2085C7.41234 8.2085 7.21949 8.28941 7.07846 8.43305L7.61364 8.9585ZM1.96483 13.6414C1.67463 13.937 1.67899 14.4118 1.97456 14.702C2.27013 14.9922 2.74498 14.9878 3.03517 14.6923L1.96483 13.6414ZM13.4091 5.0835C12.9949 5.0835 12.6591 5.41928 12.6591 5.8335C12.6591 6.24771 12.9949 6.5835 13.4091 6.5835V5.0835ZM16.75 10.0002C16.75 10.4144 17.0858 10.7502 17.5 10.7502C17.9142 10.7502 18.25 10.4144 18.25 10.0002H16.75ZM16.9648 5.30805L10.4876 11.9053L11.5579 12.9562L18.0352 6.35894L16.9648 5.30805ZM11.5579 11.9053L8.14881 8.43305L7.07846 9.48394L10.4876 12.9562L11.5579 11.9053ZM7.07846 8.43305L1.96483 13.6414L3.03517 14.6923L8.14881 9.48394L7.07846 8.43305ZM13.4091 6.5835H17.5V5.0835H13.4091V6.5835ZM16.75 5.8335V10.0002H18.25V5.8335H16.75Z"
|
||||
fill="var(--color-gray300__rgw6ez1g)"
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
class="reset_base__1klryar0"
|
||||
>
|
||||
Popular tokens
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_12_sm__rgw6ez3tj"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j SearchBar_suggestionRow__1fbf9szg SearchBar__1fbf9szf sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_8_sm__rgw6ez2oj sprinkles_paddingBottom_8_sm__rgw6ez281 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j sprinkles_cursor_pointer_default__rgw6ez79z"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_imageHolder__1fbf9szq SearchBar__1fbf9szh sprinkles_width_36_sm__rgw6ez137 sprinkles_height_36_sm__rgw6ez1a7 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_marginRight_8_sm__rgw6ezr1 SearchBar__1fbf9szp sprinkles_background_backgroundModule_default__rgw6ez4p1 sprinkles_flexShrink_0_sm__rgw6ez3xv"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_4_sm__rgw6ez3sv sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
style="width: 180px;"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_120_sm__rgw6ez15j sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j SearchBar_suggestionRow__1fbf9szg SearchBar__1fbf9szf sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_8_sm__rgw6ez2oj sprinkles_paddingBottom_8_sm__rgw6ez281 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j sprinkles_cursor_pointer_default__rgw6ez79z"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_imageHolder__1fbf9szq SearchBar__1fbf9szh sprinkles_width_36_sm__rgw6ez137 sprinkles_height_36_sm__rgw6ez1a7 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_marginRight_8_sm__rgw6ezr1 SearchBar__1fbf9szp sprinkles_background_backgroundModule_default__rgw6ez4p1 sprinkles_flexShrink_0_sm__rgw6ez3xv"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_4_sm__rgw6ez3sv sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
style="width: 180px;"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_120_sm__rgw6ez15j sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`disable nft on searchbar dropdown should render popular nft collections 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_overflow_hidden_default__rgw6ez7m3 SearchBar_searchBarDropdownNft__1fbf9szd SearchBar_baseSearchNftStyle__1fbf9sz2 SearchBar_baseSearchStyle__1fbf9sz1 SearchBar__1fbf9sz0 sprinkles_paddingTop_12_sm__rgw6ez2ov sprinkles_paddingBottom_12_sm__rgw6ez28d sprinkles_width_viewWidth_sm__rgw6ez17p sprinkles_borderStyle_solid_default__rgw6ez7ab sprinkles_borderWidth_1px_default__rgw6ez7jr sprinkles_borderColor_searchOutline_default__rgw6ez51v SearchBar__1fbf9szc sprinkles_borderBottomLeftRadius_12_default__rgw6ez7g7 sprinkles_borderBottomRightRadius_12_default__rgw6ez7hr sprinkles_height_viewHeight_sm__rgw6ez1ej sprinkles_height_auto_md__rgw6ez1ew sprinkles_backgroundColor_backgroundSurface_default__rgw6ez6cj SearchBar__1fbf9sze sprinkles_overflowY_auto_default__rgw6ez7nn"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_opacity_1_sm__rgw6ez4b7 sprinkles_transition_125_default__rgw6ez7oj"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_20_sm__rgw6ez3u7"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_12_sm__rgw6ez3tj"
|
||||
data-cy="searchbar-dropdown"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_4_sm__rgw6ez2o7 sprinkles_paddingBottom_4_sm__rgw6ez27p sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_gap_8_sm__rgw6ez3t7 sprinkles_color_gray300_default__rgw6ez4k1 common__127l8hd4 sprinkles_fontWeight_medium_sm__rgw6ezcv sprinkles_fontSize_14_sm__rgw6ezav sprinkles_lineHeight_14_sm__rgw6ezdv"
|
||||
style="line-height: 20px;"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17.5 5.8335H18.25C18.25 5.41928 17.9142 5.0835 17.5 5.0835V5.8335ZM11.0227 12.4307L10.4876 12.9562C10.6286 13.0998 10.8214 13.1807 11.0227 13.1807C11.224 13.1807 11.4169 13.0998 11.5579 12.9562L11.0227 12.4307ZM7.61364 8.9585L8.14881 8.43305C8.00778 8.28941 7.81493 8.2085 7.61364 8.2085C7.41234 8.2085 7.21949 8.28941 7.07846 8.43305L7.61364 8.9585ZM1.96483 13.6414C1.67463 13.937 1.67899 14.4118 1.97456 14.702C2.27013 14.9922 2.74498 14.9878 3.03517 14.6923L1.96483 13.6414ZM13.4091 5.0835C12.9949 5.0835 12.6591 5.41928 12.6591 5.8335C12.6591 6.24771 12.9949 6.5835 13.4091 6.5835V5.0835ZM16.75 10.0002C16.75 10.4144 17.0858 10.7502 17.5 10.7502C17.9142 10.7502 18.25 10.4144 18.25 10.0002H16.75ZM16.9648 5.30805L10.4876 11.9053L11.5579 12.9562L18.0352 6.35894L16.9648 5.30805ZM11.5579 11.9053L8.14881 8.43305L7.07846 9.48394L10.4876 12.9562L11.5579 11.9053ZM7.07846 8.43305L1.96483 13.6414L3.03517 14.6923L8.14881 9.48394L7.07846 8.43305ZM13.4091 6.5835H17.5V5.0835H13.4091V6.5835ZM16.75 5.8335V10.0002H18.25V5.8335H16.75Z"
|
||||
fill="var(--color-gray300__rgw6ez1g)"
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
class="reset_base__1klryar0"
|
||||
>
|
||||
Popular tokens
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_12_sm__rgw6ez3tj"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j SearchBar_suggestionRow__1fbf9szg SearchBar__1fbf9szf sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_8_sm__rgw6ez2oj sprinkles_paddingBottom_8_sm__rgw6ez281 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j sprinkles_cursor_pointer_default__rgw6ez79z"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_imageHolder__1fbf9szq SearchBar__1fbf9szh sprinkles_width_36_sm__rgw6ez137 sprinkles_height_36_sm__rgw6ez1a7 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_marginRight_8_sm__rgw6ezr1 SearchBar__1fbf9szp sprinkles_background_backgroundModule_default__rgw6ez4p1 sprinkles_flexShrink_0_sm__rgw6ez3xv"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_4_sm__rgw6ez3sv sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
style="width: 180px;"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_120_sm__rgw6ez15j sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j SearchBar_suggestionRow__1fbf9szg SearchBar__1fbf9szf sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_8_sm__rgw6ez2oj sprinkles_paddingBottom_8_sm__rgw6ez281 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j sprinkles_cursor_pointer_default__rgw6ez79z"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_imageHolder__1fbf9szq SearchBar__1fbf9szh sprinkles_width_36_sm__rgw6ez137 sprinkles_height_36_sm__rgw6ez1a7 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_marginRight_8_sm__rgw6ezr1 SearchBar__1fbf9szp sprinkles_background_backgroundModule_default__rgw6ez4p1 sprinkles_flexShrink_0_sm__rgw6ez3xv"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_4_sm__rgw6ez3sv sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
style="width: 180px;"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_120_sm__rgw6ez15j sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_12_sm__rgw6ez3tj"
|
||||
data-cy="searchbar-dropdown"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_4_sm__rgw6ez2o7 sprinkles_paddingBottom_4_sm__rgw6ez27p sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_gap_8_sm__rgw6ez3t7 sprinkles_color_gray300_default__rgw6ez4k1 common__127l8hd4 sprinkles_fontWeight_medium_sm__rgw6ezcv sprinkles_fontSize_14_sm__rgw6ezav sprinkles_lineHeight_14_sm__rgw6ezdv"
|
||||
style="line-height: 20px;"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17.5 5.8335H18.25C18.25 5.41928 17.9142 5.0835 17.5 5.0835V5.8335ZM11.0227 12.4307L10.4876 12.9562C10.6286 13.0998 10.8214 13.1807 11.0227 13.1807C11.224 13.1807 11.4169 13.0998 11.5579 12.9562L11.0227 12.4307ZM7.61364 8.9585L8.14881 8.43305C8.00778 8.28941 7.81493 8.2085 7.61364 8.2085C7.41234 8.2085 7.21949 8.28941 7.07846 8.43305L7.61364 8.9585ZM1.96483 13.6414C1.67463 13.937 1.67899 14.4118 1.97456 14.702C2.27013 14.9922 2.74498 14.9878 3.03517 14.6923L1.96483 13.6414ZM13.4091 5.0835C12.9949 5.0835 12.6591 5.41928 12.6591 5.8335C12.6591 6.24771 12.9949 6.5835 13.4091 6.5835V5.0835ZM16.75 10.0002C16.75 10.4144 17.0858 10.7502 17.5 10.7502C17.9142 10.7502 18.25 10.4144 18.25 10.0002H16.75ZM16.9648 5.30805L10.4876 11.9053L11.5579 12.9562L18.0352 6.35894L16.9648 5.30805ZM11.5579 11.9053L8.14881 8.43305L7.07846 9.48394L10.4876 12.9562L11.5579 11.9053ZM7.07846 8.43305L1.96483 13.6414L3.03517 14.6923L8.14881 9.48394L7.07846 8.43305ZM13.4091 6.5835H17.5V5.0835H13.4091V6.5835ZM16.75 5.8335V10.0002H18.25V5.8335H16.75Z"
|
||||
fill="var(--color-gray300__rgw6ez1g)"
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
class="reset_base__1klryar0"
|
||||
>
|
||||
Popular NFT collections
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_12_sm__rgw6ez3tj"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j SearchBar_suggestionRow__1fbf9szg SearchBar__1fbf9szf sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_8_sm__rgw6ez2oj sprinkles_paddingBottom_8_sm__rgw6ez281 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j sprinkles_cursor_pointer_default__rgw6ez79z"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_imageHolder__1fbf9szq SearchBar__1fbf9szh sprinkles_width_36_sm__rgw6ez137 sprinkles_height_36_sm__rgw6ez1a7 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_marginRight_8_sm__rgw6ezr1 SearchBar__1fbf9szp sprinkles_background_backgroundModule_default__rgw6ez4p1 sprinkles_flexShrink_0_sm__rgw6ez3xv"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_4_sm__rgw6ez3sv sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
style="width: 180px;"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_120_sm__rgw6ez15j sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j SearchBar_suggestionRow__1fbf9szg SearchBar__1fbf9szf sprinkles_paddingLeft_16_sm__rgw6ez2e7 sprinkles_paddingRight_16_sm__rgw6ez2jp sprinkles_paddingTop_8_sm__rgw6ez2oj sprinkles_paddingBottom_8_sm__rgw6ez281 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j sprinkles_cursor_pointer_default__rgw6ez79z"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 SearchBar_imageHolder__1fbf9szq SearchBar__1fbf9szh sprinkles_width_36_sm__rgw6ez137 sprinkles_height_36_sm__rgw6ez1a7 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_marginRight_8_sm__rgw6ezr1 SearchBar__1fbf9szp sprinkles_background_backgroundModule_default__rgw6ez4p1 sprinkles_flexShrink_0_sm__rgw6ez3xv"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_column_sm__rgw6ez477 sprinkles_gap_4_sm__rgw6ez3sv sprinkles_width_full_sm__rgw6ez16v"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
style="width: 180px;"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_20_sm__rgw6ez19d sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_display_flex_sm__rgw6ez44v sprinkles_flexDirection_row_sm__rgw6ez471 sprinkles_alignItems_center_sm__rgw6ez3j sprinkles_justifyContent_space-between_sm__rgw6ez48j"
|
||||
>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_120_sm__rgw6ez15j sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
<div
|
||||
class="reset_base__1klryar0 sprinkles_borderRadius_round_default__rgw6ez7cj sprinkles_height_16_sm__rgw6ez191 sprinkles_width_48_sm__rgw6ez13v sprinkles_background_backgroundModule_default__rgw6ez4p1"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -3,9 +3,9 @@ import { useWeb3React } from '@web3-react/core'
|
||||
import { useAccountDrawer } from 'components/AccountDrawer'
|
||||
import Web3Status from 'components/Web3Status'
|
||||
import { chainIdToBackendName } from 'graphql/data/util'
|
||||
import { useDisableNFTRoutes } from 'hooks/useDisableNFTRoutes'
|
||||
import { useIsNftPage } from 'hooks/useIsNftPage'
|
||||
import { useIsPoolsPage } from 'hooks/useIsPoolsPage'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Row } from 'nft/components/Flex'
|
||||
import { UniIcon } from 'nft/components/icons'
|
||||
@@ -13,6 +13,7 @@ import { useProfilePageState } from 'nft/hooks'
|
||||
import { ProfilePageStateType } from 'nft/types'
|
||||
import { ReactNode, useCallback } from 'react'
|
||||
import { NavLink, NavLinkProps, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { useIsNavSearchInputVisible } from '../../nft/hooks/useIsNavSearchInputVisible'
|
||||
@@ -60,7 +61,7 @@ export const PageTabs = () => {
|
||||
const isPoolActive = useIsPoolsPage()
|
||||
const isNftPage = useIsNftPage()
|
||||
|
||||
const shouldDisableNFTRoutes = useDisableNFTRoutes()
|
||||
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { useIsAvalancheEnabled } from 'featureFlags/flags/avalanche'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { ArrowUpRight } from 'react-feather'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ExternalLink, HideSmall } from 'theme'
|
||||
@@ -31,16 +30,15 @@ const RootWrapper = styled.div`
|
||||
`
|
||||
|
||||
const SHOULD_SHOW_ALERT = {
|
||||
[ChainId.OPTIMISM]: true,
|
||||
[ChainId.OPTIMISM_GOERLI]: true,
|
||||
[ChainId.ARBITRUM_ONE]: true,
|
||||
[ChainId.ARBITRUM_GOERLI]: true,
|
||||
[ChainId.POLYGON]: true,
|
||||
[ChainId.POLYGON_MUMBAI]: true,
|
||||
[ChainId.CELO]: true,
|
||||
[ChainId.CELO_ALFAJORES]: true,
|
||||
[ChainId.BNB]: true,
|
||||
[ChainId.AVALANCHE]: true,
|
||||
[SupportedChainId.OPTIMISM]: true,
|
||||
[SupportedChainId.OPTIMISM_GOERLI]: true,
|
||||
[SupportedChainId.ARBITRUM_ONE]: true,
|
||||
[SupportedChainId.ARBITRUM_GOERLI]: true,
|
||||
[SupportedChainId.POLYGON]: true,
|
||||
[SupportedChainId.POLYGON_MUMBAI]: true,
|
||||
[SupportedChainId.CELO]: true,
|
||||
[SupportedChainId.CELO_ALFAJORES]: true,
|
||||
[SupportedChainId.BNB]: true,
|
||||
}
|
||||
|
||||
type NetworkAlertChains = keyof typeof SHOULD_SHOW_ALERT
|
||||
@@ -49,48 +47,44 @@ const BG_COLORS_BY_DARK_MODE_AND_CHAIN_ID: {
|
||||
[darkMode in 'dark' | 'light']: { [chainId in NetworkAlertChains]: string }
|
||||
} = {
|
||||
dark: {
|
||||
[ChainId.POLYGON]:
|
||||
[SupportedChainId.POLYGON]:
|
||||
'radial-gradient(100% 93.36% at 0% 6.64%, rgba(160, 108, 247, 0.1) 0%, rgba(82, 32, 166, 0.1) 100%)',
|
||||
[ChainId.POLYGON_MUMBAI]:
|
||||
[SupportedChainId.POLYGON_MUMBAI]:
|
||||
'radial-gradient(100% 93.36% at 0% 6.64%, rgba(160, 108, 247, 0.1) 0%, rgba(82, 32, 166, 0.1) 100%)',
|
||||
[ChainId.CELO]:
|
||||
[SupportedChainId.CELO]:
|
||||
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(90, 190, 170, 0.15) 0%, rgba(80, 160, 40, 0.15) 100%)',
|
||||
[ChainId.CELO_ALFAJORES]:
|
||||
[SupportedChainId.CELO_ALFAJORES]:
|
||||
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(90, 190, 170, 0.15) 0%, rgba(80, 160, 40, 0.15) 100%)',
|
||||
[ChainId.BNB]:
|
||||
[SupportedChainId.BNB]:
|
||||
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(240, 185, 11, 0.16) 0%, rgba(255, 168, 0, 0.16) 100%)',
|
||||
[ChainId.OPTIMISM]:
|
||||
[SupportedChainId.OPTIMISM]:
|
||||
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)',
|
||||
[ChainId.OPTIMISM_GOERLI]:
|
||||
[SupportedChainId.OPTIMISM_GOERLI]:
|
||||
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.04) 0%, rgba(235, 0, 255, 0.01 96%)',
|
||||
[ChainId.ARBITRUM_ONE]:
|
||||
[SupportedChainId.ARBITRUM_ONE]:
|
||||
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.01) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.05) 0%, rgba(33, 114, 229, 0.05) 100%), hsla(0, 0%, 100%, 0.05)',
|
||||
[ChainId.ARBITRUM_GOERLI]:
|
||||
[SupportedChainId.ARBITRUM_GOERLI]:
|
||||
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.05) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(75% 75% at 0% 0%, rgba(150, 190, 220, 0.05) 0%, rgba(33, 114, 229, 0.1) 100%), hsla(0, 0%, 100%, 0.05)',
|
||||
[ChainId.AVALANCHE]:
|
||||
'radial-gradient(948% 292% at 42% 0%, rgba(255, 58, 212, 0.01) 0%, rgba(255, 255, 255, 0.04) 100%),radial-gradient(98% 96% at 2% 0%, rgba(255, 39, 39, 0.01) 0%, rgba(235, 0, 255, 0.01) 96%)',
|
||||
},
|
||||
light: {
|
||||
[ChainId.POLYGON]:
|
||||
[SupportedChainId.POLYGON]:
|
||||
'radial-gradient(182.71% 205.59% at 2.81% 7.69%, rgba(130, 71, 229, 0.2) 0%, rgba(167, 202, 255, 0.2) 100%)',
|
||||
[ChainId.POLYGON_MUMBAI]:
|
||||
[SupportedChainId.POLYGON_MUMBAI]:
|
||||
'radial-gradient(182.71% 205.59% at 2.81% 7.69%, rgba(130, 71, 229, 0.2) 0%, rgba(167, 202, 255, 0.2) 100%)',
|
||||
[ChainId.CELO]:
|
||||
[SupportedChainId.CELO]:
|
||||
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(63, 208, 137, 0.15) 0%, rgba(49, 205, 50, 0.15) 100%)',
|
||||
[ChainId.CELO_ALFAJORES]:
|
||||
[SupportedChainId.CELO_ALFAJORES]:
|
||||
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(63, 208, 137, 0.15) 0%, rgba(49, 205, 50, 0.15) 100%)',
|
||||
[ChainId.BNB]:
|
||||
[SupportedChainId.BNB]:
|
||||
'radial-gradient(182.71% 150.59% at 2.81% 7.69%, rgba(240, 185, 11, 0.16) 0%, rgba(255, 168, 0, 0.16) 100%)',
|
||||
[ChainId.OPTIMISM]:
|
||||
[SupportedChainId.OPTIMISM]:
|
||||
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
|
||||
[ChainId.OPTIMISM_GOERLI]:
|
||||
[SupportedChainId.OPTIMISM_GOERLI]:
|
||||
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
|
||||
[ChainId.ARBITRUM_ONE]:
|
||||
[SupportedChainId.ARBITRUM_ONE]:
|
||||
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1)',
|
||||
[ChainId.ARBITRUM_GOERLI]:
|
||||
[SupportedChainId.ARBITRUM_GOERLI]:
|
||||
'radial-gradient(285% 8200% at 30% 50%, rgba(40, 160, 240, 0.1) 0%, rgba(219, 255, 0, 0) 100%),radial-gradient(circle at top left, hsla(206, 50%, 75%, 0.01), hsla(215, 79%, 51%, 0.12)), hsla(0, 0%, 100%, 0.1)',
|
||||
[ChainId.AVALANCHE]:
|
||||
'radial-gradient(92% 105% at 50% 7%, rgba(255, 58, 212, 0.04) 0%, rgba(255, 255, 255, 0.03) 100%),radial-gradient(100% 97% at 0% 12%, rgba(235, 0, 255, 0.1) 0%, rgba(243, 19, 19, 0.1) 100%), hsla(0, 0%, 100%, 0.1)',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -141,16 +135,15 @@ const StyledArrowUpRight = styled(ArrowUpRight)`
|
||||
`
|
||||
|
||||
const TEXT_COLORS: { [chainId in NetworkAlertChains]: string } = {
|
||||
[ChainId.POLYGON]: 'rgba(130, 71, 229)',
|
||||
[ChainId.POLYGON_MUMBAI]: 'rgba(130, 71, 229)',
|
||||
[ChainId.CELO]: 'rgba(53, 178, 97)',
|
||||
[ChainId.CELO_ALFAJORES]: 'rgba(53, 178, 97)',
|
||||
[ChainId.OPTIMISM]: '#ff3856',
|
||||
[ChainId.OPTIMISM_GOERLI]: '#ff3856',
|
||||
[ChainId.ARBITRUM_ONE]: '#0490ed',
|
||||
[ChainId.BNB]: colors.gold400,
|
||||
[ChainId.ARBITRUM_GOERLI]: '#0490ed',
|
||||
[ChainId.AVALANCHE]: '#ff3856',
|
||||
[SupportedChainId.POLYGON]: 'rgba(130, 71, 229)',
|
||||
[SupportedChainId.POLYGON_MUMBAI]: 'rgba(130, 71, 229)',
|
||||
[SupportedChainId.CELO]: 'rgba(53, 178, 97)',
|
||||
[SupportedChainId.CELO_ALFAJORES]: 'rgba(53, 178, 97)',
|
||||
[SupportedChainId.OPTIMISM]: '#ff3856',
|
||||
[SupportedChainId.OPTIMISM_GOERLI]: '#ff3856',
|
||||
[SupportedChainId.ARBITRUM_ONE]: '#0490ed',
|
||||
[SupportedChainId.BNB]: colors.gold400,
|
||||
[SupportedChainId.ARBITRUM_GOERLI]: '#0490ed',
|
||||
}
|
||||
|
||||
function shouldShowAlert(chainId: number | undefined): chainId is NetworkAlertChains {
|
||||
@@ -160,14 +153,13 @@ function shouldShowAlert(chainId: number | undefined): chainId is NetworkAlertCh
|
||||
export function NetworkAlert() {
|
||||
const { chainId } = useWeb3React()
|
||||
const [darkMode] = useDarkModeManager()
|
||||
const isAvalancheEnabled = useIsAvalancheEnabled()
|
||||
|
||||
if (!shouldShowAlert(chainId)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const chainInfo = getChainInfo(chainId)
|
||||
if (!chainInfo || (!isAvalancheEnabled && chainId === ChainId.AVALANCHE)) return null
|
||||
if (!chainInfo) return null
|
||||
|
||||
const { label, logoUrl, bridge } = chainInfo
|
||||
const textColor = TEXT_COLORS[chainId]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { getChainInfoOrDefault, L2ChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { AlertTriangle } from 'react-feather'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ExternalLink, MEDIA_WIDTHS } from 'theme'
|
||||
@@ -62,7 +62,7 @@ export function ChainConnectivityWarning() {
|
||||
</TitleText>
|
||||
</TitleRow>
|
||||
<BodyRow>
|
||||
{chainId === ChainId.MAINNET ? (
|
||||
{chainId === SupportedChainId.MAINNET ? (
|
||||
<Trans>You may have lost your network connection.</Trans>
|
||||
) : (
|
||||
<Trans>{label} might be down right now, or you may have lost your network connection.</Trans>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import AlertTriangleFilled from 'components/Icons/AlertTriangleFilled'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import styled from 'styled-components/macro'
|
||||
|
||||
import { ThemedText } from '../../theme'
|
||||
@@ -22,7 +22,7 @@ export const PopupAlertTriangle = styled(AlertTriangleFilled)`
|
||||
height: 32px;
|
||||
`
|
||||
|
||||
export default function FailedNetworkSwitchPopup({ chainId }: { chainId: ChainId }) {
|
||||
export default function FailedNetworkSwitchPopup({ chainId }: { chainId: SupportedChainId }) {
|
||||
const chainInfo = getChainInfo(chainId)
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import styled from 'styled-components/macro'
|
||||
import { MEDIA_WIDTHS } from 'theme'
|
||||
|
||||
@@ -62,7 +62,7 @@ export default function Popups() {
|
||||
|
||||
// need extra padding if network is not L1 Ethereum
|
||||
const { chainId } = useWeb3React()
|
||||
const isNotOnMainnet = Boolean(chainId && chainId !== ChainId.MAINNET)
|
||||
const isNotOnMainnet = Boolean(chainId && chainId !== SupportedChainId.MAINNET)
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BigNumber } from '@ethersproject/bignumber'
|
||||
import { ChainId, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId, Token, WETH9 } from '@uniswap/sdk-core'
|
||||
import { FeeAmount, Pool } from '@uniswap/v3-sdk'
|
||||
import { USDC_MAINNET } from 'constants/tokens'
|
||||
import { useToken } from 'hooks/Tokens'
|
||||
@@ -25,7 +25,7 @@ beforeEach(() => {
|
||||
// tokenA: Token, tokenB: Token, fee: FeeAmount, sqrtRatioX96: BigintIsh, liquidity: BigintIsh, tickCurrent: number
|
||||
new Pool(
|
||||
USDC_MAINNET,
|
||||
WETH9[ChainId.MAINNET],
|
||||
WETH9[SupportedChainId.MAINNET],
|
||||
FeeAmount.MEDIUM,
|
||||
'1745948049099224684665158875285708',
|
||||
'4203610460178577802',
|
||||
@@ -37,7 +37,7 @@ beforeEach(() => {
|
||||
test('PositionListItem should render a position', () => {
|
||||
const positionDetails = {
|
||||
token0: USDC_MAINNET.address,
|
||||
token1: WETH9[ChainId.MAINNET].address,
|
||||
token1: WETH9[SupportedChainId.MAINNET].address,
|
||||
tokenId: BigNumber.from(479689),
|
||||
fee: FeeAmount.MEDIUM,
|
||||
liquidity: BigNumber.from('1341008833950736'),
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { Percent } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { AutoColumn } from 'components/Column'
|
||||
import { isSupportedChain, L2_CHAIN_IDS } from 'constants/chains'
|
||||
import { L2_CHAIN_IDS } from 'constants/chains'
|
||||
import useDisableScrolling from 'hooks/useDisableScrolling'
|
||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||
import { isSupportedChainId } from 'lib/hooks/routing/clientSideSmartOrderRouter'
|
||||
import { useRef } from 'react'
|
||||
import { useModalIsOpen, useToggleSettingsMenu } from 'state/application/hooks'
|
||||
import { ApplicationModal } from 'state/application/reducer'
|
||||
@@ -52,11 +54,11 @@ export default function SettingsTab({ autoSlippage, chainId }: { autoSlippage: P
|
||||
|
||||
useDisableScrolling(isOpen)
|
||||
|
||||
const isChainSupported = isSupportedChain(chainId)
|
||||
const isSupportedChain = isSupportedChainId(chainId)
|
||||
|
||||
return (
|
||||
<Menu ref={node}>
|
||||
<MenuButton disabled={!isChainSupported || chainId !== connectedChainId} isActive={isOpen} onClick={toggleMenu} />
|
||||
<MenuButton disabled={!isSupportedChain || chainId !== connectedChainId} isActive={isOpen} onClick={toggleMenu} />
|
||||
{isOpen && (
|
||||
<MenuFlyout>
|
||||
<RouterPreferenceSettings />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { darken } from 'polished'
|
||||
import { useState } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
@@ -67,7 +67,7 @@ const ResourcesContainer = styled.div`
|
||||
|
||||
type AboutSectionProps = {
|
||||
address: string
|
||||
chainId: ChainId
|
||||
chainId: SupportedChainId
|
||||
description?: string | null
|
||||
homepageUrl?: string | null
|
||||
twitterName?: string | null
|
||||
@@ -105,7 +105,7 @@ export function AboutSection({ address, chainId, description, homepageUrl, twitt
|
||||
</ThemedText.SubHeaderSmall>
|
||||
<ResourcesContainer data-cy="resources-container">
|
||||
<Resource
|
||||
name={chainId === ChainId.MAINNET ? 'Etherscan' : 'Block Explorer'}
|
||||
name={chainId === SupportedChainId.MAINNET ? 'Etherscan' : 'Block Explorer'}
|
||||
link={`${explorer}${address === 'NATIVE' ? '' : 'address/' + address}`}
|
||||
/>
|
||||
<Resource name="More analytics" link={`${infoLink}tokens/${address}`} />
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { formatCurrencyAmount, NumberType } from '@uniswap/conedison/format'
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import CurrencyLogo from 'components/Logo/CurrencyLogo'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { asSupportedChain } from 'constants/chains'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { isSupportedChain } from 'constants/chains'
|
||||
import { useStablecoinValue } from 'hooks/useStablecoinPrice'
|
||||
import useCurrencyBalance from 'lib/hooks/useCurrencyBalance'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
@@ -66,7 +67,7 @@ const StyledNetworkLabel = styled.div`
|
||||
export default function BalanceSummary({ token }: { token: Currency }) {
|
||||
const { account, chainId } = useWeb3React()
|
||||
const theme = useTheme()
|
||||
const { label, color } = getChainInfo(asSupportedChain(chainId) ?? ChainId.MAINNET)
|
||||
const { label, color } = getChainInfo(isSupportedChain(chainId) ? chainId : SupportedChainId.MAINNET)
|
||||
const balance = useCurrencyBalance(account, token)
|
||||
const formattedBalance = formatCurrencyAmount(balance, NumberType.TokenNonTx)
|
||||
const formattedUsdValue = formatCurrencyAmount(useStablecoinValue(balance), NumberType.FiatTokenStats)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { ButtonPrimary } from 'components/Button'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import useSelectChain from 'hooks/useSelectChain'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import styled from 'styled-components/macro'
|
||||
@@ -43,7 +43,7 @@ export default function InvalidTokenDetails({
|
||||
pageChainId,
|
||||
isInvalidAddress,
|
||||
}: {
|
||||
pageChainId: ChainId
|
||||
pageChainId: SupportedChainId
|
||||
isInvalidAddress?: boolean
|
||||
}) {
|
||||
const { chainId } = useWeb3React()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { formatNumber, NumberType } from '@uniswap/conedison/format'
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { ReactNode } from 'react'
|
||||
import styled from 'styled-components/macro'
|
||||
import { ExternalLink, ThemedText } from 'theme'
|
||||
@@ -68,7 +68,7 @@ function Stat({
|
||||
}
|
||||
|
||||
type StatsSectionProps = {
|
||||
chainId: ChainId
|
||||
chainId: SupportedChainId
|
||||
address: string
|
||||
priceLow52W?: NumericStat
|
||||
priceHigh52W?: NumericStat
|
||||
|
||||
@@ -26,7 +26,7 @@ import { checkWarning } from 'constants/tokenSafety'
|
||||
import { TokenPriceQuery } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { Chain, TokenQuery, TokenQueryData } from 'graphql/data/Token'
|
||||
import { QueryToken } from 'graphql/data/Token'
|
||||
import { getTokenDetailsURL, InterfaceGqlChain, supportedChainIdFromGQLChain } from 'graphql/data/util'
|
||||
import { CHAIN_NAME_TO_CHAIN_ID, getTokenDetailsURL } from 'graphql/data/util'
|
||||
import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch'
|
||||
import { UNKNOWN_TOKEN_SYMBOL, useTokenFromActiveNetwork } from 'lib/hooks/useCurrency'
|
||||
import { Swap } from 'pages/Swap'
|
||||
@@ -89,7 +89,7 @@ function useRelevantToken(
|
||||
type TokenDetailsProps = {
|
||||
urlAddress?: string
|
||||
inputTokenAddress?: string
|
||||
chain: InterfaceGqlChain
|
||||
chain: Chain
|
||||
tokenQuery: TokenQuery
|
||||
tokenPriceQuery?: TokenPriceQuery
|
||||
onChangeTimePeriod: OnChangeTimePeriod
|
||||
@@ -111,7 +111,8 @@ export default function TokenDetails({
|
||||
)
|
||||
|
||||
const { chainId: connectedChainId } = useWeb3React()
|
||||
const pageChainId = supportedChainIdFromGQLChain(chain)
|
||||
const pageChainId = CHAIN_NAME_TO_CHAIN_ID[chain]
|
||||
|
||||
const tokenQueryData = tokenQuery.token
|
||||
const crossChainMap = useMemo(
|
||||
() =>
|
||||
@@ -184,7 +185,6 @@ export default function TokenDetails({
|
||||
},
|
||||
[continueSwap, setContinueSwap]
|
||||
)
|
||||
|
||||
// address will never be undefined if token is defined; address is checked here to appease typechecker
|
||||
if (detailedToken === undefined || !address) {
|
||||
return <InvalidTokenDetails pageChainId={pageChainId} isInvalidAddress={!address} />
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import Badge from 'components/Badge'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { useFilterChainsForAvalanche } from 'featureFlags/flags/avalanche'
|
||||
import {
|
||||
BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS,
|
||||
BACKEND_SUPPORTED_CHAINS,
|
||||
supportedChainIdFromGQLChain,
|
||||
validateUrlChainParam,
|
||||
} from 'graphql/data/util'
|
||||
import { BACKEND_CHAIN_NAMES, CHAIN_NAME_TO_CHAIN_ID, validateUrlChainParam } from 'graphql/data/util'
|
||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||
import { useRef } from 'react'
|
||||
import { Check, ChevronDown, ChevronUp } from 'react-feather'
|
||||
@@ -118,12 +112,12 @@ export default function NetworkFilter() {
|
||||
const toggleMenu = useToggleModal(ApplicationModal.NETWORK_FILTER)
|
||||
useOnClickOutside(node, open ? toggleMenu : undefined)
|
||||
const navigate = useNavigate()
|
||||
const gatedUnsupportedChains = useFilterChainsForAvalanche([...BACKEND_NOT_YET_SUPPORTED_CHAIN_IDS])
|
||||
|
||||
const { chainName } = useParams<{ chainName?: string }>()
|
||||
const currentChainName = validateUrlChainParam(chainName)
|
||||
|
||||
const chainInfo = getChainInfo(supportedChainIdFromGQLChain(currentChainName))
|
||||
const chainInfo = getChainInfo(CHAIN_NAME_TO_CHAIN_ID[currentChainName])
|
||||
const BNBChainInfo = getChainInfo(CHAIN_NAME_TO_CHAIN_ID.BNB)
|
||||
|
||||
return (
|
||||
<StyledMenu ref={node}>
|
||||
@@ -135,7 +129,7 @@ export default function NetworkFilter() {
|
||||
>
|
||||
<StyledMenuContent>
|
||||
<NetworkLabel>
|
||||
<Logo src={chainInfo.logoUrl} /> {chainInfo.label}
|
||||
<Logo src={chainInfo?.logoUrl} /> {chainInfo?.label}
|
||||
</NetworkLabel>
|
||||
<Chevron open={open}>
|
||||
{open ? (
|
||||
@@ -148,8 +142,9 @@ export default function NetworkFilter() {
|
||||
</NetworkFilterOption>
|
||||
{open && (
|
||||
<MenuTimeFlyout>
|
||||
{BACKEND_SUPPORTED_CHAINS.map((network) => {
|
||||
const chainInfo = getChainInfo(supportedChainIdFromGQLChain(network))
|
||||
{BACKEND_CHAIN_NAMES.map((network) => {
|
||||
const chainInfo = getChainInfo(CHAIN_NAME_TO_CHAIN_ID[network])
|
||||
if (!chainInfo) return null
|
||||
return (
|
||||
<InternalLinkMenuItem
|
||||
key={network}
|
||||
@@ -171,22 +166,13 @@ export default function NetworkFilter() {
|
||||
</InternalLinkMenuItem>
|
||||
)
|
||||
})}
|
||||
{gatedUnsupportedChains.map((network) => {
|
||||
const chainInfo = getChainInfo(network)
|
||||
return (
|
||||
<InternalLinkMenuItem
|
||||
key={network}
|
||||
data-testid={`tokens-network-filter-option-${network}-chain`}
|
||||
disabled
|
||||
>
|
||||
<NetworkLabel>
|
||||
<Logo src={chainInfo.logoUrl} />
|
||||
{chainInfo.label}
|
||||
</NetworkLabel>
|
||||
<Tag>Coming soon</Tag>
|
||||
</InternalLinkMenuItem>
|
||||
)
|
||||
})}
|
||||
<InternalLinkMenuItem data-testid="tokens-network-filter-option-bnb-chain" disabled>
|
||||
<NetworkLabel>
|
||||
<Logo src={BNBChainInfo.logoUrl} />
|
||||
{BNBChainInfo.label}
|
||||
</NetworkLabel>
|
||||
<Tag>Coming soon</Tag>
|
||||
</InternalLinkMenuItem>
|
||||
</MenuTimeFlyout>
|
||||
)}
|
||||
</StyledMenu>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { Currency, TokenStandard } from 'graphql/data/__generated__/types-and-hooks'
|
||||
import { CHAIN_ID_TO_BACKEND_NAME } from 'graphql/data/util'
|
||||
import { render, screen } from 'test-utils/render'
|
||||
@@ -72,7 +72,7 @@ describe('LoadedRow.tsx', () => {
|
||||
__typename: 'Token',
|
||||
id: 'VG9rZW46RVRIRVJFVU1fMHhBMGI4Njk5MWM2MjE4YjM2YzFkMTlENGEyZTlFYjBjRTM2MDZlQjQ4',
|
||||
name: 'USD Coin',
|
||||
chain: CHAIN_ID_TO_BACKEND_NAME[ChainId.MAINNET],
|
||||
chain: CHAIN_ID_TO_BACKEND_NAME[SupportedChainId.MAINNET],
|
||||
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||
symbol: 'USDC',
|
||||
standard: TokenStandard.Erc20,
|
||||
@@ -96,7 +96,7 @@ describe('LoadedRow.tsx', () => {
|
||||
__typename: 'Token',
|
||||
id: 'VG9rZW46RVRIRVJFVU1fMHhBMGI4Njk5MWM2MjE4YjM2YzFkMTlENGEyZTlFYjBjRTM2MDZlQjQ4',
|
||||
name: 'USD Coin',
|
||||
chain: CHAIN_ID_TO_BACKEND_NAME[ChainId.MAINNET],
|
||||
chain: CHAIN_ID_TO_BACKEND_NAME[SupportedChainId.MAINNET],
|
||||
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||
symbol: 'USDC',
|
||||
standard: TokenStandard.Erc20,
|
||||
|
||||
@@ -7,7 +7,7 @@ import SparklineChart from 'components/Charts/SparklineChart'
|
||||
import QueryTokenLogo from 'components/Logo/QueryTokenLogo'
|
||||
import { MouseoverTooltip } from 'components/Tooltip'
|
||||
import { SparklineMap, TopToken } from 'graphql/data/TopTokens'
|
||||
import { getTokenDetailsURL, supportedChainIdFromGQLChain, validateUrlChainParam } from 'graphql/data/util'
|
||||
import { CHAIN_NAME_TO_CHAIN_ID, getTokenDetailsURL, validateUrlChainParam } from 'graphql/data/util'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { ForwardedRef, forwardRef } from 'react'
|
||||
import { CSSProperties, ReactNode } from 'react'
|
||||
@@ -435,7 +435,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
|
||||
const filterString = useAtomValue(filterStringAtom)
|
||||
|
||||
const filterNetwork = validateUrlChainParam(useParams<{ chainName?: string }>().chainName?.toUpperCase())
|
||||
const chainId = supportedChainIdFromGQLChain(filterNetwork)
|
||||
const chainId = CHAIN_NAME_TO_CHAIN_ID[filterNetwork]
|
||||
const timePeriod = useAtomValue(filterTimeAtom)
|
||||
const delta = token.market?.pricePercentChange?.value
|
||||
const arrow = getDeltaArrow(delta)
|
||||
@@ -458,7 +458,7 @@ export const LoadedRow = forwardRef((props: LoadedRowProps, ref: ForwardedRef<HT
|
||||
|
||||
// TODO: currency logo sizing mobile (32px) vs. desktop (24px)
|
||||
return (
|
||||
<div ref={ref} data-testid={`token-table-row-${token.address}`}>
|
||||
<div ref={ref} data-testid={`token-table-row-${token.symbol}`}>
|
||||
<StyledLink
|
||||
to={getTokenDetailsURL(token)}
|
||||
onClick={() =>
|
||||
|
||||
@@ -327,7 +327,7 @@ exports[`LoadedRow.tsx renders a row 1`] = `
|
||||
}
|
||||
|
||||
<div
|
||||
data-testid="token-table-row-0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
||||
data-testid="token-table-row-USDC"
|
||||
>
|
||||
<a
|
||||
class="c0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChainId } from '@uniswap/sdk-core'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
|
||||
export const MAX_WIDTH_MEDIA_BREAKPOINT = '1200px'
|
||||
export const XLARGE_MEDIA_BREAKPOINT = '960px'
|
||||
@@ -8,4 +8,4 @@ export const SMALL_MEDIA_BREAKPOINT = '540px'
|
||||
export const MOBILE_MEDIA_BREAKPOINT = '420px'
|
||||
|
||||
// includes chains that the backend does not current source off-chain metadata for
|
||||
export const UNSUPPORTED_METADATA_CHAINS = [ChainId.BNB, ChainId.AVALANCHE]
|
||||
export const UNSUPPORTED_METADATA_CHAINS = [SupportedChainId.BNB]
|
||||
|
||||
@@ -8,10 +8,11 @@ import useAccountRiskCheck from 'hooks/useAccountRiskCheck'
|
||||
import { lazy } from 'react'
|
||||
import { useModalIsOpen, useToggleModal } from 'state/application/hooks'
|
||||
import { ApplicationModal } from 'state/application/reducer'
|
||||
import { retry } from 'utils/retry'
|
||||
|
||||
const Bag = lazy(() => import('nft/components/bag/Bag'))
|
||||
const TransactionCompleteModal = lazy(() => import('nft/components/collection/TransactionCompleteModal'))
|
||||
const AirdropModal = lazy(() => import('components/AirdropModal'))
|
||||
const Bag = lazy(() => retry(() => import('nft/components/bag/Bag')))
|
||||
const TransactionCompleteModal = lazy(() => retry(() => import('nft/components/collection/TransactionCompleteModal')))
|
||||
const AirdropModal = lazy(() => retry(() => import('components/AirdropModal')))
|
||||
|
||||
export default function TopLevelModals() {
|
||||
const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { t, Trans } from '@lingui/macro'
|
||||
import { ChainId, Currency } from '@uniswap/sdk-core'
|
||||
import { Trans } from '@lingui/macro'
|
||||
import { Currency } from '@uniswap/sdk-core'
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import Badge from 'components/Badge'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedL2ChainId } from 'constants/chains'
|
||||
import { SupportedChainId, SupportedL2ChainId } from 'constants/chains'
|
||||
import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs'
|
||||
import { ReactNode, useCallback, useState } from 'react'
|
||||
import { AlertCircle, ArrowUpCircle, CheckCircle } from 'react-feather'
|
||||
@@ -120,8 +120,6 @@ function TransactionSubmittedContent({
|
||||
.catch(() => setSuccess(false))
|
||||
}, [connector, logoURL, token])
|
||||
|
||||
const explorerText = chainId === ChainId.MAINNET ? t`View on Etherscan` : t`View on Block Explorer`
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<AutoColumn>
|
||||
@@ -159,7 +157,9 @@ function TransactionSubmittedContent({
|
||||
</ButtonPrimary>
|
||||
{chainId && hash && (
|
||||
<ExternalLink href={getExplorerLink(chainId, hash, ExplorerDataType.TRANSACTION)}>
|
||||
<ThemedText.Link color={theme.accentAction}>{explorerText}</ThemedText.Link>
|
||||
<ThemedText.Link color={theme.accentAction}>
|
||||
<Trans>View on {chainId === SupportedChainId.MAINNET ? 'Etherscan' : 'Block Explorer'}</Trans>
|
||||
</ThemedText.Link>
|
||||
</ExternalLink>
|
||||
)}
|
||||
</ConfirmationModalContentWrapper>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user