diff --git a/.github/workflows/bundle.yaml b/.github/workflows/bundle.yaml deleted file mode 100644 index 1f99c34841..0000000000 --- a/.github/workflows/bundle.yaml +++ /dev/null @@ -1,40 +0,0 @@ -name: Widgets -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Set up node - uses: actions/setup-node@v2 - with: - node-version: 14 - registry-url: https://registry.npmjs.org - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - uses: actions/cache@v2 - id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`) - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} - restore-keys: | - ${{ runner.os }}-yarn- - - - name: Install dependencies - run: yarn install --frozen-lockfile - - - name: Build - run: yarn widgets:build \ No newline at end of file diff --git a/.gitignore b/.gitignore index a930a63082..0eca01ba3b 100644 --- a/.gitignore +++ b/.gitignore @@ -19,8 +19,6 @@ # builds /build -/cosmos-export -/dist /dts # misc diff --git a/INTERFACE_README.md b/INTERFACE_README.md deleted file mode 100644 index 6c120eb317..0000000000 --- a/INTERFACE_README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Uniswap Interface - -An open source interface for Uniswap -- a protocol for decentralized exchange of Ethereum tokens. - -- Website: [uniswap.org](https://uniswap.org/) -- Interface: [app.uniswap.org](https://app.uniswap.org) -- Docs: [uniswap.org/docs/](https://docs.uniswap.org/) -- Twitter: [@Uniswap](https://twitter.com/Uniswap) -- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/) -- Email: [contact@uniswap.org](mailto:contact@uniswap.org) -- Discord: [Uniswap](https://discord.gg/FCfyBSbCU5) -- Whitepapers: - - [V1](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig) - - [V2](https://uniswap.org/whitepaper.pdf) - - [V3](https://uniswap.org/whitepaper-v3.pdf) - -## Accessing the Uniswap Interface - -To access the Uniswap Interface, use an IPFS gateway link from the -[latest release](https://github.com/Uniswap/uniswap-interface/releases/latest), -or visit [app.uniswap.org](https://app.uniswap.org). - -## Unsupported tokens - -Check out `useUnsupportedTokenList()` in [src/state/lists/hooks.ts](./src/state/lists/hooks.ts) for blocking tokens in your instance of the interface. - -You can block an entire list of tokens by passing in a tokenlist like [here](./src/constants/lists.ts) or you can block specific tokens by adding them to [unsupported.tokenlist.json](./src/constants/tokenLists/unsupported.tokenlist.json). - -## Contributions - -For steps on local deployment, development, and code contribution, please see [CONTRIBUTING](./CONTRIBUTING.md). - -## Accessing Uniswap V2 - -The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2. - -- Swap on Uniswap V2: https://app.uniswap.org/#/swap?use=v2 -- View V2 liquidity: https://app.uniswap.org/#/pool/v2 -- Add V2 liquidity: https://app.uniswap.org/#/add/v2 -- Migrate V2 liquidity to V3: https://app.uniswap.org/#/migrate/v2 - -## Accessing Uniswap V1 - -The Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways -linked from the [v1.0.0 release](https://github.com/Uniswap/uniswap-interface/releases/tag/v1.0.0). diff --git a/README.md b/README.md index d99aa6be17..5ebd35e266 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -This repo is home to the Uniswap Widgets package and the web app interface [app.uniswap.org](https://app.uniswap.org). - # Uniswap Labs Interface [![Unit Tests](https://github.com/Uniswap/interface/actions/workflows/unit-tests.yaml/badge.svg)](https://github.com/Uniswap/interface/actions/workflows/unit-tests.yaml) @@ -8,14 +6,46 @@ This repo is home to the Uniswap Widgets package and the web app interface [app. [![Release](https://github.com/Uniswap/interface/actions/workflows/release.yaml/badge.svg)](https://github.com/Uniswap/interface/actions/workflows/release.yaml) [![Crowdin](https://badges.crowdin.net/uniswap-interface/localized.svg)](https://crowdin.com/project/uniswap-interface) -The web application hosted at https://app.uniswap.org is a convenient way to access the core functionality of the Uniswap Protocol. +An open source interface for Uniswap -- a protocol for decentralized exchange of Ethereum tokens. -For documentation of the interface including how to contribute or access prior builds, please view the README here: [INTERFACE_README.md](./INTERFACE_README.md) +- Website: [uniswap.org](https://uniswap.org/) +- Interface: [app.uniswap.org](https://app.uniswap.org) +- Docs: [uniswap.org/docs/](https://docs.uniswap.org/) +- Twitter: [@Uniswap](https://twitter.com/Uniswap) +- Reddit: [/r/Uniswap](https://www.reddit.com/r/Uniswap/) +- Email: [contact@uniswap.org](mailto:contact@uniswap.org) +- Discord: [Uniswap](https://discord.gg/FCfyBSbCU5) +- Whitepapers: + - [V1](https://hackmd.io/C-DvwDSfSxuh-Gd4WKE_ig) + - [V2](https://uniswap.org/whitepaper.pdf) + - [V3](https://uniswap.org/whitepaper-v3.pdf) -# Uniswap Labs Widgets +## Accessing the Uniswap Interface -The `@uniswap/widgets` package is an npm package of React components used to provide subsets of the Uniswap Protocol functionality in a small and configurable user interface element. +To access the Uniswap Interface, use an IPFS gateway link from the +[latest release](https://github.com/Uniswap/uniswap-interface/releases/latest), +or visit [app.uniswap.org](https://app.uniswap.org). -The npm package can be found here. [@uniswap/widgets](https://www.npmjs.com/package/@uniswap/widgets) +## Unsupported tokens -For documentation of the widgets package, please view the README here: [WIDGETS_README.md](./WIDGETS_README.md). +Check out `useUnsupportedTokenList()` in [src/state/lists/hooks.ts](./src/state/lists/hooks.ts) for blocking tokens in your instance of the interface. + +You can block an entire list of tokens by passing in a tokenlist like [here](./src/constants/lists.ts) or you can block specific tokens by adding them to [unsupported.tokenlist.json](./src/constants/tokenLists/unsupported.tokenlist.json). + +## Contributions + +For steps on local deployment, development, and code contribution, please see [CONTRIBUTING](./CONTRIBUTING.md). + +## Accessing Uniswap V2 + +The Uniswap Interface supports swapping, adding liquidity, removing liquidity and migrating liquidity for Uniswap protocol V2. + +- Swap on Uniswap V2: https://app.uniswap.org/#/swap?use=v2 +- View V2 liquidity: https://app.uniswap.org/#/pool/v2 +- Add V2 liquidity: https://app.uniswap.org/#/add/v2 +- Migrate V2 liquidity to V3: https://app.uniswap.org/#/migrate/v2 + +## Accessing Uniswap V1 + +The Uniswap V1 interface for mainnet and testnets is accessible via IPFS gateways +linked from the [v1.0.0 release](https://github.com/Uniswap/uniswap-interface/releases/tag/v1.0.0). \ No newline at end of file diff --git a/WIDGETS_README.md b/WIDGETS_README.md deleted file mode 100644 index efcba01368..0000000000 --- a/WIDGETS_README.md +++ /dev/null @@ -1,40 +0,0 @@ -# Uniswap Labs Swap Widget - -The Swap Widget bundles the whole swapping experience into a single React component that developers can easily embed in their app with one line of code. - -![swap widget screenshot](https://raw.githubusercontent.com/Uniswap/interface/main/src/assets/images/widget-screenshot.png) - -You can customize the theme (colors, fonts, border radius, and more) to match the style of your application. You can also configure your own default token list and optionally set a convenience fee on swaps executed through the widget on your site. - -## Installation - -Install the widgets library via `npm` or `yarn`. If you do not already use the widget's peerDependencies `redux` and `react-redux`, then you'll need to add them as well. - -```js -yarn add @uniswap/widgets redux react-redux -``` -```js -npm i --save @uniswap/widgets redux react-redux -``` - -## Documentation - -- [overview](https://docs.uniswap.org/sdk/widgets/swap-widget) -- [api reference](https://docs.uniswap.org/sdk/widgets/swap-widget/api) - -## Example Apps - -Uniswap Labs maintains two demo apps in branches of the [widgets-demo](https://github.com/Uniswap/widgets-demo) repo: - -- [NextJS](https://github.com/Uniswap/widgets-demo/tree/nextjs) -- [Create React App](https://github.com/Uniswap/widgets-demo/tree/cra) - -Others have also also released the widget in production to their userbase: - -- [OpenSea](https://opensea.io/) -- [Friends With Benefits](https://www.fwb.help/) -- [Oasis](https://oasis.app/) - -## Legal notice - -Uniswap Labs encourages integrators to evaluate their own regulatory obligations when integrating this widget into their products, including, but not limited to, those related to economic or trade sanctions compliance. diff --git a/cosmos.config.json b/cosmos.config.json deleted file mode 100644 index 6141eb839d..0000000000 --- a/cosmos.config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "watchDirs": [ - "src" - ], - "webpack": { - "configPath": "react-scripts/config/webpack.config", - "overridePath": "cosmos.override.cjs" - }, - "port": 5001 -} diff --git a/cosmos.override.cjs b/cosmos.override.cjs deleted file mode 100644 index 10132a4903..0000000000 --- a/cosmos.override.cjs +++ /dev/null @@ -1,26 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const HtmlWebpackPlugin = require('html-webpack-plugin') -const { DefinePlugin } = require('webpack') - -// Renders the cosmos fixtures in isolation, instead of using public/index.html. -module.exports = (webpackConfig) => ({ - ...webpackConfig, - plugins: webpackConfig.plugins.map((plugin) => { - if (plugin instanceof HtmlWebpackPlugin) { - return new HtmlWebpackPlugin({ - templateContent: '', - }) - } - if (plugin instanceof DefinePlugin) { - return new DefinePlugin({ - ...plugin.definitions, - 'process.env': { - ...plugin.definitions['process.env'], - REACT_APP_IS_WIDGET: true, - REACT_APP_LOCALES: '"../locales"', - }, - }) - } - return plugin - }), -}) diff --git a/package.json b/package.json index 324a604989..91b2a2785b 100644 --- a/package.json +++ b/package.json @@ -44,16 +44,6 @@ "@reach/dialog": "^0.10.3", "@reach/portal": "^0.10.3", "@react-hook/window-scroll": "^1.3.0", - "@rollup/plugin-alias": "^3.1.9", - "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-commonjs": "^21.0.1", - "@rollup/plugin-eslint": "^8.0.1", - "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^13.1.3", - "@rollup/plugin-replace": "^3.0.1", - "@rollup/plugin-typescript": "^8.3.0", - "@rollup/plugin-url": "^6.1.0", - "@svgr/rollup": "^6.2.0", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^12.0.0", "@testing-library/react-hooks": "^7.0.2", @@ -117,7 +107,6 @@ "qs": "^6.9.4", "react": "^17.0.1", "react-confetti": "^6.0.0", - "react-cosmos": "^5.6.6", "react-dom": "^17.0.1", "react-ga4": "^1.4.1", "react-is": "^17.0.2", @@ -129,14 +118,6 @@ "react-use-gesture": "^6.0.14", "redux": "^4.1.2", "redux-localstorage-simple": "^2.3.1", - "rollup": "^2.63.0", - "rollup-plugin-copy": "^3.4.0", - "rollup-plugin-delete": "^2.0.0", - "rollup-plugin-dts": "^4.1.0", - "rollup-plugin-multi-input": "^1.3.1", - "rollup-plugin-node-externals": "^3.1.2", - "rollup-plugin-scss": "^3.0.0", - "rollup-plugin-typescript2": "^0.31.1", "sass": "^1.45.1", "serve": "^11.3.2", "start-server-and-test": "^1.11.0", @@ -170,13 +151,10 @@ "i18n:compile": "yarn i18n:extract && lingui compile", "i18n:pseudo": "lingui extract --locale pseudo && lingui compile", "prepare": "yarn contracts:compile && yarn graphql:generate && yarn i18n:compile", - "prepublishOnly": "yarn widgets:build", "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=./custom-test-env.cjs", - "test:e2e": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run --record'", - "widgets:start": "cosmos", - "widgets:build": "rollup --config --failAfterWarnings --configPlugin typescript2" + "test:e2e": "start-server-and-test 'serve build -l 3000' http://localhost:3000 'cypress run --record'" }, "browserslist": { "production": [ diff --git a/rollup.config.ts b/rollup.config.ts deleted file mode 100644 index 21d8771668..0000000000 --- a/rollup.config.ts +++ /dev/null @@ -1,182 +0,0 @@ -/** - * Bundles the widgets library, which is released independently of the interface application. - * This library lives in src/lib, but shares code with the interface application. - */ - -import alias from '@rollup/plugin-alias' -import babel from '@rollup/plugin-babel' -import commonjs from '@rollup/plugin-commonjs' -import json from '@rollup/plugin-json' -import resolve from '@rollup/plugin-node-resolve' -import replace from '@rollup/plugin-replace' -import typescript from '@rollup/plugin-typescript' -import url from '@rollup/plugin-url' -import svgr from '@svgr/rollup' -import path from 'path' -import { RollupWarning } from 'rollup' -import copy from 'rollup-plugin-copy' -import del from 'rollup-plugin-delete' -import dts from 'rollup-plugin-dts' -// @ts-ignore // missing types -import multi from 'rollup-plugin-multi-input' -import externals from 'rollup-plugin-node-externals' -import sass from 'rollup-plugin-scss' -import { CompilerOptions } from 'typescript' - -const REPLACEMENTS = { - 'process.env.REACT_APP_IS_WIDGET': true, - 'process.env.REACT_APP_LOCALES': '"./locales"', - // esm requires fully-specified paths: - 'react/jsx-runtime': 'react/jsx-runtime.js', -} - -const EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx'] -const ASSET_EXTENSIONS = ['.png', '.svg'] -function isAsset(source: string) { - const extname = path.extname(source) - return extname && [...ASSET_EXTENSIONS, '.css', '.scss'].includes(extname) -} - -function isEthers(source: string) { - // @ethersproject/* modules are provided by ethers, with the exception of experimental. - return source.startsWith('@ethersproject/') && !source.endsWith('experimental') -} - -const TS_CONFIG = './tsconfig.lib.json' -// eslint-disable-next-line @typescript-eslint/no-var-requires -const { baseUrl, paths }: CompilerOptions = require(TS_CONFIG).compilerOptions -const aliases = Object.entries({ ...paths }).flatMap(([find, replacements]) => { - return replacements.map((replacement) => ({ - find: path.dirname(find), - replacement: path.join(__dirname, baseUrl || '.', path.dirname(replacement)), - })) -}) - -const plugins = [ - // Dependency resolution - resolve({ extensions: EXTENSIONS }), // resolves third-party modules within node_modules/ - alias({ entries: aliases }), // resolves paths aliased through the tsconfig (babel does not use tsconfig path resolution) - - // Source code transformation - replace({ ...REPLACEMENTS, preventAssignment: true }), - json(), // imports json as ES6; doing so enables type-checking and module resolution -] - -const check = { - input: 'src/lib/index.tsx', - output: { file: 'dist/widgets.tsc', inlineDynamicImports: true }, - external: (source: string) => isAsset(source) || isEthers(source), - plugins: [ - externals({ exclude: ['constants'], deps: true, peerDeps: true }), // marks builtins, dependencies, and peerDependencies external - ...plugins, - typescript({ tsconfig: TS_CONFIG }), - ], - onwarn: squelchTranspilationWarnings, // this pipeline is only for typechecking and generating definitions -} - -const type = { - input: 'dist/dts/lib/index.d.ts', - output: { file: 'dist/index.d.ts' }, - external: (source: string) => isAsset(source) || isEthers(source), - plugins: [ - externals({ exclude: ['constants'], deps: true, peerDeps: true }), - dts({ compilerOptions: { baseUrl: 'dist/dts' } }), - process.env.ROLLUP_WATCH ? undefined : del({ hook: 'buildEnd', targets: ['dist/widgets.tsc', 'dist/dts'] }), - ], -} - -/** - * This exports scheme works for nextjs and for CRA5. - * - * It will also work for CRA4 if you use direct imports: - * instead of `import { SwapWidget } from '@uniswap/widgets'`, - * `import { SwapWidget } from '@uniswap/widgets/dist/index.js'`. - * I do not know why CRA4 does not seem to use exports for resolution. - * - * Note that chunks are enabled. This is so the tokenlist spec can be loaded async, - * to improve first load time (due to ajv). Locales are also in separate chunks. - * - * Lastly, note that JSON and lingui are bundled into the library, as neither are fully - * supported/compatible with ES Modules. Both _could_ be bundled only with esm, but this - * yields a less complex pipeline. - */ - -const transpile = { - input: 'src/lib/index.tsx', - output: [ - { - dir: 'dist', - format: 'esm', - sourcemap: false, - }, - { - dir: 'dist/cjs', - entryFileNames: '[name].cjs', - chunkFileNames: '[name]-[hash].cjs', - format: 'cjs', - sourcemap: false, - }, - ], - external: isEthers, - plugins: [ - externals({ - exclude: [ - 'constants', - /@lingui\/(core|react)/, // @lingui incorrectly exports esm, so it must be bundled in - /\.json$/, // esm does not support JSON loading, so it must be bundled in - ], - deps: true, - peerDeps: true, - }), - ...plugins, - - // Source code transformation - url({ include: ASSET_EXTENSIONS.map((extname) => '**/*' + extname), limit: Infinity }), // imports assets as data URIs - svgr({ exportType: 'named', svgo: false }), // imports svgs as React components - sass({ output: 'dist/fonts.css' }), // generates fonts.css - commonjs(), // transforms cjs dependencies into tree-shakeable ES modules - - babel({ - babelHelpers: 'runtime', - presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }], '@babel/preset-typescript'], - extensions: EXTENSIONS, - plugins: [ - 'macros', // enables @lingui and styled-components macros - '@babel/plugin-transform-runtime', // embeds the babel runtime for library distribution - ], - }), - ], - onwarn: squelchTypeWarnings, // this pipeline is only for transpilation -} - -const locales = { - input: 'src/locales/*.js', - output: [ - { - dir: 'dist', - format: 'esm', - sourcemap: false, - }, - ], - plugins: [ - copy({ - copyOnce: true, - targets: [{ src: 'src/locales/*.js', dest: 'dist/cjs/locales', rename: (name) => `${name}.cjs` }], - }), - commonjs(), - multi(), - ], -} - -const config = [check, type, transpile, locales] -export default config - -function squelchTranspilationWarnings(warning: RollupWarning, warn: (warning: RollupWarning) => void) { - if (warning.pluginCode === 'TS5055') return - warn(warning) -} - -function squelchTypeWarnings(warning: RollupWarning, warn: (warning: RollupWarning) => void) { - if (warning.code === 'UNUSED_EXTERNAL_IMPORT') return - warn(warning) -} diff --git a/src/components/RoutingDiagram/RoutingDiagram.tsx b/src/components/RoutingDiagram/RoutingDiagram.tsx index f1b2150aac..f66a3a2d25 100644 --- a/src/components/RoutingDiagram/RoutingDiagram.tsx +++ b/src/components/RoutingDiagram/RoutingDiagram.tsx @@ -5,8 +5,8 @@ import Badge from 'components/Badge' import CurrencyLogo from 'components/CurrencyLogo' import DoubleCurrencyLogo from 'components/DoubleLogo' import Row, { AutoRow } from 'components/Row' +import { RoutingDiagramEntry } from 'components/swap/SwapRoute' import { useTokenInfoFromActiveList } from 'hooks/useTokenInfoFromActiveList' -import { RoutingDiagramEntry } from 'lib/components/Swap/RoutingDiagram/utils' import { Box } from 'rebass' import styled from 'styled-components/macro' import { ThemedText, Z_INDEX } from 'theme' diff --git a/src/components/swap/SwapRoute.tsx b/src/components/swap/SwapRoute.tsx index 16cc11ab8c..1236203342 100644 --- a/src/components/swap/SwapRoute.tsx +++ b/src/components/swap/SwapRoute.tsx @@ -1,5 +1,8 @@ import { Trans } from '@lingui/macro' -import { Currency, TradeType } from '@uniswap/sdk-core' +import { Protocol } from '@uniswap/router-sdk' +import { Currency, Percent, TradeType } from '@uniswap/sdk-core' +import { Pair } from '@uniswap/v2-sdk' +import { FeeAmount } from '@uniswap/v3-sdk' import AnimatedDropdown from 'components/AnimatedDropdown' import { AutoColumn } from 'components/Column' import { LoadingRows } from 'components/Loader/styled' @@ -8,7 +11,6 @@ import { AutoRow, RowBetween } from 'components/Row' import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains' import useActiveWeb3React from 'hooks/useActiveWeb3React' import useAutoRouterSupported from 'hooks/useAutoRouterSupported' -import { getTokenPath } from 'lib/components/Swap/RoutingDiagram/utils' import { memo, useState } from 'react' import { Plus } from 'react-feather' import { InterfaceTrade } from 'state/routing/types' @@ -106,3 +108,41 @@ export default memo(function SwapRoute({ trade, syncing, fixedOpen = false, ...r ) }) + +export interface RoutingDiagramEntry { + percent: Percent + path: [Currency, Currency, FeeAmount][] + protocol: Protocol +} + +const V2_DEFAULT_FEE_TIER = 3000 + +/** + * Loops through all routes on a trade and returns an array of diagram entries. + */ +export function getTokenPath(trade: InterfaceTrade): RoutingDiagramEntry[] { + return trade.swaps.map(({ route: { path: tokenPath, pools, protocol }, inputAmount, outputAmount }) => { + const portion = + trade.tradeType === TradeType.EXACT_INPUT + ? inputAmount.divide(trade.inputAmount) + : outputAmount.divide(trade.outputAmount) + const percent = new Percent(portion.numerator, portion.denominator) + const path: RoutingDiagramEntry['path'] = [] + for (let i = 0; i < pools.length; i++) { + const nextPool = pools[i] + const tokenIn = tokenPath[i] + const tokenOut = tokenPath[i + 1] + const entry: RoutingDiagramEntry['path'][0] = [ + tokenIn, + tokenOut, + nextPool instanceof Pair ? V2_DEFAULT_FEE_TIER : nextPool.fee, + ] + path.push(entry) + } + return { + percent, + path, + protocol, + } + }) +} diff --git a/src/hooks/useActiveWeb3React.ts b/src/hooks/useActiveWeb3React.ts index c3529196bb..e9c5c0207b 100644 --- a/src/hooks/useActiveWeb3React.ts +++ b/src/hooks/useActiveWeb3React.ts @@ -1,15 +1,10 @@ /* eslint-disable react-hooks/rules-of-hooks */ import { Web3Provider } from '@ethersproject/providers' -import { default as useWidgetsWeb3React } from 'lib/hooks/useActiveWeb3React' import { useWeb3React } from 'web3-react-core' import { NetworkContextName } from '../constants/misc' export default function useActiveWeb3React() { - if (process.env.REACT_APP_IS_WIDGET) { - return useWidgetsWeb3React() - } - const interfaceContext = useWeb3React() const interfaceNetworkContext = useWeb3React( process.env.REACT_APP_IS_WIDGET ? undefined : NetworkContextName diff --git a/src/lib/.eslintrc.json b/src/lib/.eslintrc.json deleted file mode 100644 index 0f76db7a45..0000000000 --- a/src/lib/.eslintrc.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "extends": ["../../.eslintrc.json"], - "plugins": ["better-styled-components"], - "rules": { - "better-styled-components/sort-declarations-alphabetically": "error", - "no-restricted-imports": [ - "error", - { - "paths": [ - { - "name": "react-feather", - "message": "Please import from lib/icons to ensure performant usage." - }, - { - "name": "@uniswap/smart-order-router", - "message": "Forbidden import; smart-order-router is lazy-loaded." - } - ], - "patterns": [ - { - "group": ["styled-components"], - "message": "Please import styled from lib/theme to get the correct typings." - } - ] - } - ] - } -} diff --git a/src/lib/assets/fonts.scss b/src/lib/assets/fonts.scss deleted file mode 100644 index 6019bda692..0000000000 --- a/src/lib/assets/fonts.scss +++ /dev/null @@ -1,22 +0,0 @@ -// Use Inter mixin to set font-display: block. -@use "@fontsource/inter/scss/mixins" as Inter; -@include Inter.fontFace( - $fontName: 'Inter', - $weight: 400, - $display: block, -); -@include Inter.fontFace( - $fontName: 'Inter', - $weight: 500, - $display: block, -); -@include Inter.fontFace( - $fontName: 'Inter', - $weight: 600, - $display: block, -); -@include Inter.fontFaceVariable( - $display: block, -); - -@import "~@fontsource/ibm-plex-mono/400.css"; \ No newline at end of file diff --git a/src/lib/assets/missing-token-image.png b/src/lib/assets/missing-token-image.png deleted file mode 100644 index 8447733af9..0000000000 Binary files a/src/lib/assets/missing-token-image.png and /dev/null differ diff --git a/src/lib/assets/svg/auto_router.svg b/src/lib/assets/svg/auto_router.svg deleted file mode 100644 index 2aa1268848..0000000000 --- a/src/lib/assets/svg/auto_router.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/lib/assets/svg/check.svg b/src/lib/assets/svg/check.svg deleted file mode 100644 index 64735211ef..0000000000 --- a/src/lib/assets/svg/check.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/lib/assets/svg/expando.svg b/src/lib/assets/svg/expando.svg deleted file mode 100644 index aef744a93b..0000000000 --- a/src/lib/assets/svg/expando.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/lib/assets/svg/inline_spinner.svg b/src/lib/assets/svg/inline_spinner.svg deleted file mode 100644 index 441b0dc948..0000000000 --- a/src/lib/assets/svg/inline_spinner.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/lib/assets/svg/logo.svg b/src/lib/assets/svg/logo.svg deleted file mode 100644 index 3bd07e1b17..0000000000 --- a/src/lib/assets/svg/logo.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/lib/assets/svg/spinner.svg b/src/lib/assets/svg/spinner.svg deleted file mode 100644 index 7bcc7cf548..0000000000 --- a/src/lib/assets/svg/spinner.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/lib/assets/svg/wallet.svg b/src/lib/assets/svg/wallet.svg deleted file mode 100644 index d462eb8750..0000000000 --- a/src/lib/assets/svg/wallet.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/lib/components/ActionButton.tsx b/src/lib/components/ActionButton.tsx deleted file mode 100644 index dbe6deab07..0000000000 --- a/src/lib/components/ActionButton.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { AlertTriangle, Icon, LargeIcon } from 'lib/icons' -import styled, { Color, css, keyframes, ThemedText } from 'lib/theme' -import { ReactNode, useMemo } from 'react' - -import Button from './Button' -import Row from './Row' - -const StyledButton = styled(Button)` - border-radius: ${({ theme }) => theme.borderRadius * 0.75}em; - flex-grow: 1; - transition: background-color 0.25s ease-out, border-radius 0.25s ease-out, flex-grow 0.25s ease-out; - - :disabled { - margin: -1px; - } -` - -const ActionRow = styled(Row)`` - -const grow = keyframes` - from { - opacity: 0; - width: 0; - } - to { - opacity: 1; - width: max-content; - } -` - -const actionCss = css` - border: 1px solid ${({ theme }) => theme.outline}; - padding: calc(0.25em - 1px); - padding-left: calc(0.75em - 1px); - - ${ActionRow} { - animation: ${grow} 0.25s ease-in; - flex-grow: 1; - justify-content: flex-start; - white-space: nowrap; - } - - ${StyledButton} { - border-radius: ${({ theme }) => theme.borderRadius}em; - flex-grow: 0; - padding: 1em; - } -` - -export const Overlay = styled(Row)<{ hasAction: boolean }>` - border-radius: ${({ theme }) => theme.borderRadius}em; - flex-direction: row-reverse; - min-height: 3.5em; - transition: padding 0.25s ease-out; - - ${({ hasAction }) => hasAction && actionCss} -` - -export interface Action { - message: ReactNode - icon?: Icon - onClick?: () => void - children?: ReactNode -} - -export interface BaseProps { - color?: Color - action?: Action -} - -export type ActionButtonProps = BaseProps & Omit, keyof BaseProps> - -export default function ActionButton({ color = 'accent', disabled, action, onClick, children }: ActionButtonProps) { - const textColor = useMemo(() => (color === 'accent' && !disabled ? 'onAccent' : 'currentColor'), [color, disabled]) - return ( - - {(action ? action.onClick : true) && ( - - - {action?.children || children} - - - )} - {action && ( - - - {action?.message} - - )} - - ) -} diff --git a/src/lib/components/BrandedFooter.tsx b/src/lib/components/BrandedFooter.tsx deleted file mode 100644 index c3d77280cf..0000000000 --- a/src/lib/components/BrandedFooter.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Trans } from '@lingui/macro' -import Row from 'lib/components/Row' -import { Logo } from 'lib/icons' -import styled, { brand, ThemedText } from 'lib/theme' -import { memo } from 'react' - -import ExternalLink from './ExternalLink' - -const UniswapA = styled(ExternalLink)` - color: ${({ theme }) => theme.secondary}; - cursor: pointer; - text-decoration: none; - - ${Logo} { - fill: ${({ theme }) => theme.secondary}; - height: 1em; - transition: transform 0.25s ease, fill 0.25s ease; - width: 1em; - will-change: transform; - } - - :hover ${Logo} { - fill: ${brand}; - transform: rotate(-5deg); - } -` - -export default memo(function BrandedFooter() { - return ( - - - - - - Powered by the Uniswap protocol - - - - - ) -}) diff --git a/src/lib/components/Button.tsx b/src/lib/components/Button.tsx deleted file mode 100644 index fe7288ef75..0000000000 --- a/src/lib/components/Button.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Icon } from 'lib/icons' -import styled, { Color, css } from 'lib/theme' -import { ComponentProps, forwardRef } from 'react' - -export const BaseButton = styled.button` - background-color: transparent; - border: none; - border-radius: 0.5em; - color: currentColor; - cursor: pointer; - font-size: inherit; - font-weight: inherit; - height: inherit; - line-height: inherit; - margin: 0; - padding: 0; - - :enabled { - transition: filter 0.125s linear; - } - - :disabled { - cursor: initial; - filter: saturate(0) opacity(0.4); - } -` -const transitionCss = css` - transition: background-color 0.125s linear, border-color 0.125s linear, filter 0.125s linear; -` - -export default styled(BaseButton)<{ color?: Color; transition?: boolean }>` - border: 1px solid transparent; - color: ${({ color = 'interactive', theme }) => color === 'interactive' && theme.onInteractive}; - - :enabled { - background-color: ${({ color = 'interactive', theme }) => theme[color]}; - ${({ transition = true }) => transition && transitionCss}; - } - - :enabled:hover { - background-color: ${({ color = 'interactive', theme }) => theme.onHover(theme[color])}; - } - - :disabled { - border-color: ${({ theme }) => theme.outline}; - color: ${({ theme }) => theme.secondary}; - } -` - -const transparentButton = (defaultColor: Color) => styled(BaseButton)<{ color?: Color }>` - color: ${({ color = defaultColor, theme }) => theme[color]}; - - :enabled:hover { - color: ${({ color = defaultColor, theme }) => theme.onHover(theme[color])}; - } -` - -export const TextButton = transparentButton('accent') - -const SecondaryButton = transparentButton('secondary') - -interface IconButtonProps { - icon: Icon - iconProps?: ComponentProps -} - -export const IconButton = forwardRef>( - function IconButton({ icon: Icon, iconProps, ...props }: IconButtonProps & ComponentProps, ref) { - return ( - - - - ) - } -) diff --git a/src/lib/components/Column.tsx b/src/lib/components/Column.tsx deleted file mode 100644 index c91d9eb727..0000000000 --- a/src/lib/components/Column.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import styled, { Color, css, Theme } from 'lib/theme' - -const Column = styled.div<{ - align?: string - color?: Color - justify?: string - gap?: number - padded?: true - flex?: true - grow?: true - theme: Theme - css?: ReturnType -}>` - align-items: ${({ align }) => align ?? 'center'}; - color: ${({ color, theme }) => color && theme[color]}; - display: ${({ flex }) => (flex ? 'flex' : 'grid')}; - flex-direction: column; - flex-grow: ${({ grow }) => grow && 1}; - gap: ${({ gap }) => gap && `${gap}em`}; - grid-auto-flow: row; - grid-template-columns: 1fr; - justify-content: ${({ justify }) => justify ?? 'space-between'}; - padding: ${({ padded }) => padded && '0.75em'}; - - ${({ css }) => css} -` - -export default Column diff --git a/src/lib/components/Dialog.tsx b/src/lib/components/Dialog.tsx deleted file mode 100644 index b700e393c4..0000000000 --- a/src/lib/components/Dialog.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import 'wicg-inert' - -import { X } from 'lib/icons' -import styled, { Color, Layer, ThemeProvider } from 'lib/theme' -import { delayUnmountForAnimation } from 'lib/utils/animations' -import { createContext, ReactElement, ReactNode, useContext, useEffect, useRef, useState } from 'react' -import { createPortal } from 'react-dom' - -import { IconButton } from './Button' -import Column from './Column' -import { default as BaseHeader } from './Header' -import Rule from './Rule' - -// Include inert from wicg-inert -declare global { - interface HTMLElement { - inert?: boolean - } -} - -const Context = createContext({ - element: null as HTMLElement | null, - active: false, - setActive: (active: boolean) => undefined as void, -}) - -interface ProviderProps { - value: HTMLElement | null - children: ReactNode -} - -export function Provider({ value, children }: ProviderProps) { - // If a Dialog is active, mark the main content inert - const ref = useRef(null) - const [active, setActive] = useState(false) - const context = { element: value, active, setActive } - useEffect(() => { - if (ref.current) { - ref.current.inert = active - } - }, [active]) - return ( -
- {children} -
- ) -} - -const OnCloseContext = createContext<() => void>(() => void 0) - -interface HeaderProps { - title?: ReactElement - ruled?: boolean - children?: ReactNode -} - -export function Header({ title, children, ruled }: HeaderProps) { - return ( - <> - - - {children} - - - {ruled && } - - - ) -} - -export const Modal = styled.div<{ color: Color }>` - background-color: ${({ color, theme }) => theme[color]}; - border-radius: ${({ theme }) => theme.borderRadius * 0.75}em; - display: flex; - flex-direction: column; - height: 100%; - left: 0; - overflow: hidden; - position: absolute; - top: 0; - width: 100%; - z-index: ${Layer.DIALOG}; -` - -interface DialogProps { - color: Color - children: ReactNode - onClose?: () => void -} - -export default function Dialog({ color, children, onClose = () => void 0 }: DialogProps) { - const context = useContext(Context) - useEffect(() => { - context.setActive(true) - return () => context.setActive(false) - }, [context]) - - const modal = useRef(null) - useEffect(() => delayUnmountForAnimation(modal), []) - - useEffect(() => { - const close = (e: KeyboardEvent) => e.key === 'Escape' && onClose?.() - document.addEventListener('keydown', close, true) - return () => document.removeEventListener('keydown', close, true) - }, [onClose]) - return ( - context.element && - createPortal( - - - - {children} - - - , - context.element - ) - ) -} diff --git a/src/lib/components/Error/ErrorBoundary.tsx b/src/lib/components/Error/ErrorBoundary.tsx deleted file mode 100644 index 01fee12f0b..0000000000 --- a/src/lib/components/Error/ErrorBoundary.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Trans } from '@lingui/macro' -import React, { ErrorInfo } from 'react' - -import Dialog from '../Dialog' -import ErrorDialog from './ErrorDialog' - -export type ErrorHandler = (error: Error, info: ErrorInfo) => void - -interface ErrorBoundaryProps { - onError?: ErrorHandler -} - -type ErrorBoundaryState = { - error: Error | null -} - -export default class ErrorBoundary extends React.Component { - constructor(props: ErrorBoundaryProps) { - super(props) - this.state = { error: null } - } - - static getDerivedStateFromError(error: Error) { - return { error } - } - - componentDidCatch(error: Error, errorInfo: ErrorInfo) { - this.props.onError?.(error, errorInfo) - } - - render() { - if (this.state.error) { - return ( - - Something went wrong.} - action={Reload the page} - onClick={() => window.location.reload()} - /> - - ) - } - return this.props.children - } -} diff --git a/src/lib/components/Error/ErrorDialog.tsx b/src/lib/components/Error/ErrorDialog.tsx deleted file mode 100644 index 7844caba9c..0000000000 --- a/src/lib/components/Error/ErrorDialog.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Trans } from '@lingui/macro' -import ActionButton from 'lib/components/ActionButton' -import Column from 'lib/components/Column' -import Expando from 'lib/components/Expando' -import { AlertTriangle, Icon, LargeIcon } from 'lib/icons' -import styled, { Color, ThemedText } from 'lib/theme' -import { ReactNode, useCallback, useState } from 'react' - -const HeaderIcon = styled(LargeIcon)` - flex-grow: 1; - transition: height 0.25s, width 0.25s; - - svg { - transition: height 0.25s, width 0.25s; - } -` - -interface StatusHeaderProps { - icon: Icon - iconColor?: Color - iconSize?: number - children: ReactNode -} - -export function StatusHeader({ icon: Icon, iconColor, iconSize = 4, children }: StatusHeaderProps) { - return ( - <> - - - - {children} - - - - ) -} - -const ErrorHeader = styled(Column)<{ open: boolean }>` - transition: gap 0.25s; - - div:last-child { - max-height: ${({ open }) => (open ? 0 : 60 / 14)}em; // 3 * line-height - overflow-y: hidden; - transition: max-height 0.25s; - } -` - -interface ErrorDialogProps { - header?: ReactNode - error: Error - action: ReactNode - onClick: () => void -} - -export default function ErrorDialog({ header, error, action, onClick }: ErrorDialogProps) { - const [open, setOpen] = useState(false) - const onExpand = useCallback(() => setOpen((open) => !open), []) - - return ( - - - - - Something went wrong. - - {header} - - - - Error details} open={open} onExpand={onExpand} height={7.5}> - - {error.name} - {error.message ? `: ${error.message}` : ''} - - - {action} - - - ) -} diff --git a/src/lib/components/EtherscanLink.tsx b/src/lib/components/EtherscanLink.tsx deleted file mode 100644 index 49b90f2f47..0000000000 --- a/src/lib/components/EtherscanLink.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { SupportedChainId } from 'constants/chains' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { Link } from 'lib/icons' -import styled, { Color } from 'lib/theme' -import { ReactNode, useMemo } from 'react' -import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' - -import ExternalLink from './ExternalLink' -import Row from './Row' - -const StyledExternalLink = styled(ExternalLink)<{ color: Color }>` - color: ${({ theme, color }) => theme[color]}; - text-decoration: none; -` - -interface EtherscanLinkProps { - type: ExplorerDataType - data?: string - color?: Color - children: ReactNode -} - -export default function EtherscanLink({ data, type, color = 'currentColor', children }: EtherscanLinkProps) { - const { chainId } = useActiveWeb3React() - const url = useMemo( - () => data && getExplorerLink(chainId || SupportedChainId.MAINNET, data, type), - [chainId, data, type] - ) - - return ( - - - {children} - {url && } - - - ) -} diff --git a/src/lib/components/Expando.tsx b/src/lib/components/Expando.tsx deleted file mode 100644 index bb3ddda1d8..0000000000 --- a/src/lib/components/Expando.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { IconButton } from 'lib/components/Button' -import Column from 'lib/components/Column' -import Row from 'lib/components/Row' -import Rule from 'lib/components/Rule' -import useScrollbar from 'lib/hooks/useScrollbar' -import { Expando as ExpandoIcon } from 'lib/icons' -import styled from 'lib/theme' -import { PropsWithChildren, ReactNode, useState } from 'react' - -const HeaderColumn = styled(Column)` - transition: gap 0.25s; -` - -const ExpandoColumn = styled(Column)<{ height: number; open: boolean }>` - height: ${({ height, open }) => (open ? height : 0)}em; - overflow: hidden; - position: relative; - transition: height 0.25s, padding 0.25s; - - :after { - background: linear-gradient(transparent, ${({ theme }) => theme.dialog}); - bottom: 0; - content: ''; - height: 0.75em; - pointer-events: none; - position: absolute; - width: calc(100% - 1em); - } -` - -const InnerColumn = styled(Column)<{ height: number }>` - height: ${({ height }) => height}em; - padding: 0.5em 0; -` - -interface ExpandoProps { - title: ReactNode - open: boolean - onExpand: () => void - // The absolute height of the expanded container, in em. - height: number -} - -/** A scrollable Expando with an absolute height. */ -export default function Expando({ title, open, onExpand, height, children }: PropsWithChildren) { - const [scrollingEl, setScrollingEl] = useState(null) - const scrollbar = useScrollbar(scrollingEl) - return ( - - - - - {title} - - - - - - - {children} - - - - ) - return null -} diff --git a/src/lib/components/ExternalLink.tsx b/src/lib/components/ExternalLink.tsx deleted file mode 100644 index 41c217f692..0000000000 --- a/src/lib/components/ExternalLink.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { HTMLProps } from 'react' - -/** - * Outbound link - */ -export default function ExternalLink({ - target = '_blank', - href, - rel = 'noopener noreferrer', - ...rest -}: Omit, 'as' | 'ref' | 'onClick'> & { href?: string }) { - return ( - - {rest.children} - - ) -} diff --git a/src/lib/components/Header.tsx b/src/lib/components/Header.tsx deleted file mode 100644 index 9b267a5746..0000000000 --- a/src/lib/components/Header.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { largeIconCss } from 'lib/icons' -import styled, { ThemedText } from 'lib/theme' -import { ReactElement, ReactNode } from 'react' - -import Row from './Row' - -const HeaderRow = styled(Row)` - height: 1.75em; - margin: 0 0.75em 0.75em; - padding-top: 0.5em; - ${largeIconCss} -` - -export interface HeaderProps { - title?: ReactElement - children: ReactNode -} - -export default function Header({ title, children }: HeaderProps) { - return ( - - {title && {title}} - {children} - - ) -} diff --git a/src/lib/components/Input.tsx b/src/lib/components/Input.tsx deleted file mode 100644 index 68c3735147..0000000000 --- a/src/lib/components/Input.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import { loadingOpacity } from 'lib/css/loading' -import styled, { css } from 'lib/theme' -import { transparentize } from 'polished' -import { ChangeEvent, forwardRef, HTMLProps, useCallback } from 'react' - -const Input = styled.input` - -webkit-appearance: textfield; - background-color: transparent; - border: none; - color: currentColor; - font-family: inherit; - font-size: inherit; - font-weight: inherit; - line-height: inherit; - margin: 0; - outline: none; - overflow: hidden; - padding: 0; - text-align: left; - text-overflow: ellipsis; - width: 100%; - - ::-webkit-search-decoration { - -webkit-appearance: none; - } - - [type='number'] { - -moz-appearance: textfield; - } - - ::-webkit-outer-spin-button, - ::-webkit-inner-spin-button { - -webkit-appearance: none; - } - - ::placeholder { - color: ${({ theme }) => theme.secondary}; - } - - :enabled { - transition: color 0.125s linear; - } - - :disabled { - // Overrides WebKit's override of input:disabled color. - -webkit-text-fill-color: ${({ theme }) => transparentize(1 - loadingOpacity, theme.primary)}; - color: ${({ theme }) => transparentize(1 - loadingOpacity, theme.primary)}; - } -` - -export default Input - -interface StringInputProps extends Omit, 'onChange' | 'as' | 'value'> { - value: string - onChange: (input: string) => void -} - -export const StringInput = forwardRef(function StringInput( - { value, onChange, ...props }: StringInputProps, - ref -) { - return ( - onChange(e.target.value)} - // universal input options - inputMode="text" - autoComplete="off" - autoCorrect="off" - // text-specific options - type="text" - placeholder={props.placeholder || '-'} - minLength={1} - spellCheck="false" - ref={ref as any} - {...props} - /> - ) -}) - -interface NumericInputProps extends Omit, 'onChange' | 'as' | 'value'> { - value: string - onChange: (input: string) => void -} - -interface EnforcedNumericInputProps extends NumericInputProps { - // Validates nextUserInput; returns stringified value, or null if invalid - enforcer: (nextUserInput: string) => string | null -} - -const NumericInput = forwardRef(function NumericInput( - { value, onChange, enforcer, pattern, ...props }: EnforcedNumericInputProps, - ref -) { - const validateChange = useCallback( - (event: ChangeEvent) => { - const nextInput = enforcer(event.target.value.replace(/,/g, '.'))?.replace(/^0+$/, '0') - if (nextInput !== undefined) { - onChange(nextInput) - } - }, - [enforcer, onChange] - ) - - return ( - - ) -}) - -const integerRegexp = /^\d*$/ -const integerEnforcer = (nextUserInput: string) => { - if (nextUserInput === '' || integerRegexp.test(nextUserInput)) { - const nextInput = parseInt(nextUserInput) - return isNaN(nextInput) ? '' : nextInput.toString() - } - return null -} -export const IntegerInput = forwardRef(function IntegerInput(props: NumericInputProps, ref) { - return -}) - -const decimalRegexp = /^\d*(?:[.])?\d*$/ -const decimalEnforcer = (nextUserInput: string) => { - if (nextUserInput === '') { - return '' - } else if (nextUserInput === '.') { - return '0.' - } else if (decimalRegexp.test(nextUserInput)) { - return nextUserInput - } - return null -} -export const DecimalInput = forwardRef(function DecimalInput(props: NumericInputProps, ref) { - return -}) - -export const inputCss = css` - background-color: ${({ theme }) => theme.container}; - border: 1px solid ${({ theme }) => theme.container}; - border-radius: ${({ theme }) => theme.borderRadius}em; - cursor: text; - padding: calc(0.5em - 1px); - - :hover:not(:focus-within) { - background-color: ${({ theme }) => theme.onHover(theme.container)}; - border-color: ${({ theme }) => theme.onHover(theme.container)}; - } - - :focus-within { - border-color: ${({ theme }) => theme.active}; - } -` diff --git a/src/lib/components/Popover.tsx b/src/lib/components/Popover.tsx deleted file mode 100644 index 754172f651..0000000000 --- a/src/lib/components/Popover.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { Options, Placement } from '@popperjs/core' -import styled, { Layer } from 'lib/theme' -import maxSize from 'popper-max-size-modifier' -import React, { createContext, useContext, useMemo, useRef, useState } from 'react' -import { createPortal } from 'react-dom' -import { usePopper } from 'react-popper' - -const BoundaryContext = createContext(null) - -export const BoundaryProvider = BoundaryContext.Provider - -const PopoverContainer = styled.div<{ show: boolean }>` - background-color: ${({ theme }) => theme.dialog}; - border: 1px solid ${({ theme }) => theme.outline}; - border-radius: 0.5em; - opacity: ${(props) => (props.show ? 1 : 0)}; - padding: 10px 12px; - transition: visibility 0.25s linear, opacity 0.25s linear; - visibility: ${(props) => (props.show ? 'visible' : 'hidden')}; - z-index: ${Layer.TOOLTIP}; -` - -const Reference = styled.div` - align-self: flex-start; - display: inline-block; - height: 1em; -` - -const Arrow = styled.div` - height: 8px; - width: 8px; - z-index: ${Layer.TOOLTIP}; - - ::before { - background: ${({ theme }) => theme.dialog}; - border: 1px solid ${({ theme }) => theme.outline}; - content: ''; - height: 8px; - position: absolute; - transform: rotate(45deg); - width: 8px; - } - - &.arrow-top { - bottom: -4px; - ::before { - border-radius: 1px; - border-left: none; - border-top: none; - } - } - - &.arrow-bottom { - top: -5px; // includes -1px from border - ::before { - border-bottom: none; - border-right: none; - border-radius: 1px; - } - } - - &.arrow-left { - right: -4px; - ::before { - border-bottom: none; - border-left: none; - border-radius: 1px; - } - } - - &.arrow-right { - left: -5px; // includes -1px from border - ::before { - border-radius: 1px; - border-right: none; - border-top: none; - } - } -` - -export interface PopoverProps { - content: React.ReactNode - show: boolean - children: React.ReactNode - placement: Placement - offset?: number - contained?: true -} - -export default function Popover({ content, show, children, placement, offset, contained }: PopoverProps) { - const boundary = useContext(BoundaryContext) - const reference = useRef(null) - - // Use callback refs to be notified when instantiated - const [popover, setPopover] = useState(null) - const [arrow, setArrow] = useState(null) - - const options = useMemo((): Options => { - const modifiers: Options['modifiers'] = [ - { name: 'offset', options: { offset: [4, offset || 4] } }, - { name: 'arrow', options: { element: arrow, padding: 4 } }, - ] - if (contained) { - modifiers.push( - { name: 'preventOverflow', options: { boundary, padding: 8 } }, - { name: 'flip', options: { boundary, padding: 8 } }, - { ...maxSize, options: { boundary, padding: 8 } }, - { - name: 'applyMaxSize', - enabled: true, - phase: 'beforeWrite', - requires: ['maxSize'], - fn({ state }) { - const { width } = state.modifiersData.maxSize - state.styles.popper = { - ...state.styles.popper, - maxWidth: `${width}px`, - } - }, - } - ) - } - return { - placement, - strategy: 'absolute', - modifiers, - } - }, [offset, arrow, contained, placement, boundary]) - - const { styles, attributes } = usePopper(reference.current, popover, options) - - return ( - <> - {children} - {boundary && - createPortal( - - {content} - - , - boundary - )} - - ) -} diff --git a/src/lib/components/RecentTransactionsDialog.tsx b/src/lib/components/RecentTransactionsDialog.tsx deleted file mode 100644 index 3f1c79ceb9..0000000000 --- a/src/lib/components/RecentTransactionsDialog.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Trans } from '@lingui/macro' -import { Currency } from '@uniswap/sdk-core' -import { AlertTriangle, ArrowRight, CheckCircle, Spinner, Trash2 } from 'lib/icons' -import styled, { ThemedText } from 'lib/theme' -import { useMemo, useState } from 'react' - -import Button from './Button' -import Column from './Column' -import { Header } from './Dialog' -import Row from './Row' -import TokenImg from './TokenImg' - -interface ITokenAmount { - value: number - token: Currency -} - -export enum TransactionStatus { - SUCCESS = 0, - ERROR, - PENDING, -} - -interface ITransaction { - input: ITokenAmount - output: ITokenAmount - status: TransactionStatus -} - -const TransactionRow = styled(Row)` - padding: 0.5em 1em; - - :first-of-type { - padding-top: 1em; - } -` - -function TokenAmount({ value: { value, token } }: { value: ITokenAmount }) { - return ( - - - - {value.toLocaleString('en')} {token.symbol} - - - ) -} - -function Transaction({ tx }: { tx: ITransaction }) { - const statusIcon = useMemo(() => { - switch (tx.status) { - case TransactionStatus.SUCCESS: - return - case TransactionStatus.ERROR: - return - case TransactionStatus.PENDING: - return - } - }, [tx.status]) - return ( - - - - - - - - - - {statusIcon} - - - ) -} - -export default function RecentTransactionsDialog() { - const [txs, setTxs] = useState([]) - - return ( - <> -
Recent transactions} ruled> - -
- - {txs.map((tx, key) => ( - - ))} - - - ) -} diff --git a/src/lib/components/Row.tsx b/src/lib/components/Row.tsx deleted file mode 100644 index 43b28d7f75..0000000000 --- a/src/lib/components/Row.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import styled, { Color, Theme } from 'lib/theme' -import { Children, ReactNode } from 'react' - -const Row = styled.div<{ - color?: Color - align?: string - justify?: string - pad?: number - gap?: number - flex?: true - grow?: true | 'first' | 'last' - children?: ReactNode - theme: Theme -}>` - align-items: ${({ align }) => align ?? 'center'}; - color: ${({ color, theme }) => color && theme[color]}; - display: ${({ flex }) => (flex ? 'flex' : 'grid')}; - flex-flow: wrap; - flex-grow: ${({ grow }) => grow && 1}; - gap: ${({ gap }) => gap && `${gap}em`}; - grid-auto-flow: column; - grid-template-columns: ${({ grow, children }) => { - if (grow === 'first') return '1fr' - if (grow === 'last') return `repeat(${Children.count(children) - 1}, auto) 1fr` - if (grow) return `repeat(${Children.count(children)}, 1fr)` - return undefined - }}; - justify-content: ${({ justify }) => justify ?? 'space-between'}; - padding: ${({ pad }) => pad && `0 ${pad}em`}; -` - -export default Row diff --git a/src/lib/components/Rule.tsx b/src/lib/components/Rule.tsx deleted file mode 100644 index c16cc37be1..0000000000 --- a/src/lib/components/Rule.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import styled from 'lib/theme' - -const Rule = styled.hr<{ padded?: true; scrollingEdge?: 'top' | 'bottom' }>` - border: none; - border-bottom: 1px solid ${({ theme }) => theme.outline}; - margin: 0 ${({ padded }) => (padded ? '0.75em' : 0)}; - margin-bottom: ${({ scrollingEdge }) => (scrollingEdge === 'bottom' ? -1 : 0)}px; - margin-top: ${({ scrollingEdge }) => (scrollingEdge !== 'bottom' ? -1 : 0)}px; - - // Integrators will commonly modify hr width - this overrides any modifications within the widget. - max-width: auto; - width: auto; -` - -export default Rule diff --git a/src/lib/components/Swap/Input.tsx b/src/lib/components/Swap/Input.tsx deleted file mode 100644 index 46b0e155e9..0000000000 --- a/src/lib/components/Swap/Input.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import { useLingui } from '@lingui/react' -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { loadingTransitionCss } from 'lib/css/loading' -import { - useIsSwapFieldIndependent, - useSwapAmount, - useSwapCurrency, - useSwapCurrencyAmount, - useSwapInfo, -} from 'lib/hooks/swap' -import { usePrefetchCurrencyColor } from 'lib/hooks/useCurrencyColor' -import { Field } from 'lib/state/swap' -import styled, { ThemedText } from 'lib/theme' -import { useMemo } from 'react' -import { TradeState } from 'state/routing/types' -import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' -import { maxAmountSpend } from 'utils/maxAmountSpend' - -import Column from '../Column' -import Row from '../Row' -import TokenImg from '../TokenImg' -import TokenInput from './TokenInput' - -export const USDC = styled(Row)` - ${loadingTransitionCss}; -` - -export const Balance = styled(ThemedText.Body2)<{ focused: boolean }>` - opacity: ${({ focused }) => (focused ? 1 : 0)}; - transition: opacity 0.25s ${({ focused }) => (focused ? 'ease-in' : 'ease-out')}; -` - -const InputColumn = styled(Column)<{ approved?: boolean }>` - margin: 0.75em; - position: relative; - - ${TokenImg} { - filter: ${({ approved }) => (approved ? undefined : 'saturate(0) opacity(0.4)')}; - transition: filter 0.25s; - } -` - -export interface InputProps { - disabled: boolean - focused: boolean -} - -interface UseFormattedFieldAmountArguments { - disabled: boolean - currencyAmount?: CurrencyAmount - fieldAmount?: string -} - -export function useFormattedFieldAmount({ disabled, currencyAmount, fieldAmount }: UseFormattedFieldAmountArguments) { - return useMemo(() => { - if (disabled) { - return '' - } - if (fieldAmount !== undefined) { - return fieldAmount - } - if (currencyAmount) { - return currencyAmount.toSignificant(6) - } - return '' - }, [disabled, currencyAmount, fieldAmount]) -} - -export default function Input({ disabled, focused }: InputProps) { - const { i18n } = useLingui() - const { - [Field.INPUT]: { balance, amount: tradeCurrencyAmount, usdc }, - trade: { state: tradeState }, - } = useSwapInfo() - - const [inputAmount, updateInputAmount] = useSwapAmount(Field.INPUT) - const [inputCurrency, updateInputCurrency] = useSwapCurrency(Field.INPUT) - const inputCurrencyAmount = useSwapCurrencyAmount(Field.INPUT) - - // extract eagerly in case of reversal - usePrefetchCurrencyColor(inputCurrency) - - const isRouteLoading = disabled || tradeState === TradeState.SYNCING || tradeState === TradeState.LOADING - const isDependentField = !useIsSwapFieldIndependent(Field.INPUT) - const isLoading = isRouteLoading && isDependentField - - //TODO(ianlapham): mimic logic from app swap page - const mockApproved = true - - // account for gas needed if using max on native token - const max = useMemo(() => { - const maxAmount = maxAmountSpend(balance) - return maxAmount?.greaterThan(0) ? maxAmount.toExact() : undefined - }, [balance]) - - const balanceColor = useMemo(() => { - const insufficientBalance = - balance && - (inputCurrencyAmount ? inputCurrencyAmount.greaterThan(balance) : tradeCurrencyAmount?.greaterThan(balance)) - return insufficientBalance ? 'error' : undefined - }, [balance, inputCurrencyAmount, tradeCurrencyAmount]) - - const amount = useFormattedFieldAmount({ - disabled, - currencyAmount: tradeCurrencyAmount, - fieldAmount: inputAmount, - }) - - return ( - - - - - {usdc ? `$${formatCurrencyAmount(usdc, 6, 'en', 2)}` : '-'} - {balance && ( - - Balance: {formatCurrencyAmount(balance, 4, i18n.locale)} - - )} - - - - - - ) -} diff --git a/src/lib/components/Swap/Output.tsx b/src/lib/components/Swap/Output.tsx deleted file mode 100644 index b9f9eecf1c..0000000000 --- a/src/lib/components/Swap/Output.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useLingui } from '@lingui/react' -import { atom } from 'jotai' -import { useAtomValue } from 'jotai/utils' -import BrandedFooter from 'lib/components/BrandedFooter' -import { useIsSwapFieldIndependent, useSwapAmount, useSwapCurrency, useSwapInfo } from 'lib/hooks/swap' -import useCurrencyColor from 'lib/hooks/useCurrencyColor' -import { Field } from 'lib/state/swap' -import styled, { DynamicThemeProvider, ThemedText } from 'lib/theme' -import { PropsWithChildren } from 'react' -import { TradeState } from 'state/routing/types' -import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' - -import Column from '../Column' -import Row from '../Row' -import { Balance, InputProps, USDC, useFormattedFieldAmount } from './Input' -import TokenInput from './TokenInput' - -export const colorAtom = atom(undefined) - -const OutputColumn = styled(Column)<{ hasColor: boolean | null }>` - background-color: ${({ theme }) => theme.module}; - border-radius: ${({ theme }) => theme.borderRadius - 0.25}em; - padding: 0.75em; - padding-bottom: 0.5em; - position: relative; - - // Set transitions to reduce color flashes when switching color/token. - // When color loads, transition the background so that it transitions from the empty or last state, but not _to_ the empty state. - transition: ${({ hasColor }) => (hasColor ? 'background-color 0.25s ease-out' : undefined)}; - > { - // When color is loading, delay the color/stroke so that it seems to transition from the last state. - transition: ${({ hasColor }) => (hasColor === null ? 'color 0.25s ease-in, stroke 0.25s ease-in' : undefined)}; - } -` - -export default function Output({ disabled, focused, children }: PropsWithChildren) { - const { i18n } = useLingui() - - const { - [Field.OUTPUT]: { balance, amount: outputCurrencyAmount, usdc: outputUSDC }, - trade: { state: tradeState }, - impact, - } = useSwapInfo() - - const [swapOutputAmount, updateSwapOutputAmount] = useSwapAmount(Field.OUTPUT) - const [swapOutputCurrency, updateSwapOutputCurrency] = useSwapCurrency(Field.OUTPUT) - - const isRouteLoading = disabled || tradeState === TradeState.SYNCING || tradeState === TradeState.LOADING - const isDependentField = !useIsSwapFieldIndependent(Field.OUTPUT) - const isLoading = isRouteLoading && isDependentField - - const overrideColor = useAtomValue(colorAtom) - const dynamicColor = useCurrencyColor(swapOutputCurrency) - const color = overrideColor || dynamicColor - - // different state true/null/false allow smoother color transition - const hasColor = swapOutputCurrency ? Boolean(color) || null : false - - const amount = useFormattedFieldAmount({ - disabled, - currencyAmount: outputCurrencyAmount, - fieldAmount: swapOutputAmount, - }) - - return ( - - - - - For - - - - - - - {outputUSDC ? `$${formatCurrencyAmount(outputUSDC, 6, 'en', 2)}` : '-'}{' '} - {impact && ({impact.toString()})} - - {balance && ( - - Balance: {formatCurrencyAmount(balance, 4, i18n.locale)} - - )} - - - - {children} - - - - ) -} diff --git a/src/lib/components/Swap/Price.tsx b/src/lib/components/Swap/Price.tsx deleted file mode 100644 index 1651ba583b..0000000000 --- a/src/lib/components/Swap/Price.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { useLingui } from '@lingui/react' -import { Trade } from '@uniswap/router-sdk' -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import Row from 'lib/components/Row' -import { ThemedText } from 'lib/theme' -import formatLocaleNumber from 'lib/utils/formatLocaleNumber' -import { useCallback, useMemo, useState } from 'react' -import { formatCurrencyAmount, formatPrice } from 'utils/formatCurrencyAmount' - -import { TextButton } from '../Button' - -interface PriceProps { - trade: Trade - outputUSDC?: CurrencyAmount -} - -/** Displays the price of a trade. If outputUSDC is included, also displays the unit price. */ -export default function Price({ trade, outputUSDC }: PriceProps) { - const { i18n } = useLingui() - const { inputAmount, outputAmount, executionPrice } = trade - - const [base, setBase] = useState<'input' | 'output'>('input') - const onClick = useCallback(() => setBase((base) => (base === 'input' ? 'output' : 'input')), []) - - // Compute the usdc price from the output price, so that it aligns with the displayed price. - const { price, usdcPrice } = useMemo(() => { - switch (base) { - case 'input': - return { - price: executionPrice, - usdcPrice: outputUSDC?.multiply(inputAmount.decimalScale).divide(inputAmount), - } - case 'output': - return { - price: executionPrice.invert(), - usdcPrice: outputUSDC?.multiply(outputAmount.decimalScale).divide(outputAmount), - } - } - }, [base, executionPrice, inputAmount, outputAmount, outputUSDC]) - - return ( - - - - {formatLocaleNumber({ number: 1, sigFigs: 1, locale: i18n.locale })} {price.baseCurrency.symbol} ={' '} - {formatPrice(price, 6, i18n.locale)} {price.quoteCurrency.symbol} - {usdcPrice && ( - (${formatCurrencyAmount(usdcPrice, 6, 'en', 2)}) - )} - - - - ) -} diff --git a/src/lib/components/Swap/ReverseButton.tsx b/src/lib/components/Swap/ReverseButton.tsx deleted file mode 100644 index 717cfddfee..0000000000 --- a/src/lib/components/Swap/ReverseButton.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { useSwitchSwapCurrencies } from 'lib/hooks/swap' -import { ArrowDown as ArrowDownIcon, ArrowUp as ArrowUpIcon } from 'lib/icons' -import styled, { Layer } from 'lib/theme' -import { useCallback, useState } from 'react' - -import Button from '../Button' -import Row from '../Row' - -const ReverseRow = styled(Row)` - left: 50%; - position: absolute; - transform: translate(-50%, -50%); - z-index: ${Layer.OVERLAY}; -` - -const ArrowUp = styled(ArrowUpIcon)` - left: calc(50% - 0.37em); - position: absolute; - top: calc(50% - 0.82em); -` - -const ArrowDown = styled(ArrowDownIcon)` - bottom: calc(50% - 0.82em); - position: absolute; - right: calc(50% - 0.37em); -` - -const Overlay = styled.div` - background-color: ${({ theme }) => theme.container}; - border-radius: ${({ theme }) => theme.borderRadius}em; - padding: 0.25em; -` - -const StyledReverseButton = styled(Button)<{ turns: number }>` - border-radius: ${({ theme }) => theme.borderRadius * 0.75}em; - color: ${({ theme }) => theme.primary}; - height: 2.5em; - position: relative; - width: 2.5em; - - div { - transform: rotate(${({ turns }) => turns / 2}turn); - transition: transform 0.25s ease-in-out; - will-change: transform; - } -` - -export default function ReverseButton({ disabled }: { disabled?: boolean }) { - const [turns, setTurns] = useState(0) - const switchCurrencies = useSwitchSwapCurrencies() - const onClick = useCallback(() => { - switchCurrencies() - setTurns((turns) => ++turns) - }, [switchCurrencies]) - - return ( - - - -
- - -
-
-
-
- ) -} diff --git a/src/lib/components/Swap/RoutingDiagram/index.tsx b/src/lib/components/Swap/RoutingDiagram/index.tsx deleted file mode 100644 index c810b25641..0000000000 --- a/src/lib/components/Swap/RoutingDiagram/index.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { Plural, Trans } from '@lingui/macro' -import { Currency, TradeType } from '@uniswap/sdk-core' -import { FeeAmount } from '@uniswap/v3-sdk' -import { ReactComponent as DotLine } from 'assets/svg/dot_line.svg' -import Column from 'lib/components/Column' -import Row from 'lib/components/Row' -import Rule from 'lib/components/Rule' -import TokenImg from 'lib/components/TokenImg' -import { AutoRouter } from 'lib/icons' -import styled, { Layer, ThemedText } from 'lib/theme' -import { useMemo } from 'react' -import { InterfaceTrade } from 'state/routing/types' - -import { getTokenPath, RoutingDiagramEntry } from './utils' - -const StyledAutoRouterLabel = styled(ThemedText.ButtonSmall)` - @supports (-webkit-background-clip: text) and (-webkit-text-fill-color: transparent) { - background-image: linear-gradient(90deg, #2172e5 0%, #54e521 163.16%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - } -` - -function Header({ routes }: { routes: RoutingDiagramEntry[] }) { - return ( - - - - - - Auto Router - - - - - - - - ) -} - -const Dots = styled(DotLine)` - color: ${({ theme }) => theme.outline}; - position: absolute; - z-index: ${Layer.UNDERLAYER}; -` - -const RouteRow = styled(Row)` - flex-wrap: nowrap; -` - -const RouteNode = styled(Row)` - background-color: ${({ theme }) => theme.interactive}; - border-radius: ${({ theme }) => `${(theme.borderRadius ?? 1) * 0.5}em`}; - margin-left: 1.625em; - padding: 0.25em 0.375em; - width: max-content; -` - -const RouteBadge = styled.div` - background-color: ${({ theme }) => theme.module}; - border-radius: ${({ theme }) => `${(theme.borderRadius ?? 1) * 0.25}em`}; - padding: 0.125em; -` - -function RouteDetail({ route }: { route: RoutingDiagramEntry }) { - const protocol = route.protocol.toUpperCase() - return ( - - - {route.percent.toSignificant(2)}% - - {protocol} - - - - ) -} - -const RoutePool = styled(RouteNode)` - margin: 0 0.75em; -` - -function Pool({ - originCurrency, - targetCurrency, - feeAmount, -}: { - originCurrency: Currency - targetCurrency: Currency - feeAmount: FeeAmount -}) { - return ( - - - - - - {feeAmount / 10_000}% - - - - ) -} - -function Route({ route }: { route: RoutingDiagramEntry }) { - const [originCurrency] = route.path[0] - const [, targetCurrency] = route.path[route.path.length - 1] - - return ( - - - - - - - {route.path.map(([originCurrency, targetCurrency, feeAmount], index) => ( - - ))} - - - - - ) -} - -export default function RoutingDiagram({ trade }: { trade: InterfaceTrade }) { - const routes: RoutingDiagramEntry[] = useMemo(() => getTokenPath(trade), [trade]) - - return ( - -
- - {routes.map((route, index) => ( - - ))} - - ) -} diff --git a/src/lib/components/Swap/RoutingDiagram/utils.ts b/src/lib/components/Swap/RoutingDiagram/utils.ts deleted file mode 100644 index 34d675e868..0000000000 --- a/src/lib/components/Swap/RoutingDiagram/utils.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Protocol } from '@uniswap/router-sdk' -import { Currency, Percent, TradeType } from '@uniswap/sdk-core' -import { Pair } from '@uniswap/v2-sdk' -import { FeeAmount } from '@uniswap/v3-sdk' -import { InterfaceTrade } from 'state/routing/types' - -export interface RoutingDiagramEntry { - percent: Percent - path: [Currency, Currency, FeeAmount][] - protocol: Protocol -} - -const V2_DEFAULT_FEE_TIER = 3000 - -/** - * Loops through all routes on a trade and returns an array of diagram entries. - */ -export function getTokenPath(trade: InterfaceTrade): RoutingDiagramEntry[] { - return trade.swaps.map(({ route: { path: tokenPath, pools, protocol }, inputAmount, outputAmount }) => { - const portion = - trade.tradeType === TradeType.EXACT_INPUT - ? inputAmount.divide(trade.inputAmount) - : outputAmount.divide(trade.outputAmount) - const percent = new Percent(portion.numerator, portion.denominator) - const path: RoutingDiagramEntry['path'] = [] - for (let i = 0; i < pools.length; i++) { - const nextPool = pools[i] - const tokenIn = tokenPath[i] - const tokenOut = tokenPath[i + 1] - const entry: RoutingDiagramEntry['path'][0] = [ - tokenIn, - tokenOut, - nextPool instanceof Pair ? V2_DEFAULT_FEE_TIER : nextPool.fee, - ] - path.push(entry) - } - return { - percent, - path, - protocol, - } - }) -} diff --git a/src/lib/components/Swap/Settings.fixture.tsx b/src/lib/components/Swap/Settings.fixture.tsx deleted file mode 100644 index d24efc858d..0000000000 --- a/src/lib/components/Swap/Settings.fixture.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Modal } from '../Dialog' -import { SettingsDialog } from './Settings' - -export default ( - - - -) diff --git a/src/lib/components/Swap/Settings/MaxSlippageSelect.tsx b/src/lib/components/Swap/Settings/MaxSlippageSelect.tsx deleted file mode 100644 index de78aa6fcc..0000000000 --- a/src/lib/components/Swap/Settings/MaxSlippageSelect.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useAtom } from 'jotai' -import Popover from 'lib/components/Popover' -import { useTooltip } from 'lib/components/Tooltip' -import { getSlippageWarning, toPercent } from 'lib/hooks/useSlippage' -import { AlertTriangle, Check, Icon, LargeIcon, XOctagon } from 'lib/icons' -import { autoSlippageAtom, maxSlippageAtom } from 'lib/state/settings' -import styled, { ThemedText } from 'lib/theme' -import { forwardRef, memo, ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react' - -import { BaseButton, TextButton } from '../../Button' -import Column from '../../Column' -import { DecimalInput, inputCss } from '../../Input' -import Row from '../../Row' -import { Label, optionCss } from './components' - -const tooltip = ( - Your transaction will revert if the price changes unfavorably by more than this percentage. -) -const highSlippage = High slippage increases the risk of price movement -const invalidSlippage = Please enter a valid slippage % - -const placeholder = '0.10' - -const Button = styled(TextButton)<{ selected: boolean }>` - ${({ selected }) => optionCss(selected)} -` - -const Custom = styled(BaseButton)<{ selected: boolean }>` - ${({ selected }) => optionCss(selected)} - ${inputCss} - padding: calc(0.75em - 3px) 0.625em; -` - -interface OptionProps { - wrapper: typeof Button | typeof Custom - selected: boolean - onSelect: () => void - icon?: ReactNode - tabIndex?: number - children: ReactNode -} - -const Option = forwardRef(function Option( - { wrapper: Wrapper, children, selected, onSelect, icon, tabIndex }: OptionProps, - ref -) { - return ( - - - {children} - {icon ? icon : } - - - ) -}) - -const Warning = memo(function Warning({ state, showTooltip }: { state?: 'warning' | 'error'; showTooltip: boolean }) { - let icon: Icon | undefined - let content: ReactNode - let show = showTooltip - switch (state) { - case 'error': - icon = XOctagon - content = invalidSlippage - show = true - break - case 'warning': - icon = AlertTriangle - content = highSlippage - break - } - return ( - {content}} - show={show} - placement="top" - offset={16} - contained - > - - - ) -}) - -export default function MaxSlippageSelect() { - const [autoSlippage, setAutoSlippage] = useAtom(autoSlippageAtom) - const [maxSlippage, setMaxSlippage] = useAtom(maxSlippageAtom) - const maxSlippageInput = useMemo(() => maxSlippage?.toString() || '', [maxSlippage]) - - const option = useRef(null) - const showTooltip = useTooltip(option.current) - - const input = useRef(null) - const focus = useCallback(() => input.current?.focus(), [input]) - - const [warning, setWarning] = useState<'warning' | 'error' | undefined>(getSlippageWarning(toPercent(maxSlippage))) - useEffect(() => { - setWarning(getSlippageWarning(toPercent(maxSlippage))) - }, [maxSlippage]) - - const onInputSelect = useCallback(() => { - focus() - const percent = toPercent(maxSlippage) - const warning = getSlippageWarning(percent) - setAutoSlippage(!percent || warning === 'error') - }, [focus, maxSlippage, setAutoSlippage]) - - const processValue = useCallback( - (value: number | undefined) => { - const percent = toPercent(value) - const warning = getSlippageWarning(percent) - setMaxSlippage(value) - setAutoSlippage(!percent || warning === 'error') - }, - [setAutoSlippage, setMaxSlippage] - ) - - return ( - - - ) -} diff --git a/src/lib/components/Swap/Settings/MockToggle.tsx b/src/lib/components/Swap/Settings/MockToggle.tsx deleted file mode 100644 index bb7397162f..0000000000 --- a/src/lib/components/Swap/Settings/MockToggle.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useAtom } from 'jotai' -import { mockTogglableAtom } from 'lib/state/settings' - -import Row from '../../Row' -import Toggle from '../../Toggle' -import { Label } from './components' - -export default function MockToggle() { - const [mockTogglable, toggleMockTogglable] = useAtom(mockTogglableAtom) - return ( - - - ) -} diff --git a/src/lib/components/Swap/Settings/TransactionTtlInput.tsx b/src/lib/components/Swap/Settings/TransactionTtlInput.tsx deleted file mode 100644 index e5c4568661..0000000000 --- a/src/lib/components/Swap/Settings/TransactionTtlInput.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useDefaultTransactionTtl, useTransactionTtl } from 'lib/hooks/useTransactionDeadline' -import styled, { ThemedText } from 'lib/theme' -import { useRef } from 'react' - -import Column from '../../Column' -import { inputCss, IntegerInput } from '../../Input' -import Row from '../../Row' -import { Label } from './components' - -const tooltip = Your transaction will revert if it has been pending for longer than this period of time. - -const Input = styled(Row)` - ${inputCss} -` - -export default function TransactionTtlInput() { - const [ttl, setTtl] = useTransactionTtl() - const defaultTtl = useDefaultTransactionTtl() - const placeholder = defaultTtl.toString() - const input = useRef(null) - return ( - - - ) -} diff --git a/src/lib/components/Swap/Settings/components.tsx b/src/lib/components/Swap/Settings/components.tsx deleted file mode 100644 index 2e400e72a9..0000000000 --- a/src/lib/components/Swap/Settings/components.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import styled, { css, ThemedText } from 'lib/theme' -import { ReactNode } from 'react' -// eslint-disable-next-line no-restricted-imports -import { AnyStyledComponent } from 'styled-components' - -import Row from '../../Row' -import Tooltip from '../../Tooltip' - -export const optionCss = (selected: boolean) => css` - border: 1px solid ${({ theme }) => (selected ? theme.active : theme.outline)}; - border-radius: ${({ theme }) => theme.borderRadius * 0.75}em; - color: ${({ theme }) => theme.primary} !important; - display: grid; - grid-gap: 0.25em; - padding: calc(0.75em - 1px) 0.625em; - - :enabled { - border: 1px solid ${({ theme }) => (selected ? theme.active : theme.outline)}; - } - - :enabled:hover { - border-color: ${({ theme }) => theme.onHover(selected ? theme.active : theme.outline)}; - } - - :enabled:focus-within { - border-color: ${({ theme }) => theme.active}; - } -` - -export function value(Value: AnyStyledComponent) { - return styled(Value)<{ selected?: boolean; cursor?: string }>` - cursor: ${({ cursor }) => cursor ?? 'pointer'}; - ` -} - -interface LabelProps { - name: ReactNode - tooltip?: ReactNode -} - -export function Label({ name, tooltip }: LabelProps) { - return ( - - {name} - {tooltip && ( - - {tooltip} - - )} - - ) -} diff --git a/src/lib/components/Swap/Settings/index.tsx b/src/lib/components/Swap/Settings/index.tsx deleted file mode 100644 index 2d2288a9a3..0000000000 --- a/src/lib/components/Swap/Settings/index.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useResetAtom } from 'jotai/utils' -import useScrollbar from 'lib/hooks/useScrollbar' -import { Settings as SettingsIcon } from 'lib/icons' -import { settingsAtom } from 'lib/state/settings' -import styled, { ThemedText } from 'lib/theme' -import React, { useState } from 'react' - -import { IconButton, TextButton } from '../../Button' -import Column from '../../Column' -import Dialog, { Header } from '../../Dialog' -import { BoundaryProvider } from '../../Popover' -import MaxSlippageSelect from './MaxSlippageSelect' -import TransactionTtlInput from './TransactionTtlInput' - -export function SettingsDialog() { - const [boundary, setBoundary] = useState(null) - const scrollbar = useScrollbar(boundary, { padded: true }) - const resetSettings = useResetAtom(settingsAtom) - return ( - <> -
Settings} ruled> - - - Reset - - -
- - - - - - - - ) -} - -const SettingsButton = styled(IconButton)<{ hover: boolean }>` - ${SettingsIcon} { - transform: ${({ hover }) => hover && 'rotate(45deg)'}; - transition: ${({ hover }) => hover && 'transform 0.25s'}; - will-change: transform; - } -` - -export default function Settings({ disabled }: { disabled?: boolean }) { - const [open, setOpen] = useState(false) - const [hover, setHover] = useState(false) - return ( - <> - setOpen(true)} - onMouseEnter={() => setHover(true)} - onMouseLeave={() => setHover(false)} - icon={SettingsIcon} - /> - {open && ( - setOpen(false)}> - - - )} - - ) -} diff --git a/src/lib/components/Swap/Status.fixture.tsx b/src/lib/components/Swap/Status.fixture.tsx deleted file mode 100644 index e1b93a9d7d..0000000000 --- a/src/lib/components/Swap/Status.fixture.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Modal } from '../Dialog' - -function Fixture() { - return null - // TODO(zzmp): Mock void 0} /> -} - -export default ( - - - -) diff --git a/src/lib/components/Swap/Status/StatusDialog.tsx b/src/lib/components/Swap/Status/StatusDialog.tsx deleted file mode 100644 index eebe9262ca..0000000000 --- a/src/lib/components/Swap/Status/StatusDialog.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { Trans } from '@lingui/macro' -import ErrorDialog, { StatusHeader } from 'lib/components/Error/ErrorDialog' -import EtherscanLink from 'lib/components/EtherscanLink' -import Rule from 'lib/components/Rule' -import SwapSummary from 'lib/components/Swap/Summary' -import useInterval from 'lib/hooks/useInterval' -import { CheckCircle, Clock, Spinner } from 'lib/icons' -import { SwapTransactionInfo, Transaction, TransactionType, WrapTransactionInfo } from 'lib/state/transactions' -import styled, { ThemedText } from 'lib/theme' -import ms from 'ms.macro' -import { useCallback, useMemo, useState } from 'react' -import { ExplorerDataType } from 'utils/getExplorerLink' - -import ActionButton from '../../ActionButton' -import Column from '../../Column' -import Row from '../../Row' - -const errorMessage = ( - - Try increasing your slippage tolerance. -
- NOTE: Fee on transfer and rebase tokens are incompatible with Uniswap V3. -
-) - -const TransactionRow = styled(Row)` - flex-direction: row-reverse; -` - -type PendingTransaction = Transaction - -function ElapsedTime({ tx }: { tx: PendingTransaction }) { - const [elapsedMs, setElapsedMs] = useState(0) - - useInterval(() => setElapsedMs(Date.now() - tx.addedTime), tx.receipt ? null : ms`1s`) - - const toElapsedTime = useCallback((ms: number) => { - let sec = Math.floor(ms / 1000) - const min = Math.floor(sec / 60) - sec = sec % 60 - if (min) { - return ( - - {min}m {sec}s - - ) - } else { - return {sec}s - } - }, []) - return ( - - - {toElapsedTime(elapsedMs)} - - ) -} - -interface TransactionStatusProps { - tx: PendingTransaction - onClose: () => void -} - -function TransactionStatus({ tx, onClose }: TransactionStatusProps) { - const Icon = useMemo(() => { - return tx.receipt?.status ? CheckCircle : Spinner - }, [tx.receipt?.status]) - const heading = useMemo(() => { - if (tx.info.type === TransactionType.SWAP) { - return tx.receipt?.status ? Swap confirmed : Swap pending - } else if (tx.info.type === TransactionType.WRAP) { - if (tx.info.unwrapped) { - return tx.receipt?.status ? Unwrap confirmed : Unwrap pending - } - return tx.receipt?.status ? Wrap confirmed : Wrap pending - } - return tx.receipt?.status ? Transaction confirmed : Transaction pending - }, [tx.info, tx.receipt?.status]) - - return ( - - - {heading} - {tx.info.type === TransactionType.SWAP ? ( - - ) : null} - - - - - - View on Etherscan - - - - - - Close - - - ) -} - -export default function TransactionStatusDialog({ tx, onClose }: TransactionStatusProps) { - return tx.receipt?.status === 0 ? ( - Dismiss} - onClick={onClose} - /> - ) : ( - - ) -} diff --git a/src/lib/components/Swap/Status/index.ts b/src/lib/components/Swap/Status/index.ts deleted file mode 100644 index b0ccbf9360..0000000000 --- a/src/lib/components/Swap/Status/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as StatusDialog } from './StatusDialog' diff --git a/src/lib/components/Swap/Summary.fixture.tsx b/src/lib/components/Swap/Summary.fixture.tsx deleted file mode 100644 index f88f469e1e..0000000000 --- a/src/lib/components/Swap/Summary.fixture.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { tokens } from '@uniswap/default-token-list' -import { SupportedChainId } from 'constants/chains' -import { nativeOnChain } from 'constants/tokens' -import { useUpdateAtom } from 'jotai/utils' -import { useSwapInfo } from 'lib/hooks/swap' -import { SwapInfoProvider } from 'lib/hooks/swap/useSwapInfo' -import { Field, swapAtom } from 'lib/state/swap' -import { useEffect } from 'react' -import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo' -import invariant from 'tiny-invariant' - -import { Modal } from '../Dialog' -import { SummaryDialog } from './Summary' - -const ETH = nativeOnChain(SupportedChainId.MAINNET) -const UNI = (function () { - const token = tokens.find(({ symbol }) => symbol === 'UNI') - invariant(token) - return new WrappedTokenInfo(token) -})() - -function Fixture() { - const setState = useUpdateAtom(swapAtom) - const { - [Field.INPUT]: { usdc: inputUSDC }, - [Field.OUTPUT]: { usdc: outputUSDC }, - trade: { trade }, - slippage, - impact, - } = useSwapInfo() - - useEffect(() => { - setState({ - independentField: Field.INPUT, - amount: '1', - [Field.INPUT]: ETH, - [Field.OUTPUT]: UNI, - }) - }, [setState]) - - return trade ? ( - - void 0} - trade={trade} - slippage={slippage} - inputUSDC={inputUSDC} - outputUSDC={outputUSDC} - impact={impact} - /> - - ) : null -} - -export default ( - <> - - - - -) diff --git a/src/lib/components/Swap/Summary/Details.tsx b/src/lib/components/Swap/Summary/Details.tsx deleted file mode 100644 index 6e05b492ad..0000000000 --- a/src/lib/components/Swap/Summary/Details.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { t } from '@lingui/macro' -import { useLingui } from '@lingui/react' -import { Trade } from '@uniswap/router-sdk' -import { Currency, TradeType } from '@uniswap/sdk-core' -import { useAtomValue } from 'jotai/utils' -import Column from 'lib/components/Column' -import Row from 'lib/components/Row' -import { Slippage } from 'lib/hooks/useSlippage' -import { PriceImpact } from 'lib/hooks/useUSDCPriceImpact' -import { feeOptionsAtom } from 'lib/state/swap' -import styled, { Color, ThemedText } from 'lib/theme' -import { useMemo } from 'react' -import { currencyId } from 'utils/currencyId' -import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' -import { computeRealizedLPFeeAmount } from 'utils/prices' - -const Value = styled.span<{ color?: Color }>` - color: ${({ color, theme }) => color && theme[color]}; - white-space: nowrap; -` - -interface DetailProps { - label: string - value: string - color?: Color -} - -function Detail({ label, value, color }: DetailProps) { - return ( - - - {label} - {value} - - - ) -} - -interface DetailsProps { - trade: Trade - slippage: Slippage - impact?: PriceImpact -} - -export default function Details({ trade, slippage, impact }: DetailsProps) { - const { inputAmount, outputAmount } = trade - const inputCurrency = inputAmount.currency - const outputCurrency = outputAmount.currency - const integrator = window.location.hostname - const feeOptions = useAtomValue(feeOptionsAtom) - const lpFeeAmount = useMemo(() => computeRealizedLPFeeAmount(trade), [trade]) - const { i18n } = useLingui() - - const details = useMemo(() => { - const rows: Array<[string, string] | [string, string, Color | undefined]> = [] - // @TODO(ianlapham): Check that provider fee is even a valid list item - - if (feeOptions) { - const fee = outputAmount.multiply(feeOptions.fee) - if (fee.greaterThan(0)) { - const parsedFee = formatCurrencyAmount(fee, 6, i18n.locale) - rows.push([t`${integrator} fee`, `${parsedFee} ${outputCurrency.symbol || currencyId(outputCurrency)}`]) - } - } - - if (impact) { - rows.push([t`Price impact`, impact.toString(), impact.warning]) - } - - if (lpFeeAmount) { - const parsedLpFee = formatCurrencyAmount(lpFeeAmount, 6, i18n.locale) - rows.push([t`Liquidity provider fee`, `${parsedLpFee} ${inputCurrency.symbol || currencyId(inputCurrency)}`]) - } - - if (trade.tradeType === TradeType.EXACT_OUTPUT) { - const localizedMaxSent = formatCurrencyAmount(trade.maximumAmountIn(slippage.allowed), 6, i18n.locale) - rows.push([t`Maximum sent`, `${localizedMaxSent} ${inputCurrency.symbol}`]) - } - - if (trade.tradeType === TradeType.EXACT_INPUT) { - const localizedMaxSent = formatCurrencyAmount(trade.minimumAmountOut(slippage.allowed), 6, i18n.locale) - rows.push([t`Minimum received`, `${localizedMaxSent} ${outputCurrency.symbol}`]) - } - - rows.push([t`Slippage tolerance`, `${slippage.allowed.toFixed(2)}%`, slippage.warning]) - - return rows - }, [ - feeOptions, - i18n.locale, - impact, - inputCurrency, - integrator, - lpFeeAmount, - outputAmount, - outputCurrency, - slippage, - trade, - ]) - - return ( - - {details.map(([label, detail, color]) => ( - - ))} - - ) -} diff --git a/src/lib/components/Swap/Summary/Summary.tsx b/src/lib/components/Swap/Summary/Summary.tsx deleted file mode 100644 index d58f69c052..0000000000 --- a/src/lib/components/Swap/Summary/Summary.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { useLingui } from '@lingui/react' -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { PriceImpact } from 'lib/hooks/useUSDCPriceImpact' -import { ArrowRight } from 'lib/icons' -import { ThemedText } from 'lib/theme' -import { PropsWithChildren } from 'react' -import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' - -import Column from '../../Column' -import Row from '../../Row' -import TokenImg from '../../TokenImg' - -interface TokenValueProps { - input: CurrencyAmount - usdc?: CurrencyAmount -} - -function TokenValue({ input, usdc, children }: PropsWithChildren) { - const { i18n } = useLingui() - return ( - - - - - {formatCurrencyAmount(input, 6, i18n.locale)} {input.currency.symbol} - - - {usdc && ( - - - ${formatCurrencyAmount(usdc, 6, 'en', 2)} - {children} - - - )} - - ) -} - -interface SummaryProps { - input: CurrencyAmount - output: CurrencyAmount - inputUSDC?: CurrencyAmount - outputUSDC?: CurrencyAmount - impact?: PriceImpact -} - -export default function Summary({ input, output, inputUSDC, outputUSDC, impact }: SummaryProps) { - return ( - - - - - {impact && ({impact.toString()})} - - - ) -} diff --git a/src/lib/components/Swap/Summary/index.tsx b/src/lib/components/Swap/Summary/index.tsx deleted file mode 100644 index 3a334940a3..0000000000 --- a/src/lib/components/Swap/Summary/index.tsx +++ /dev/null @@ -1,182 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useLingui } from '@lingui/react' -import { Trade } from '@uniswap/router-sdk' -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import ActionButton, { Action } from 'lib/components/ActionButton' -import Column from 'lib/components/Column' -import { Header } from 'lib/components/Dialog' -import Expando from 'lib/components/Expando' -import Row from 'lib/components/Row' -import { Slippage } from 'lib/hooks/useSlippage' -import { PriceImpact } from 'lib/hooks/useUSDCPriceImpact' -import { AlertTriangle, BarChart, Info, Spinner } from 'lib/icons' -import styled, { ThemedText } from 'lib/theme' -import { useCallback, useMemo, useState } from 'react' -import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' -import { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer' - -import Price from '../Price' -import Details from './Details' -import Summary from './Summary' - -export default Summary - -const Content = styled(Column)`` -const Heading = styled(Column)`` -const Footing = styled(Column)`` -const Body = styled(Column)<{ open: boolean }>` - height: calc(100% - 2.5em); - - ${Content}, ${Heading} { - flex-grow: 1; - transition: flex-grow 0.25s; - } - - ${Footing} { - margin-bottom: ${({ open }) => (open ? '-0.75em' : undefined)}; - max-height: ${({ open }) => (open ? 0 : '3em')}; - opacity: ${({ open }) => (open ? 0 : 1)}; - transition: max-height 0.25s, margin-bottom 0.25s, opacity 0.15s 0.1s; - visibility: ${({ open }) => (open ? 'hidden' : undefined)}; - } -` - -function Subhead({ impact, slippage }: { impact?: PriceImpact; slippage: Slippage }) { - return ( - - {impact?.warning || slippage.warning ? ( - - ) : ( - - )} - - {impact?.warning ? ( - High price impact - ) : slippage.warning ? ( - High slippage - ) : ( - Swap details - )} - - - ) -} - -function Estimate({ trade, slippage }: { trade: Trade; slippage: Slippage }) { - const { i18n } = useLingui() - const text = useMemo(() => { - switch (trade.tradeType) { - case TradeType.EXACT_INPUT: - return ( - - Output is estimated. You will receive at least{' '} - {formatCurrencyAmount(trade.minimumAmountOut(slippage.allowed), 6, i18n.locale)}{' '} - {trade.outputAmount.currency.symbol} or the transaction will revert. - - ) - case TradeType.EXACT_OUTPUT: - return ( - - Output is estimated. You will send at most{' '} - {formatCurrencyAmount(trade.maximumAmountIn(slippage.allowed), 6, i18n.locale)}{' '} - {trade.inputAmount.currency.symbol} or the transaction will revert. - - ) - } - }, [i18n.locale, slippage.allowed, trade]) - return {text} -} - -function ConfirmButton({ - trade, - highPriceImpact, - onConfirm, -}: { - trade: Trade - highPriceImpact: boolean - onConfirm: () => Promise -}) { - const [ackPriceImpact, setAckPriceImpact] = useState(false) - - const [ackTrade, setAckTrade] = useState(trade) - const doesTradeDiffer = useMemo( - () => Boolean(trade && ackTrade && tradeMeaningfullyDiffers(trade, ackTrade)), - [ackTrade, trade] - ) - - const [isPending, setIsPending] = useState(false) - const onClick = useCallback(async () => { - setIsPending(true) - await onConfirm() - setIsPending(false) - }, [onConfirm]) - - const action = useMemo((): Action | undefined => { - if (isPending) { - return { message: Confirm in your wallet, icon: Spinner } - } else if (doesTradeDiffer) { - return { - message: Price updated, - icon: BarChart, - onClick: () => setAckTrade(trade), - children: Accept, - } - } else if (highPriceImpact && !ackPriceImpact) { - return { - message: High price impact, - onClick: () => setAckPriceImpact(true), - children: Acknowledge, - } - } - return - }, [ackPriceImpact, doesTradeDiffer, highPriceImpact, isPending, trade]) - - return ( - - Confirm swap - - ) -} - -interface SummaryDialogProps { - trade: Trade - slippage: Slippage - inputUSDC?: CurrencyAmount - outputUSDC?: CurrencyAmount - impact?: PriceImpact - onConfirm: () => Promise -} - -export function SummaryDialog({ trade, slippage, inputUSDC, outputUSDC, impact, onConfirm }: SummaryDialogProps) { - const { inputAmount, outputAmount } = trade - - const [open, setOpen] = useState(false) - const onExpand = useCallback(() => setOpen((open) => !open), []) - - return ( - <> -
Swap summary} ruled /> - - - - - - - } open={open} onExpand={onExpand} height={7}> -
- - - - - - - - - ) -} diff --git a/src/lib/components/Swap/Swap.fixture.tsx b/src/lib/components/Swap/Swap.fixture.tsx deleted file mode 100644 index 52140f5a07..0000000000 --- a/src/lib/components/Swap/Swap.fixture.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { tokens } from '@uniswap/default-token-list' -import { TokenInfo } from '@uniswap/token-lists' -import { SupportedChainId } from 'constants/chains' -import { DAI, USDC_MAINNET } from 'constants/tokens' -import { useUpdateAtom } from 'jotai/utils' -import { TokenListProvider } from 'lib/hooks/useTokenList' -import { useEffect } from 'react' -import { useSelect, useValue } from 'react-cosmos/fixture' - -import Swap from '.' -import { colorAtom } from './Output' - -const validateColor = (() => { - const validator = document.createElement('div').style - return (color: string) => { - validator.color = '' - validator.color = color - return validator.color !== '' - } -})() - -function Fixture() { - const setColor = useUpdateAtom(colorAtom) - const [color] = useValue('token color', { defaultValue: '' }) - useEffect(() => { - if (!color || validateColor(color)) { - setColor(color) - } - }, [color, setColor]) - - const [convenienceFee] = useValue('convenienceFee', { defaultValue: 100 }) - const FEE_RECIPIENT_OPTIONS = [ - '', - '0x1D9Cd50Dde9C19073B81303b3d930444d11552f7', - '0x0dA5533d5a9aA08c1792Ef2B6a7444E149cCB0AD', - '0xE6abE059E5e929fd17bef158902E73f0FEaCD68c', - ] - const [convenienceFeeRecipient] = useSelect('convenienceFeeRecipient', { - options: FEE_RECIPIENT_OPTIONS, - defaultValue: FEE_RECIPIENT_OPTIONS[1], - }) - - const optionsToAddressMap: Record = { - None: undefined, - Native: 'NATIVE', - DAI: DAI.address, - USDC: USDC_MAINNET.address, - } - const addressOptions = Object.keys(optionsToAddressMap) - - const [defaultInputToken] = useSelect('defaultInputToken', { - options: addressOptions, - defaultValue: addressOptions[1], - }) - const [defaultInputAmount] = useValue('defaultInputAmount', { defaultValue: 1 }) - - const [defaultOutputToken] = useSelect('defaultOutputToken', { - options: addressOptions, - defaultValue: addressOptions[2], - }) - const [defaultOutputAmount] = useValue('defaultOutputAmount', { defaultValue: 0 }) - - const tokenListNameMap: Record = { - 'default list': tokens, - 'mainnet only': tokens.filter((token) => SupportedChainId.MAINNET === token.chainId), - 'arbitrum only': [ - { - logoURI: 'https://assets.coingecko.com/coins/images/9956/thumb/4943.png?1636636734', - chainId: 42161, - address: '0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1', - name: 'Dai Stablecoin', - symbol: 'DAI', - decimals: 18, - }, - { - logoURI: 'https://assets.coingecko.com/coins/images/6319/thumb/USD_Coin_icon.png?1547042389', - chainId: 42161, - address: '0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8', - name: 'USD Coin (Arb1)', - symbol: 'USDC', - decimals: 6, - }, - ], - } - - const tokenListOptions = Object.keys(tokenListNameMap) - const [tokenListName] = useSelect('tokenList', { - options: tokenListOptions, - defaultValue: tokenListOptions[0], - }) - - return ( - - console.log('onConnectWallet')} // this handler is included as a test of functionality, but only logs - /> - - ) -} - -export default diff --git a/src/lib/components/Swap/SwapButton/index.tsx b/src/lib/components/Swap/SwapButton/index.tsx deleted file mode 100644 index 967f7571db..0000000000 --- a/src/lib/components/Swap/SwapButton/index.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useAtomValue, useUpdateAtom } from 'jotai/utils' -import { useSwapInfo } from 'lib/hooks/swap' -import { useSwapApprovalOptimizedTrade } from 'lib/hooks/swap/useSwapApproval' -import { useSwapCallback } from 'lib/hooks/swap/useSwapCallback' -import useWrapCallback, { WrapType } from 'lib/hooks/swap/useWrapCallback' -import { useAddTransaction } from 'lib/hooks/transactions' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { useSetOldestValidBlock } from 'lib/hooks/useIsValidBlock' -import useTransactionDeadline from 'lib/hooks/useTransactionDeadline' -import { Spinner } from 'lib/icons' -import { displayTxHashAtom, feeOptionsAtom, Field } from 'lib/state/swap' -import { TransactionType } from 'lib/state/transactions' -import { useTheme } from 'lib/theme' -import { isAnimating } from 'lib/utils/animations' -import { memo, useCallback, useEffect, useMemo, useState } from 'react' -import { TradeState } from 'state/routing/types' -import invariant from 'tiny-invariant' - -import ActionButton, { ActionButtonProps } from '../../ActionButton' -import Dialog from '../../Dialog' -import { SummaryDialog } from '../Summary' -import useApprovalData, { useIsPendingApproval } from './useApprovalData' - -interface SwapButtonProps { - disabled?: boolean -} - -export default memo(function SwapButton({ disabled }: SwapButtonProps) { - const { account, chainId } = useActiveWeb3React() - const { - [Field.INPUT]: { - currency: inputCurrency, - amount: inputCurrencyAmount, - balance: inputCurrencyBalance, - usdc: inputUSDC, - }, - [Field.OUTPUT]: { usdc: outputUSDC }, - trade, - slippage, - impact, - } = useSwapInfo() - const feeOptions = useAtomValue(feeOptionsAtom) - - // TODO(zzmp): Return an optimized trade directly from useSwapInfo. - const optimizedTrade = - // Use trade.trade if there is no swap optimized trade. This occurs if approvals are still pending. - useSwapApprovalOptimizedTrade(trade.trade, slippage.allowed, useIsPendingApproval) || trade.trade - const deadline = useTransactionDeadline() - - const { type: wrapType, callback: wrapCallback } = useWrapCallback() - const { approvalAction, signatureData } = useApprovalData(optimizedTrade, slippage, inputCurrencyAmount) - const { callback: swapCallback } = useSwapCallback({ - trade: optimizedTrade, - allowedSlippage: slippage.allowed, - recipientAddressOrName: account ?? null, - signatureData, - deadline, - feeOptions, - }) - - const [open, setOpen] = useState(false) - // Close the review modal if there is no available trade. - useEffect(() => setOpen((open) => (trade.trade ? open : false)), [trade.trade]) - // Close the review modal on chain change. - useEffect(() => setOpen(false), [chainId]) - - const addTransaction = useAddTransaction() - const setDisplayTxHash = useUpdateAtom(displayTxHashAtom) - const setOldestValidBlock = useSetOldestValidBlock() - - const [isPending, setIsPending] = useState(false) - const onWrap = useCallback(async () => { - setIsPending(true) - try { - const transaction = await wrapCallback?.() - if (!transaction) return - addTransaction({ - response: transaction, - type: TransactionType.WRAP, - unwrapped: wrapType === WrapType.UNWRAP, - currencyAmountRaw: transaction.value?.toString() ?? '0', - chainId, - }) - setDisplayTxHash(transaction.hash) - } catch (e) { - // TODO(zzmp): Surface errors from wrap. - console.log(e) - } - - // Only reset pending after any queued animations to avoid layout thrashing, because a - // successful wrap will open the status dialog and immediately cover the button. - const postWrap = () => { - setIsPending(false) - document.removeEventListener('animationend', postWrap) - } - if (isAnimating(document)) { - document.addEventListener('animationend', postWrap) - } else { - postWrap() - } - }, [addTransaction, chainId, setDisplayTxHash, wrapCallback, wrapType]) - // Reset the pending state if user updates the swap. - useEffect(() => setIsPending(false), [inputCurrencyAmount, trade]) - - const onSwap = useCallback(async () => { - try { - const transaction = await swapCallback?.() - if (!transaction) return - invariant(trade.trade) - addTransaction({ - response: transaction, - type: TransactionType.SWAP, - tradeType: trade.trade.tradeType, - inputCurrencyAmount: trade.trade.inputAmount, - outputCurrencyAmount: trade.trade.outputAmount, - }) - setDisplayTxHash(transaction.hash) - - // Set the block containing the response to the oldest valid block to ensure that the - // completed trade's impact is reflected in future fetched trades. - transaction.wait(1).then((receipt) => { - setOldestValidBlock(receipt.blockNumber) - }) - - // Only reset open after any queued animations to avoid layout thrashing, because a - // successful swap will open the status dialog and immediately cover the summary dialog. - const postSwap = () => { - setOpen(false) - document.removeEventListener('animationend', postSwap) - } - if (isAnimating(document)) { - document.addEventListener('animationend', postSwap) - } else { - postSwap() - } - } catch (e) { - // TODO(zzmp): Surface errors from swap. - console.log(e) - } - }, [addTransaction, setDisplayTxHash, setOldestValidBlock, swapCallback, trade.trade]) - - const disableSwap = useMemo( - () => - disabled || - !chainId || - (wrapType === WrapType.NONE && !optimizedTrade) || - !(inputCurrencyAmount && inputCurrencyBalance) || - inputCurrencyBalance.lessThan(inputCurrencyAmount), - [disabled, wrapType, optimizedTrade, chainId, inputCurrencyAmount, inputCurrencyBalance] - ) - const actionProps = useMemo((): Partial | undefined => { - if (disableSwap) { - return { disabled: true } - } else if (wrapType === WrapType.NONE) { - return approvalAction - ? { action: approvalAction } - : trade.state === TradeState.VALID - ? { onClick: () => setOpen(true) } - : { disabled: true } - } else { - return isPending - ? { action: { message: Confirm in your wallet, icon: Spinner } } - : { onClick: onWrap } - } - }, [approvalAction, disableSwap, isPending, onWrap, trade.state, wrapType]) - const Label = useCallback(() => { - switch (wrapType) { - case WrapType.UNWRAP: - return Unwrap {inputCurrency?.symbol} - case WrapType.WRAP: - return Wrap {inputCurrency?.symbol} - case WrapType.NONE: - default: - return Review swap - } - }, [inputCurrency?.symbol, wrapType]) - const onClose = useCallback(() => setOpen(false), []) - - const { tokenColorExtraction } = useTheme() - return ( - <> - - - {open && trade.trade && ( - - - - )} - - ) -}) diff --git a/src/lib/components/Swap/SwapButton/useApprovalData.tsx b/src/lib/components/Swap/SwapButton/useApprovalData.tsx deleted file mode 100644 index 5d16aac0c8..0000000000 --- a/src/lib/components/Swap/SwapButton/useApprovalData.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { Trans } from '@lingui/macro' -import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core' -import { Action } from 'lib/components/ActionButton' -import EtherscanLink from 'lib/components/EtherscanLink' -import { - ApproveOrPermitState, - useApproveOrPermit, - useSwapApprovalOptimizedTrade, - useSwapRouterAddress, -} from 'lib/hooks/swap/useSwapApproval' -import { useAddTransaction, usePendingApproval } from 'lib/hooks/transactions' -import { Slippage } from 'lib/hooks/useSlippage' -import { Spinner } from 'lib/icons' -import { TransactionType } from 'lib/state/transactions' -import { useCallback, useEffect, useMemo, useState } from 'react' -import { ExplorerDataType } from 'utils/getExplorerLink' - -export function useIsPendingApproval(token?: Token, spender?: string): boolean { - return Boolean(usePendingApproval(token, spender)) -} - -export default function useApprovalData( - trade: ReturnType, - slippage: Slippage, - currencyAmount?: CurrencyAmount -) { - const currency = currencyAmount?.currency - const { approvalState, signatureData, handleApproveOrPermit } = useApproveOrPermit( - trade, - slippage.allowed, - useIsPendingApproval, - currencyAmount - ) - - const [isPending, setIsPending] = useState(false) - const addTransaction = useAddTransaction() - const onApprove = useCallback(async () => { - setIsPending(true) - const transaction = await handleApproveOrPermit() - if (transaction) { - addTransaction({ type: TransactionType.APPROVAL, ...transaction }) - } - setIsPending(false) - }, [addTransaction, handleApproveOrPermit]) - // Reset the pending state if currency changes. - useEffect(() => setIsPending(false), [currency]) - - const approvalHash = usePendingApproval(currency?.isToken ? currency : undefined, useSwapRouterAddress(trade)) - const approvalAction = useMemo((): Action | undefined => { - if (!trade || !currency) return - - switch (approvalState) { - case ApproveOrPermitState.REQUIRES_APPROVAL: - if (isPending) { - return { message: Approve in your wallet, icon: Spinner } - } - return { - message: Approve {currency.symbol} first, - onClick: onApprove, - children: Approve, - } - case ApproveOrPermitState.REQUIRES_SIGNATURE: - if (isPending) { - return { message: Allow in your wallet, icon: Spinner } - } - return { - message: Allow {currency.symbol} first, - onClick: onApprove, - children: Allow, - } - case ApproveOrPermitState.PENDING_APPROVAL: - return { - message: ( - - Approval pending - - ), - icon: Spinner, - } - case ApproveOrPermitState.PENDING_SIGNATURE: - return { message: Allowance pending, icon: Spinner } - case ApproveOrPermitState.APPROVED: - return - } - }, [approvalHash, approvalState, currency, isPending, onApprove, trade]) - - return { approvalAction, signatureData: signatureData ?? undefined } -} diff --git a/src/lib/components/Swap/TokenInput.tsx b/src/lib/components/Swap/TokenInput.tsx deleted file mode 100644 index 7fa28bec5a..0000000000 --- a/src/lib/components/Swap/TokenInput.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import 'setimmediate' - -import { Trans } from '@lingui/macro' -import { Currency } from '@uniswap/sdk-core' -import TokenSelect from 'lib/components/TokenSelect' -import { loadingTransitionCss } from 'lib/css/loading' -import styled, { keyframes, ThemedText } from 'lib/theme' -import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react' - -import Button from '../Button' -import Column from '../Column' -import { DecimalInput } from '../Input' -import Row from '../Row' - -const TokenInputRow = styled(Row)` - grid-template-columns: 1fr; -` - -const ValueInput = styled(DecimalInput)` - color: ${({ theme }) => theme.primary}; - height: 1.5em; - margin: -0.25em 0; - - :hover:not(:focus-within) { - color: ${({ theme }) => theme.onHover(theme.primary)}; - } - - :hover:not(:focus-within)::placeholder { - color: ${({ theme }) => theme.onHover(theme.secondary)}; - } - - ${loadingTransitionCss} -` - -const delayedFadeIn = keyframes` - 0% { - opacity: 0; - } - 25% { - opacity: 0; - } - 100% { - opacity: 1; - } -` - -const MaxButton = styled(Button)` - animation: ${delayedFadeIn} 0.25s linear; - border-radius: 0.75em; - padding: 0.5em; -` - -interface TokenInputProps { - currency?: Currency - amount: string - max?: string - disabled?: boolean - onChangeInput: (input: string) => void - onChangeCurrency: (currency: Currency) => void - loading?: boolean - children: ReactNode -} - -export default function TokenInput({ - currency, - amount, - max, - disabled, - onChangeInput, - onChangeCurrency, - loading, - children, -}: TokenInputProps) { - const input = useRef(null) - const onSelect = useCallback( - (currency: Currency) => { - onChangeCurrency(currency) - setImmediate(() => input.current?.focus()) - }, - [onChangeCurrency] - ) - - const maxButton = useRef(null) - const hasMax = useMemo(() => Boolean(max && max !== amount), [max, amount]) - const [showMax, setShowMax] = useState(hasMax) - useEffect(() => setShowMax((hasMax && input.current?.contains(document.activeElement)) ?? false), [hasMax]) - const onBlur = useCallback((e) => { - // Filters out clicks on input or maxButton, because onBlur fires before onClickMax. - if (!input.current?.contains(e.relatedTarget) && !maxButton.current?.contains(e.relatedTarget)) { - setShowMax(false) - } - }, []) - const onClickMax = useCallback(() => { - onChangeInput(max || '') - setShowMax(false) - setImmediate(() => { - input.current?.focus() - // Brings the start of the input into view. NB: This only works for clicks, not eg keyboard interactions. - input.current?.setSelectionRange(0, null) - }) - }, [max, onChangeInput]) - - return ( - - - - setShowMax(hasMax)} - onChange={onChangeInput} - disabled={disabled || !currency} - isLoading={Boolean(loading)} - ref={input} - > - - {showMax && ( - - {/* Without a tab index, Safari would not populate the FocusEvent.relatedTarget needed by onBlur. */} - - Max - - - )} - - - {children} - - ) -} diff --git a/src/lib/components/Swap/Toolbar/Caption.tsx b/src/lib/components/Swap/Toolbar/Caption.tsx deleted file mode 100644 index 3a6315e45e..0000000000 --- a/src/lib/components/Swap/Toolbar/Caption.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { Trans } from '@lingui/macro' -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import Column from 'lib/components/Column' -import Rule from 'lib/components/Rule' -import Tooltip from 'lib/components/Tooltip' -import { loadingCss } from 'lib/css/loading' -import { PriceImpact } from 'lib/hooks/useUSDCPriceImpact' -import { AlertTriangle, Icon, Info, InlineSpinner } from 'lib/icons' -import styled, { ThemedText } from 'lib/theme' -import { ReactNode, useCallback } from 'react' -import { InterfaceTrade } from 'state/routing/types' - -import Price from '../Price' -import RoutingDiagram from '../RoutingDiagram' - -const Loading = styled.span` - color: ${({ theme }) => theme.secondary}; - ${loadingCss}; -` - -interface CaptionProps { - icon?: Icon - caption: ReactNode -} - -function Caption({ icon: Icon = AlertTriangle, caption }: CaptionProps) { - return ( - <> - - {caption} - - ) -} - -export function Connecting() { - return ( - - Connecting… - - } - /> - ) -} - -export function ConnectWallet() { - return Connect wallet to swap} /> -} - -export function UnsupportedNetwork() { - return Unsupported network - switch to another to trade} /> -} - -export function InsufficientBalance({ currency }: { currency: Currency }) { - return Insufficient {currency?.symbol} balance} /> -} - -export function InsufficientLiquidity() { - return Insufficient liquidity in the pool for your trade} /> -} - -export function Error() { - return Error fetching trade} /> -} - -export function Empty() { - return Enter an amount} /> -} - -export function LoadingTrade() { - return ( - - Fetching best price… - - } - /> - ) -} - -export function WrapCurrency({ inputCurrency, outputCurrency }: { inputCurrency: Currency; outputCurrency: Currency }) { - const Text = useCallback( - () => ( - - Convert {inputCurrency.symbol} to {outputCurrency.symbol} - - ), - [inputCurrency.symbol, outputCurrency.symbol] - ) - - return } /> -} - -export function Trade({ - trade, - outputUSDC, - impact, -}: { - trade: InterfaceTrade - outputUSDC?: CurrencyAmount - impact?: PriceImpact -}) { - return ( - <> - - - {impact?.warning && ( - <> - - The output amount is estimated at {impact.toString()} less than the input amount due to high price - impact - - - - )} - - - - - - ) -} diff --git a/src/lib/components/Swap/Toolbar/index.tsx b/src/lib/components/Swap/Toolbar/index.tsx deleted file mode 100644 index f4f83075f1..0000000000 --- a/src/lib/components/Swap/Toolbar/index.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { ALL_SUPPORTED_CHAIN_IDS } from 'constants/chains' -import { useIsAmountPopulated, useSwapInfo } from 'lib/hooks/swap' -import useWrapCallback, { WrapType } from 'lib/hooks/swap/useWrapCallback' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { largeIconCss } from 'lib/icons' -import { Field } from 'lib/state/swap' -import styled, { ThemedText } from 'lib/theme' -import { memo, useMemo } from 'react' -import { TradeState } from 'state/routing/types' - -import Row from '../../Row' -import Rule from '../../Rule' -import * as Caption from './Caption' - -const ToolbarRow = styled(Row)` - padding: 0.5em 0; - ${largeIconCss} -` - -export default memo(function Toolbar() { - const { active, activating, chainId } = useActiveWeb3React() - const { - [Field.INPUT]: { currency: inputCurrency, balance: inputBalance, amount: inputAmount }, - [Field.OUTPUT]: { currency: outputCurrency, usdc: outputUSDC }, - trade: { trade, state }, - impact, - } = useSwapInfo() - const isAmountPopulated = useIsAmountPopulated() - const { type: wrapType } = useWrapCallback() - const caption = useMemo(() => { - if (!active || !chainId) { - if (activating) return - return - } - - if (!ALL_SUPPORTED_CHAIN_IDS.includes(chainId)) { - return - } - - if (inputCurrency && outputCurrency && isAmountPopulated) { - if (state === TradeState.SYNCING || state === TradeState.LOADING) { - return - } - if (inputBalance && inputAmount?.greaterThan(inputBalance)) { - return - } - if (wrapType !== WrapType.NONE) { - return - } - if (state === TradeState.NO_ROUTE_FOUND || (trade && !trade.swaps)) { - return - } - if (trade?.inputAmount && trade.outputAmount) { - return - } - if (state === TradeState.INVALID) { - return - } - } - - return - }, [ - activating, - active, - chainId, - impact, - inputAmount, - inputBalance, - inputCurrency, - isAmountPopulated, - outputCurrency, - outputUSDC, - state, - trade, - wrapType, - ]) - - return ( - <> - - - - {caption} - - - - ) -}) diff --git a/src/lib/components/Swap/index.tsx b/src/lib/components/Swap/index.tsx deleted file mode 100644 index b89bd9ab26..0000000000 --- a/src/lib/components/Swap/index.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { Trans } from '@lingui/macro' -import { useAtom } from 'jotai' -import { SwapInfoProvider } from 'lib/hooks/swap/useSwapInfo' -import useSyncConvenienceFee, { FeeOptions } from 'lib/hooks/swap/useSyncConvenienceFee' -import useSyncTokenDefaults, { TokenDefaults } from 'lib/hooks/swap/useSyncTokenDefaults' -import { usePendingTransactions } from 'lib/hooks/transactions' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import useHasFocus from 'lib/hooks/useHasFocus' -import useOnSupportedNetwork from 'lib/hooks/useOnSupportedNetwork' -import { displayTxHashAtom } from 'lib/state/swap' -import { SwapTransactionInfo, Transaction, TransactionType, WrapTransactionInfo } from 'lib/state/transactions' -import { useState } from 'react' - -import Dialog from '../Dialog' -import Header from '../Header' -import { BoundaryProvider } from '../Popover' -import Wallet from '../Wallet' -import Input from './Input' -import Output from './Output' -import ReverseButton from './ReverseButton' -import Settings from './Settings' -import { StatusDialog } from './Status' -import SwapButton from './SwapButton' -import Toolbar from './Toolbar' -import useValidate from './useValidate' - -function getTransactionFromMap( - txs: { [hash: string]: Transaction }, - hash?: string -): Transaction | undefined { - if (hash) { - const tx = txs[hash] - if (tx?.info?.type === TransactionType.SWAP) { - return tx as Transaction - } - if (tx?.info?.type === TransactionType.WRAP) { - return tx as Transaction - } - } - return -} - -export interface SwapProps extends TokenDefaults, FeeOptions { - onConnectWallet?: () => void -} - -export default function Swap(props: SwapProps) { - useValidate(props) - useSyncConvenienceFee(props) - useSyncTokenDefaults(props) - - const { active, account } = useActiveWeb3React() - const [wrapper, setWrapper] = useState(null) - - const [displayTxHash, setDisplayTxHash] = useAtom(displayTxHashAtom) - const pendingTxs = usePendingTransactions() - const displayTx = getTransactionFromMap(pendingTxs, displayTxHash) - - const onSupportedNetwork = useOnSupportedNetwork() - const isDisabled = !(active && onSupportedNetwork) - - const focused = useHasFocus(wrapper) - - return ( - <> -
Swap}> - {active && } - -
-
- - - - - - - - - - -
- {displayTx && ( - - setDisplayTxHash()} /> - - )} - - ) -} diff --git a/src/lib/components/Swap/useValidate.tsx b/src/lib/components/Swap/useValidate.tsx deleted file mode 100644 index 7ae2f135e5..0000000000 --- a/src/lib/components/Swap/useValidate.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { IntegrationError } from 'lib/errors' -import { FeeOptions } from 'lib/hooks/swap/useSyncConvenienceFee' -import { DefaultAddress, TokenDefaults } from 'lib/hooks/swap/useSyncTokenDefaults' -import { PropsWithChildren, useEffect } from 'react' - -import { isAddress } from '../../../utils' - -function isAddressOrAddressMap(addressOrMap: DefaultAddress): boolean { - if (typeof addressOrMap === 'object') { - return Object.values(addressOrMap).every((address) => isAddress(address)) - } - if (typeof addressOrMap === 'string') { - return typeof isAddress(addressOrMap) === 'string' - } - return false -} - -type ValidatorProps = PropsWithChildren - -export default function useValidate(props: ValidatorProps) { - const { convenienceFee, convenienceFeeRecipient } = props - useEffect(() => { - if (convenienceFee) { - if (convenienceFee > 100 || convenienceFee < 0) { - throw new IntegrationError(`convenienceFee must be between 0 and 100 (you set it to ${convenienceFee}).`) - } - if (!convenienceFeeRecipient) { - throw new IntegrationError('convenienceFeeRecipient is required when convenienceFee is set.') - } - - if (typeof convenienceFeeRecipient === 'string') { - if (!isAddress(convenienceFeeRecipient)) { - throw new IntegrationError( - `convenienceFeeRecipient must be a valid address (you set it to ${convenienceFeeRecipient}).` - ) - } - } else if (typeof convenienceFeeRecipient === 'object') { - Object.values(convenienceFeeRecipient).forEach((recipient) => { - if (!isAddress(recipient)) { - const values = Object.values(convenienceFeeRecipient).join(', ') - throw new IntegrationError( - `All values in convenienceFeeRecipient object must be valid addresses (you used ${values}).` - ) - } - }) - } - } - }, [convenienceFee, convenienceFeeRecipient]) - - const { defaultInputAmount, defaultOutputAmount } = props - useEffect(() => { - if (defaultOutputAmount && defaultInputAmount) { - throw new IntegrationError('defaultInputAmount and defaultOutputAmount may not both be defined.') - } - if (defaultInputAmount && (isNaN(+defaultInputAmount) || defaultInputAmount < 0)) { - throw new IntegrationError(`defaultInputAmount must be a positive number (you set it to ${defaultInputAmount})`) - } - if (defaultOutputAmount && (isNaN(+defaultOutputAmount) || defaultOutputAmount < 0)) { - throw new IntegrationError( - `defaultOutputAmount must be a positive number (you set it to ${defaultOutputAmount}).` - ) - } - }, [defaultInputAmount, defaultOutputAmount]) - - const { defaultInputTokenAddress, defaultOutputTokenAddress } = props - useEffect(() => { - if ( - defaultInputTokenAddress && - !isAddressOrAddressMap(defaultInputTokenAddress) && - defaultInputTokenAddress !== 'NATIVE' - ) { - throw new IntegrationError( - `defaultInputTokenAddress must be a valid address or "NATIVE" (you set it to ${defaultInputTokenAddress}).` - ) - } - if ( - defaultOutputTokenAddress && - !isAddressOrAddressMap(defaultOutputTokenAddress) && - defaultOutputTokenAddress !== 'NATIVE' - ) { - throw new IntegrationError( - `defaultOutputTokenAddress must be a valid address or "NATIVE" (you set it to ${defaultOutputTokenAddress}).` - ) - } - }, [defaultInputTokenAddress, defaultOutputTokenAddress]) -} diff --git a/src/lib/components/Toggle.tsx b/src/lib/components/Toggle.tsx deleted file mode 100644 index f8c10e2f46..0000000000 --- a/src/lib/components/Toggle.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { t } from '@lingui/macro' -import styled, { ThemedText } from 'lib/theme' -import { transparentize } from 'polished' -import { KeyboardEvent, useCallback } from 'react' - -const Input = styled.input<{ text: string }>` - -moz-appearance: none; - -webkit-appearance: none; - align-items: center; - appearance: none; - background: ${({ theme }) => theme.interactive}; - border: none; - border-radius: ${({ theme }) => theme.borderRadius * 1.25}em; - cursor: pointer; - display: flex; - font-size: inherit; - font-weight: inherit; - height: 2em; - margin: 0; - padding: 0; - - position: relative; - width: 4.5em; - - :before { - background-color: ${({ theme }) => theme.secondary}; - border-radius: ${({ theme }) => theme.borderRadius * 50}%; - content: ''; - display: inline-block; - height: 1.5em; - margin-left: 0.25em; - position: absolute; - width: 1.5em; - } - - :hover:before { - background-color: ${({ theme }) => transparentize(0.3, theme.secondary)}; - } - - :checked:before { - background-color: ${({ theme }) => theme.accent}; - margin-left: 2.75em; - } - - :hover:checked:before { - background-color: ${({ theme }) => transparentize(0.3, theme.accent)}; - } - - :after { - content: '${({ text }) => text}'; - margin-left: 1.75em; - text-align: center; - width: 2.75em; - } - - :checked:after { - margin-left: 0; - } - - :before { - transition: margin 0.25s ease; - } -` - -interface ToggleProps { - checked: boolean - onToggle: () => void -} - -export default function Toggle({ checked, onToggle }: ToggleProps) { - const onKeyDown = useCallback( - (e: KeyboardEvent) => { - if (e.key === 'Enter') { - onToggle() - } - }, - [onToggle] - ) - return ( - - onToggle()} - onKeyDown={onKeyDown} - /> - - ) -} diff --git a/src/lib/components/TokenImg.tsx b/src/lib/components/TokenImg.tsx deleted file mode 100644 index 0bf51b10e4..0000000000 --- a/src/lib/components/TokenImg.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { Currency } from '@uniswap/sdk-core' -import { useToken } from 'lib/hooks/useCurrency' -import useCurrencyLogoURIs from 'lib/hooks/useCurrencyLogoURIs' -import { MissingToken } from 'lib/icons' -import styled from 'lib/theme' -import { useCallback, useMemo, useState } from 'react' - -const badSrcs = new Set() - -interface BaseProps { - token: Currency -} - -type TokenImgProps = BaseProps & Omit, keyof BaseProps> - -function TokenImg({ token, ...rest }: TokenImgProps) { - // Use the wrapped token info so that it includes the logoURI. - const tokenInfo = useToken(token.isToken ? token.wrapped.address : undefined) ?? token - - const srcs = useCurrencyLogoURIs(tokenInfo) - - const [attempt, setAttempt] = useState(0) - const src = useMemo(() => { - // Trigger a re-render when an error occurs. - void attempt - - return srcs.find((src) => !badSrcs.has(src)) - }, [attempt, srcs]) - const onError = useCallback( - (e) => { - if (src) badSrcs.add(src) - setAttempt((attempt) => ++attempt) - }, - [src] - ) - - if (!src) return - - const alt = tokenInfo.name || tokenInfo.symbol - return {alt} -} - -export default styled(TokenImg)<{ size?: number }>` - // radial-gradient calculates distance from the corner, not the edge: divide by sqrt(2) - background: radial-gradient( - ${({ theme }) => theme.module} calc(100% / ${Math.sqrt(2)} - 1.5px), - ${({ theme }) => theme.outline} calc(100% / ${Math.sqrt(2)} - 1.5px) - ); - border-radius: 100%; - height: ${({ size }) => size || 1}em; - width: ${({ size }) => size || 1}em; -` diff --git a/src/lib/components/TokenSelect.fixture.tsx b/src/lib/components/TokenSelect.fixture.tsx deleted file mode 100644 index 487819c30a..0000000000 --- a/src/lib/components/TokenSelect.fixture.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list' -import { TokenListProvider } from 'lib/hooks/useTokenList' - -import { Modal } from './Dialog' -import { TokenSelectDialog } from './TokenSelect' - -export default function Fixture() { - return ( - - - void 0} onClose={() => void 0} /> - - - ) -} diff --git a/src/lib/components/TokenSelect/NoTokensAvailableOnNetwork.tsx b/src/lib/components/TokenSelect/NoTokensAvailableOnNetwork.tsx deleted file mode 100644 index a9f0961475..0000000000 --- a/src/lib/components/TokenSelect/NoTokensAvailableOnNetwork.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Trans } from '@lingui/macro' -import { HelpCircle } from 'lib/icons' -import styled, { css, ThemedText } from 'lib/theme' - -import Column from '../Column' - -const HelpCircleIcon = styled(HelpCircle)` - height: 64px; - margin-bottom: 12px; - stroke: ${({ theme }) => theme.secondary}; - width: 64px; -` - -const wrapperCss = css` - display: flex; - height: 80%; - text-align: center; - width: 100%; -` - -export default function NoTokensAvailableOnNetwork() { - return ( - - - - No tokens are available on this network. Please switch to another network. - - - ) -} diff --git a/src/lib/components/TokenSelect/TokenBase.tsx b/src/lib/components/TokenSelect/TokenBase.tsx deleted file mode 100644 index 737c589613..0000000000 --- a/src/lib/components/TokenSelect/TokenBase.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Currency } from '@uniswap/sdk-core' -import styled, { ThemedText } from 'lib/theme' - -import Button from '../Button' -import Row from '../Row' -import TokenImg from '../TokenImg' - -const TokenButton = styled(Button)` - border-radius: ${({ theme }) => theme.borderRadius}em; - padding: 0.25em 0.75em 0.25em 0.25em; -` - -interface TokenBaseProps { - value: Currency - onClick: (value: Currency) => void -} - -export default function TokenBase({ value, onClick }: TokenBaseProps) { - return ( - onClick(value)}> - - - - {value.symbol} - - - - ) -} diff --git a/src/lib/components/TokenSelect/TokenButton.tsx b/src/lib/components/TokenSelect/TokenButton.tsx deleted file mode 100644 index 654798aa32..0000000000 --- a/src/lib/components/TokenSelect/TokenButton.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { Trans } from '@lingui/macro' -import { Currency } from '@uniswap/sdk-core' -import { ChevronDown } from 'lib/icons' -import styled, { css, ThemedText } from 'lib/theme' -import { useEffect, useMemo, useState } from 'react' - -import Button from '../Button' -import Row from '../Row' -import TokenImg from '../TokenImg' - -const transitionCss = css` - transition: background-color 0.125s linear, border-color 0.125s linear, filter 0.125s linear, width 0.125s ease-out; -` - -const StyledTokenButton = styled(Button)` - border-radius: ${({ theme }) => theme.borderRadius}em; - padding: 0.25em; - - :enabled { - ${({ transition }) => transition && transitionCss}; - } -` - -const TokenButtonRow = styled(Row)<{ empty: boolean; collapsed: boolean }>` - float: right; - height: 1.2em; - // max-width must have an absolute value in order to transition. - max-width: ${({ collapsed }) => (collapsed ? '1.2em' : '12em')}; - padding-left: ${({ empty }) => empty && 0.5}em; - width: fit-content; - overflow: hidden; - transition: max-width 0.25s linear; - - img { - min-width: 1.2em; - } -` - -interface TokenButtonProps { - value?: Currency - collapsed: boolean - disabled?: boolean - onClick: () => void -} - -export default function TokenButton({ value, collapsed, disabled, onClick }: TokenButtonProps) { - const buttonBackgroundColor = useMemo(() => (value ? 'interactive' : 'accent'), [value]) - const contentColor = useMemo(() => (value || disabled ? 'onInteractive' : 'onAccent'), [value, disabled]) - - // Transition the button only if transitioning from a disabled state. - // This makes initialization cleaner without adding distracting UX to normal swap flows. - const [shouldTransition, setShouldTransition] = useState(disabled) - useEffect(() => { - if (disabled) { - setShouldTransition(true) - } - }, [disabled]) - - // width must have an absolute value in order to transition, so it is taken from the row ref. - const [row, setRow] = useState(null) - const style = useMemo(() => { - if (!shouldTransition) return - return { width: row ? row.clientWidth + /* padding= */ 8 + /* border= */ 2 : undefined } - }, [row, shouldTransition]) - - return ( - setShouldTransition(false)} - > - - - {value ? ( - <> - - {value.symbol} - - ) : ( - Select a token - )} - - - - - ) -} diff --git a/src/lib/components/TokenSelect/TokenOptions.tsx b/src/lib/components/TokenSelect/TokenOptions.tsx deleted file mode 100644 index 2335d9452c..0000000000 --- a/src/lib/components/TokenSelect/TokenOptions.tsx +++ /dev/null @@ -1,254 +0,0 @@ -import { useLingui } from '@lingui/react' -import { Currency } from '@uniswap/sdk-core' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import useCurrencyBalance from 'lib/hooks/useCurrencyBalance' -import useNativeEvent from 'lib/hooks/useNativeEvent' -import useScrollbar from 'lib/hooks/useScrollbar' -import styled, { ThemedText } from 'lib/theme' -import { - ComponentClass, - CSSProperties, - forwardRef, - KeyboardEvent, - memo, - SyntheticEvent, - useCallback, - useEffect, - useImperativeHandle, - useRef, - useState, -} from 'react' -import AutoSizer from 'react-virtualized-auto-sizer' -import { areEqual, FixedSizeList, FixedSizeListProps } from 'react-window' -import { currencyId } from 'utils/currencyId' -import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' - -import { BaseButton } from '../Button' -import Column from '../Column' -import Row from '../Row' -import TokenImg from '../TokenImg' - -const TokenButton = styled(BaseButton)` - border-radius: 0; - outline: none; - padding: 0.5em 0.75em; -` - -const ITEM_SIZE = 56 -type ItemData = Currency[] -interface FixedSizeTokenList extends FixedSizeList, ComponentClass> {} -const TokenList = styled(FixedSizeList as unknown as FixedSizeTokenList)<{ - hover: number - scrollbar?: ReturnType -}>` - ${TokenButton}[data-index='${({ hover }) => hover}'] { - background-color: ${({ theme }) => theme.onHover(theme.module)}; - } - - ${({ scrollbar }) => scrollbar} - overscroll-behavior: none; // prevent Firefox's bouncy overscroll effect (because it does not trigger the scroll handler) -` -const OnHover = styled.div<{ hover: number }>` - background-color: ${({ theme }) => theme.onHover(theme.module)}; - height: ${ITEM_SIZE}px; - left: 0; - position: absolute; - top: ${({ hover }) => hover * ITEM_SIZE}px; - width: 100%; -` - -interface TokenOptionProps { - index: number - value: Currency - style: CSSProperties -} - -interface BubbledEvent extends SyntheticEvent { - index?: number - token?: Currency - ref?: HTMLButtonElement -} - -const TokenBalance = styled.div<{ isLoading: boolean }>` - background-color: ${({ theme, isLoading }) => isLoading && theme.secondary}; - border-radius: 0.25em; - padding: 0.375em 0; -` - -function TokenOption({ index, value, style }: TokenOptionProps) { - const { i18n } = useLingui() - const ref = useRef(null) - // Annotate the event to be handled later instead of passing in handlers to avoid rerenders. - // This prevents token logos from reloading and flashing on the screen. - const onEvent = (e: BubbledEvent) => { - e.index = index - e.token = value - e.ref = ref.current ?? undefined - } - - const { account } = useActiveWeb3React() - const balance = useCurrencyBalance(account, value) - - return ( - - - - - - - {value.symbol} - {value.name} - - - - {balance?.greaterThan(0) && formatCurrencyAmount(balance, 2, i18n.locale)} - - - - - ) -} - -const itemKey = (index: number, tokens: ItemData) => currencyId(tokens[index]) -const ItemRow = memo(function ItemRow({ - data: tokens, - index, - style, -}: { - data: ItemData - index: number - style: CSSProperties -}) { - return -}, -areEqual) - -interface TokenOptionsHandle { - onKeyDown: (e: KeyboardEvent) => void - blur: () => void -} - -interface TokenOptionsProps { - tokens: Currency[] - onSelect: (token: Currency) => void -} - -const TokenOptions = forwardRef(function TokenOptions( - { tokens, onSelect }: TokenOptionsProps, - ref -) { - const [focused, setFocused] = useState(false) - const [hover, setHover] = useState<{ index: number; currency?: Currency }>({ index: -1 }) - useEffect(() => { - setHover((hover) => { - const index = hover.currency ? tokens.indexOf(hover.currency) : -1 - return { index, currency: tokens[index] } - }) - }, [tokens]) - - const list = useRef(null) - const [element, setElement] = useState(null) - const scrollTo = useCallback( - (index: number | undefined) => { - if (index === undefined) return - list.current?.scrollToItem(index) - if (focused) { - element?.querySelector(`[data-index='${index}']`)?.focus() - } - setHover({ index, currency: tokens[index] }) - }, - [element, focused, tokens] - ) - - const onKeyDown = useCallback( - (e: KeyboardEvent) => { - if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { - if (e.key === 'ArrowDown' && hover.index < tokens.length - 1) { - scrollTo(hover.index + 1) - } else if (e.key === 'ArrowUp' && hover.index > 0) { - scrollTo(hover.index - 1) - } else if (e.key === 'ArrowUp' && hover.index === -1) { - scrollTo(tokens.length - 1) - } - e.preventDefault() - } - if (e.key === 'Enter' && hover.index !== -1) { - onSelect(tokens[hover.index]) - } - }, - [hover.index, onSelect, scrollTo, tokens] - ) - const blur = useCallback(() => setHover({ index: -1 }), []) - useImperativeHandle(ref, () => ({ onKeyDown, blur }), [blur, onKeyDown]) - - const onClick = useCallback(({ token }: BubbledEvent) => token && onSelect(token), [onSelect]) - const onFocus = useCallback( - ({ index }: BubbledEvent) => { - setFocused(true) - scrollTo(index) - }, - [scrollTo] - ) - const onBlur = useCallback(() => setFocused(false), []) - const onMouseMove = useCallback(({ index }: BubbledEvent) => scrollTo(index), [scrollTo]) - - const scrollbar = useScrollbar(element, { padded: true }) - const onHover = useRef(null) - // use native onscroll handler to capture Safari's bouncy overscroll effect - useNativeEvent( - element, - 'scroll', - useCallback(() => { - if (element && onHover.current) { - // must be set synchronously to avoid jank (avoiding useState) - onHover.current.style.marginTop = `${-element.scrollTop}px` - } - }, [element]) - ) - - return ( - - {/* OnHover is a workaround to Safari's incorrect (overflow: overlay) implementation */} - - - {({ height }) => ( - - {ItemRow} - - )} - - - ) -}) - -export default TokenOptions diff --git a/src/lib/components/TokenSelect/TokenOptionsSkeleton.tsx b/src/lib/components/TokenSelect/TokenOptionsSkeleton.tsx deleted file mode 100644 index 01b05675de..0000000000 --- a/src/lib/components/TokenSelect/TokenOptionsSkeleton.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import styled, { ThemedText } from 'lib/theme' - -import Column from '../Column' -import Row from '../Row' - -const Img = styled.div` - clip-path: circle(50%); - height: 1.5em; - width: 1.5em; -` -const Symbol = styled.div` - height: 0.75em; - width: 7em; -` -const Name = styled.div` - height: 0.5em; - width: 5.5em; -` -const Balance = styled.div` - padding: 0.375em 0; - width: 1.5em; -` -const TokenRow = styled.div` - outline: none; - padding: 0.6875em 0.75em; - - ${Img}, ${Symbol}, ${Name}, ${Balance} { - background-color: ${({ theme }) => theme.secondary}; - border-radius: 0.25em; - } -` - -function TokenOption() { - return ( - - - - - - - - - - - - - - - - - - - ) -} - -export default function TokenOptionsSkeleton() { - return ( - - - - - - - - ) -} diff --git a/src/lib/components/TokenSelect/index.tsx b/src/lib/components/TokenSelect/index.tsx deleted file mode 100644 index 73f73a6303..0000000000 --- a/src/lib/components/TokenSelect/index.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import { t, Trans } from '@lingui/macro' -import { Currency } from '@uniswap/sdk-core' -import { Header as DialogHeader } from 'lib/components/Dialog' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { useCurrencyBalances } from 'lib/hooks/useCurrencyBalance' -import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import useTokenList, { useIsTokenListLoaded, useQueryTokens } from 'lib/hooks/useTokenList' -import styled, { ThemedText } from 'lib/theme' -import { ElementRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' - -import Column from '../Column' -import Dialog from '../Dialog' -import { inputCss, StringInput } from '../Input' -import Row from '../Row' -import Rule from '../Rule' -import NoTokensAvailableOnNetwork from './NoTokensAvailableOnNetwork' -import TokenButton from './TokenButton' -import TokenOptions from './TokenOptions' -import TokenOptionsSkeleton from './TokenOptionsSkeleton' - -const SearchInput = styled(StringInput)` - ${inputCss} -` - -function usePrefetchBalances() { - const { account } = useActiveWeb3React() - const tokenList = useTokenList() - const prefetchedTokenList = useRef() - useCurrencyBalances(account, tokenList !== prefetchedTokenList.current ? tokenList : undefined) - prefetchedTokenList.current = tokenList -} - -function useAreBalancesLoaded(): boolean { - const { account } = useActiveWeb3React() - const tokens = useTokenList() - const native = useNativeCurrency() - const currencies = useMemo(() => [native, ...tokens], [native, tokens]) - const balances = useCurrencyBalances(account, currencies).filter(Boolean) - return !account || currencies.length === balances.length -} - -interface TokenSelectDialogProps { - value?: Currency - onSelect: (token: Currency) => void - onClose: () => void -} - -export function TokenSelectDialog({ value, onSelect, onClose }: TokenSelectDialogProps) { - const [query, setQuery] = useState('') - const list = useTokenList() - const tokens = useQueryTokens(query, list) - - const isTokenListLoaded = useIsTokenListLoaded() - const areBalancesLoaded = useAreBalancesLoaded() - const [isLoaded, setIsLoaded] = useState(isTokenListLoaded && areBalancesLoaded) - // Give the balance-less tokens a small block period to avoid layout thrashing from re-sorting. - useEffect(() => { - if (!isLoaded) { - const timeout = setTimeout(() => setIsLoaded(true), 250) - return () => clearTimeout(timeout) - } - return - }, [isLoaded]) - useEffect( - () => setIsLoaded(Boolean(query) || (isTokenListLoaded && areBalancesLoaded)), - [query, areBalancesLoaded, isTokenListLoaded] - ) - - const input = useRef(null) - useEffect(() => input.current?.focus({ preventScroll: true }), [input]) - - const [options, setOptions] = useState | null>(null) - - const { chainId } = useActiveWeb3React() - const listHasTokens = useMemo(() => list.some((token) => token.chainId === chainId), [chainId, list]) - - if (!listHasTokens && isLoaded) { - return ( - - Select a token} /> - - - ) - } - - return ( - - Select a token} /> - - - - - - - - - {isLoaded ? ( - tokens.length ? ( - - ) : ( - - - - No results found. - - - - ) - ) : ( - - )} - - ) -} - -interface TokenSelectProps { - value?: Currency - collapsed: boolean - disabled?: boolean - onSelect: (value: Currency) => void -} - -export default memo(function TokenSelect({ value, collapsed, disabled, onSelect }: TokenSelectProps) { - usePrefetchBalances() - - const [open, setOpen] = useState(false) - const onOpen = useCallback(() => setOpen(true), []) - const selectAndClose = useCallback( - (value: Currency) => { - onSelect(value) - setOpen(false) - }, - [onSelect, setOpen] - ) - return ( - <> - - {open && setOpen(false)} />} - - ) -}) diff --git a/src/lib/components/Tooltip.tsx b/src/lib/components/Tooltip.tsx deleted file mode 100644 index 7e50787c44..0000000000 --- a/src/lib/components/Tooltip.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Placement } from '@popperjs/core' -import useHasFocus from 'lib/hooks/useHasFocus' -import useHasHover from 'lib/hooks/useHasHover' -import { HelpCircle, Icon } from 'lib/icons' -import styled from 'lib/theme' -import { ComponentProps, ReactNode, useRef } from 'react' - -import { IconButton } from './Button' -import Popover from './Popover' - -export function useTooltip(tooltip: Node | null | undefined): boolean { - const hover = useHasHover(tooltip) - const focus = useHasFocus(tooltip) - return hover || focus -} - -const IconTooltip = styled(IconButton)` - cursor: help; -` - -interface TooltipProps { - icon?: Icon - iconProps?: ComponentProps - children: ReactNode - placement?: Placement - offset?: number - contained?: true -} - -export default function Tooltip({ - icon: Icon = HelpCircle, - iconProps, - children, - placement = 'auto', - offset, - contained, -}: TooltipProps) { - const tooltip = useRef(null) - const showTooltip = useTooltip(tooltip.current) - return ( - - - - ) -} diff --git a/src/lib/components/Wallet.tsx b/src/lib/components/Wallet.tsx deleted file mode 100644 index ae03acfaf2..0000000000 --- a/src/lib/components/Wallet.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Trans } from '@lingui/macro' -import { Wallet as WalletIcon } from 'lib/icons' -import { ThemedText } from 'lib/theme' - -import { TextButton } from './Button' -import Row from './Row' - -interface WalletProps { - disabled?: boolean - onClick?: () => void -} - -export default function Wallet({ disabled, onClick }: WalletProps) { - return disabled ? ( - - - - - Connect your wallet - - - - ) : null -} diff --git a/src/lib/components/Widget.tsx b/src/lib/components/Widget.tsx deleted file mode 100644 index 4868a64fbf..0000000000 --- a/src/lib/components/Widget.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { JsonRpcProvider } from '@ethersproject/providers' -import { TokenInfo } from '@uniswap/token-lists' -import { Provider as Eip1193Provider } from '@web3-react/types' -import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales' -import { Provider as AtomProvider } from 'jotai' -import { TransactionsUpdater } from 'lib/hooks/transactions' -import { ActiveWeb3Provider } from 'lib/hooks/useActiveWeb3React' -import { BlockNumberProvider } from 'lib/hooks/useBlockNumber' -import { TokenListProvider } from 'lib/hooks/useTokenList' -import { Provider as I18nProvider } from 'lib/i18n' -import { MulticallUpdater, store as multicallStore } from 'lib/state/multicall' -import styled, { keyframes, Theme, ThemeProvider } from 'lib/theme' -import { UNMOUNTING } from 'lib/utils/animations' -import { PropsWithChildren, StrictMode, useMemo, useState } from 'react' -import { Provider as ReduxProvider } from 'react-redux' - -import { Modal, Provider as DialogProvider } from './Dialog' -import ErrorBoundary, { ErrorHandler } from './Error/ErrorBoundary' - -const WidgetWrapper = styled.div<{ width?: number | string }>` - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - background-color: ${({ theme }) => theme.container}; - border-radius: ${({ theme }) => theme.borderRadius}em; - box-sizing: border-box; - color: ${({ theme }) => theme.primary}; - display: flex; - flex-direction: column; - font-feature-settings: 'ss01' on, 'ss02' on, 'cv01' on, 'cv03' on; - font-size: 16px; - font-smooth: always; - font-variant: none; - height: 360px; - min-width: 300px; - padding: 0.25em; - position: relative; - user-select: none; - width: ${({ width }) => width && (isNaN(Number(width)) ? width : `${width}px`)}; - - * { - box-sizing: border-box; - font-family: ${({ theme }) => (typeof theme.fontFamily === 'string' ? theme.fontFamily : theme.fontFamily.font)}; - - @supports (font-variation-settings: normal) { - font-family: ${({ theme }) => (typeof theme.fontFamily === 'string' ? undefined : theme.fontFamily.variable)}; - } - } -` - -const slideIn = keyframes` - from { - transform: translateY(calc(100% - 0.25em)); - } -` -const slideOut = keyframes` - to { - transform: translateY(calc(100% - 0.25em)); - } -` - -const DialogWrapper = styled.div` - border-radius: ${({ theme }) => theme.borderRadius * 0.75}em; - height: calc(100% - 0.5em); - left: 0; - margin: 0.25em; - overflow: hidden; - position: absolute; - top: 0; - width: calc(100% - 0.5em); - - @supports (overflow: clip) { - overflow: clip; - } - - ${Modal} { - animation: ${slideIn} 0.25s ease-in; - - &.${UNMOUNTING} { - animation: ${slideOut} 0.25s ease-out; - } - } -` - -export type WidgetProps = { - theme?: Theme - locale?: SupportedLocale - provider?: Eip1193Provider | JsonRpcProvider - jsonRpcEndpoint?: string | JsonRpcProvider - tokenList?: string | TokenInfo[] - width?: string | number - dialog?: HTMLElement | null - className?: string - onError?: ErrorHandler -} - -export default function Widget(props: PropsWithChildren) { - const { children, theme, provider, jsonRpcEndpoint, dialog: userDialog, className, onError } = props - const width = useMemo(() => { - if (props.width && props.width < 300) { - console.warn(`Widget width must be at least 300px (you set it to ${props.width}). Falling back to 300px.`) - return 300 - } - return props.width ?? 360 - }, [props.width]) - const locale = useMemo(() => { - if (props.locale && ![...SUPPORTED_LOCALES, 'pseudo'].includes(props.locale)) { - console.warn(`Unsupported locale: ${props.locale}. Falling back to ${DEFAULT_LOCALE}.`) - return DEFAULT_LOCALE - } - return props.locale ?? DEFAULT_LOCALE - }, [props.locale]) - - const [dialog, setDialog] = useState(null) - return ( - - - - - - - - - - - - - - {children} - - - - - - - - - - - ) -} diff --git a/src/lib/cosmos.decorator.tsx b/src/lib/cosmos.decorator.tsx deleted file mode 100644 index 7da44ce9e3..0000000000 --- a/src/lib/cosmos.decorator.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { JSXElementConstructor, ReactElement } from 'react' - -import Row from './components/Row' -import Widget from './cosmos/components/Widget' - -export default function WidgetDecorator({ - children, -}: { - children: ReactElement> -}) { - return ( - - {children} - - ) -} diff --git a/src/lib/cosmos/components/Widget.tsx b/src/lib/cosmos/components/Widget.tsx deleted file mode 100644 index 865f7df264..0000000000 --- a/src/lib/cosmos/components/Widget.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { tokens } from '@uniswap/default-token-list' -import { initializeConnector } from '@web3-react/core' -import { MetaMask } from '@web3-react/metamask' -import { Connector } from '@web3-react/types' -import { WalletConnect } from '@web3-react/walletconnect' -import { SupportedChainId } from 'constants/chains' -import { INFURA_NETWORK_URLS } from 'constants/infura' -import { DEFAULT_LOCALE, SUPPORTED_LOCALES } from 'constants/locales' -import Widget from 'lib/components/Widget' -import { darkTheme, defaultTheme, lightTheme } from 'lib/theme' -import { ReactNode, useEffect, useState } from 'react' -import { useSelect, useValue } from 'react-cosmos/fixture' - -const [metaMask] = initializeConnector((actions) => new MetaMask(actions)) -const [walletConnect] = initializeConnector( - (actions) => new WalletConnect(actions, { rpc: INFURA_NETWORK_URLS }) -) - -export default function Wrapper({ children }: { children: ReactNode }) { - const [width] = useValue('width', { defaultValue: 360 }) - const [locale] = useSelect('locale', { - defaultValue: DEFAULT_LOCALE, - options: ['fa-KE (unsupported)', 'pseudo', ...SUPPORTED_LOCALES], - }) - const [darkMode] = useValue('dark mode', { defaultValue: false }) - const [theme, setTheme] = useValue('theme', { defaultValue: { ...defaultTheme, ...lightTheme } }) - useEffect(() => { - setTheme({ ...defaultTheme, ...(darkMode ? darkTheme : lightTheme) }) - }, [darkMode, setTheme]) - - const NO_JSON_RPC = 'None' - const [jsonRpcEndpoint] = useSelect('JSON-RPC', { - defaultValue: INFURA_NETWORK_URLS[SupportedChainId.MAINNET], - options: [NO_JSON_RPC, ...Object.values(INFURA_NETWORK_URLS).sort()], - }) - - const NO_CONNECTOR = 'None' - const META_MASK = 'MetaMask' - const WALLET_CONNECT = 'WalletConnect' - const [connectorType] = useSelect('Provider', { - defaultValue: NO_CONNECTOR, - options: [NO_CONNECTOR, META_MASK, WALLET_CONNECT], - }) - const [connector, setConnector] = useState() - useEffect(() => { - let stale = false - activateConnector(connectorType) - return () => { - stale = true - } - - async function activateConnector(connectorType: 'None' | 'MetaMask' | 'WalletConnect') { - let connector: Connector - switch (connectorType) { - case META_MASK: - await metaMask.activate() - connector = metaMask - break - case WALLET_CONNECT: - await walletConnect.activate() - connector = walletConnect - } - if (!stale) { - setConnector((oldConnector) => { - oldConnector?.deactivate?.() - return connector - }) - } - } - }, [connectorType]) - - return ( - - {children} - - ) -} diff --git a/src/lib/css/loading.ts b/src/lib/css/loading.ts deleted file mode 100644 index bf807165eb..0000000000 --- a/src/lib/css/loading.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { css } from 'lib/theme' - -export const loadingOpacity = 0.6 - -export const loadingCss = css` - filter: grayscale(1); - opacity: ${loadingOpacity}; -` - -// need to use isLoading as `loading` is a reserved prop -export const loadingTransitionCss = css<{ isLoading: boolean }>` - opacity: ${({ isLoading }) => isLoading && loadingOpacity}; - transition: color 0.125s linear, opacity ${({ isLoading }) => (isLoading ? 0 : 0.25)}s ease-in-out; -` diff --git a/src/lib/errors.ts b/src/lib/errors.ts deleted file mode 100644 index 6245f8bebd..0000000000 --- a/src/lib/errors.ts +++ /dev/null @@ -1,6 +0,0 @@ -export class IntegrationError extends Error { - constructor(message: string) { - super(message) - this.name = 'Integration Error' - } -} diff --git a/src/lib/hooks/routing/useClientSideSmartOrderRouterTrade.ts b/src/lib/hooks/routing/useClientSideSmartOrderRouterTrade.ts deleted file mode 100644 index 9c66860758..0000000000 --- a/src/lib/hooks/routing/useClientSideSmartOrderRouterTrade.ts +++ /dev/null @@ -1,151 +0,0 @@ -import 'setimmediate' - -import { Protocol } from '@uniswap/router-sdk' -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import { SupportedChainId } from 'constants/chains' -import useDebounce from 'hooks/useDebounce' -import { useStablecoinAmountFromFiatValue } from 'hooks/useUSDCPrice' -import { useCallback, useMemo } from 'react' -import { GetQuoteResult, InterfaceTrade, TradeState } from 'state/routing/types' -import { computeRoutes, transformRoutesToTrade } from 'state/routing/utils' - -import useWrapCallback, { WrapType } from '../swap/useWrapCallback' -import useActiveWeb3React from '../useActiveWeb3React' -import { useGetIsValidBlock } from '../useIsValidBlock' -import usePoll from '../usePoll' -import { useRoutingAPIArguments } from './useRoutingAPIArguments' - -/** - * Reduces client-side latency by increasing the minimum percentage of the input token to use for each route in a split route while SOR is used client-side. - * Defaults are defined in https://github.com/Uniswap/smart-order-router/blob/309e6f6603984d3b5aef0733b0cfaf129c29f602/src/routers/alpha-router/config.ts#L83. - */ -const DistributionPercents: { [key: number]: number } = { - [SupportedChainId.MAINNET]: 10, - [SupportedChainId.OPTIMISM]: 10, - [SupportedChainId.OPTIMISTIC_KOVAN]: 10, - [SupportedChainId.ARBITRUM_ONE]: 25, - [SupportedChainId.ARBITRUM_RINKEBY]: 25, -} -const DEFAULT_DISTRIBUTION_PERCENT = 10 -function getConfig(chainId: SupportedChainId | undefined) { - return { - // Limit to only V2 and V3. - protocols: [Protocol.V2, Protocol.V3], - distributionPercent: (chainId && DistributionPercents[chainId]) ?? DEFAULT_DISTRIBUTION_PERCENT, - } -} - -export default function useClientSideSmartOrderRouterTrade( - tradeType: TTradeType, - amountSpecified?: CurrencyAmount, - otherCurrency?: Currency -): { - state: TradeState - trade: InterfaceTrade | undefined -} { - const amount = useMemo(() => amountSpecified?.asFraction, [amountSpecified]) - const [currencyIn, currencyOut] = - tradeType === TradeType.EXACT_INPUT - ? [amountSpecified?.currency, otherCurrency] - : [otherCurrency, amountSpecified?.currency] - - // Debounce is used to prevent excessive requests to SOR, as it is data intensive. - // Fast user actions (ie updating the input) should be debounced, but currency changes should not. - const [debouncedAmount, debouncedCurrencyIn, debouncedCurrencyOut] = useDebounce( - useMemo(() => [amount, currencyIn, currencyOut], [amount, currencyIn, currencyOut]), - 200 - ) - const isDebouncing = - amount !== debouncedAmount && currencyIn === debouncedCurrencyIn && currencyOut === debouncedCurrencyOut - - const queryArgs = useRoutingAPIArguments({ - tokenIn: currencyIn, - tokenOut: currencyOut, - amount: amountSpecified, - tradeType, - useClientSideRouter: true, - }) - const chainId = amountSpecified?.currency.chainId - const { library } = useActiveWeb3React() - const params = useMemo(() => chainId && library && { chainId, provider: library }, [chainId, library]) - const config = useMemo(() => getConfig(chainId), [chainId]) - const { type: wrapType } = useWrapCallback() - - const getQuoteResult = useCallback(async (): Promise<{ data?: GetQuoteResult; error?: unknown }> => { - if (wrapType !== WrapType.NONE) return { error: undefined } - if (!queryArgs || !params) return { error: undefined } - try { - // Lazy-load the smart order router to improve initial pageload times. - const quoteResult = await ( - await import('./clientSideSmartOrderRouter') - ).getClientSideQuote(queryArgs, params, config) - - // There is significant post-fetch processing, so delay a tick to prevent dropped frames. - // This is only important in the context of integrations - if we control the whole site, - // then we can afford to drop a few frames. - return new Promise((resolve) => setImmediate(() => resolve(quoteResult))) - } catch { - return { error: true } - } - }, [config, params, queryArgs, wrapType]) - - const getIsValidBlock = useGetIsValidBlock() - const { data: quoteResult, error } = usePoll(getQuoteResult, JSON.stringify(queryArgs), { - debounce: isDebouncing, - isStale: useCallback(({ data }) => !getIsValidBlock(Number(data?.blockNumber) || 0), [getIsValidBlock]), - }) ?? { - error: undefined, - } - const isValid = getIsValidBlock(Number(quoteResult?.blockNumber) || 0) - - const route = useMemo( - () => computeRoutes(currencyIn, currencyOut, tradeType, quoteResult), - [currencyIn, currencyOut, quoteResult, tradeType] - ) - const gasUseEstimateUSD = useStablecoinAmountFromFiatValue(quoteResult?.gasUseEstimateUSD) ?? null - const trade = useMemo(() => { - if (route) { - try { - return route && transformRoutesToTrade(route, tradeType, gasUseEstimateUSD) - } catch (e: unknown) { - console.debug('transformRoutesToTrade failed: ', e) - } - } - return - }, [gasUseEstimateUSD, route, tradeType]) - - return useMemo(() => { - if (!currencyIn || !currencyOut) { - return { state: TradeState.INVALID, trade: undefined } - } - - if (!trade && !error) { - if (isDebouncing) { - return { state: TradeState.SYNCING, trade: undefined } - } else if (!isValid) { - return { state: TradeState.LOADING, trade: undefined } - } - } - - let otherAmount = undefined - if (quoteResult) { - switch (tradeType) { - case TradeType.EXACT_INPUT: - otherAmount = CurrencyAmount.fromRawAmount(currencyOut, quoteResult.quote) - break - case TradeType.EXACT_OUTPUT: - otherAmount = CurrencyAmount.fromRawAmount(currencyIn, quoteResult.quote) - break - } - } - - if (error || !otherAmount || !route || route.length === 0) { - return { state: TradeState.NO_ROUTE_FOUND, trade: undefined } - } - - if (trade) { - return { state: TradeState.VALID, trade } - } - return { state: TradeState.INVALID, trade: undefined } - }, [currencyIn, currencyOut, trade, error, isValid, quoteResult, route, isDebouncing, tradeType]) -} diff --git a/src/lib/hooks/swap/index.ts b/src/lib/hooks/swap/index.ts deleted file mode 100644 index 5f02f9db27..0000000000 --- a/src/lib/hooks/swap/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Currency, CurrencyAmount } from '@uniswap/sdk-core' -import { useAtom } from 'jotai' -import { useAtomValue, useUpdateAtom } from 'jotai/utils' -import { pickAtom } from 'lib/state/atoms' -import { Field, swapAtom } from 'lib/state/swap' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { useCallback, useMemo } from 'react' -export { default as useSwapInfo } from './useSwapInfo' - -function otherField(field: Field) { - switch (field) { - case Field.INPUT: - return Field.OUTPUT - break - case Field.OUTPUT: - return Field.INPUT - break - } -} - -export function useSwitchSwapCurrencies() { - const update = useUpdateAtom(swapAtom) - return useCallback(() => { - update((swap) => { - const oldOutput = swap[Field.OUTPUT] - swap[Field.OUTPUT] = swap[Field.INPUT] - swap[Field.INPUT] = oldOutput - switch (swap.independentField) { - case Field.INPUT: - swap.independentField = Field.OUTPUT - break - case Field.OUTPUT: - swap.independentField = Field.INPUT - break - } - }) - }, [update]) -} - -export function useSwapCurrency(field: Field): [Currency | undefined, (currency?: Currency) => void] { - const atom = useMemo(() => pickAtom(swapAtom, field), [field]) - const otherAtom = useMemo(() => pickAtom(swapAtom, otherField(field)), [field]) - const [currency, setCurrency] = useAtom(atom) - const otherCurrency = useAtomValue(otherAtom) - const switchSwapCurrencies = useSwitchSwapCurrencies() - const setOrSwitchCurrency = useCallback( - (currency?: Currency) => { - if (currency === otherCurrency) { - switchSwapCurrencies() - } else { - setCurrency(currency) - } - }, - [otherCurrency, setCurrency, switchSwapCurrencies] - ) - return [currency, setOrSwitchCurrency] -} - -const independentFieldAtom = pickAtom(swapAtom, 'independentField') - -export function useIsSwapFieldIndependent(field: Field): boolean { - const independentField = useAtomValue(independentFieldAtom) - return independentField === field -} - -const amountAtom = pickAtom(swapAtom, 'amount') - -// check if any amount has been entered by user -export function useIsAmountPopulated() { - return Boolean(useAtomValue(amountAtom)) -} - -export function useSwapAmount(field: Field): [string | undefined, (amount: string) => void] { - const amount = useAtomValue(amountAtom) - const isFieldIndependent = useIsSwapFieldIndependent(field) - const value = isFieldIndependent ? amount : undefined - const updateSwap = useUpdateAtom(swapAtom) - const updateAmount = useCallback( - (amount: string) => - updateSwap((swap) => { - swap.independentField = field - swap.amount = amount - }), - [field, updateSwap] - ) - return [value, updateAmount] -} - -export function useSwapCurrencyAmount(field: Field): CurrencyAmount | undefined { - const isFieldIndependent = useIsSwapFieldIndependent(field) - const isAmountPopulated = useIsAmountPopulated() - const [swapAmount] = useSwapAmount(field) - const [swapCurrency] = useSwapCurrency(field) - const currencyAmount = useMemo(() => tryParseCurrencyAmount(swapAmount, swapCurrency), [swapAmount, swapCurrency]) - if (isFieldIndependent && isAmountPopulated) { - return currencyAmount - } - return -} diff --git a/src/lib/hooks/swap/useBestTrade.ts b/src/lib/hooks/swap/useBestTrade.ts deleted file mode 100644 index 69385f0425..0000000000 --- a/src/lib/hooks/swap/useBestTrade.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import { useClientSideV3Trade } from 'hooks/useClientSideV3Trade' -import useLast from 'hooks/useLast' -import { useMemo } from 'react' -import { InterfaceTrade, TradeState } from 'state/routing/types' - -import useClientSideSmartOrderRouterTrade from '../routing/useClientSideSmartOrderRouterTrade' - -export const INVALID_TRADE = { state: TradeState.INVALID, trade: undefined } - -/** - * Returns the best v2+v3 trade for a desired swap. - * @param tradeType whether the swap is an exact in/out - * @param amountSpecified the exact amount to swap in/out - * @param otherCurrency the desired output/payment currency - */ -export function useBestTrade( - tradeType: TradeType, - amountSpecified?: CurrencyAmount, - otherCurrency?: Currency -): { - state: TradeState - trade: InterfaceTrade | undefined -} { - const clientSORTradeObject = useClientSideSmartOrderRouterTrade(tradeType, amountSpecified, otherCurrency) - - // Use a simple client side logic as backup if SOR is not available. - const useFallback = - clientSORTradeObject.state === TradeState.NO_ROUTE_FOUND || clientSORTradeObject.state === TradeState.INVALID - const fallbackTradeObject = useClientSideV3Trade( - tradeType, - useFallback ? amountSpecified : undefined, - useFallback ? otherCurrency : undefined - ) - - const tradeObject = useFallback ? fallbackTradeObject : clientSORTradeObject - const lastTrade = useLast(tradeObject.trade, Boolean) ?? undefined - - // Return the last trade while syncing/loading to avoid jank from clearing the last trade while loading. - // If the trade is unsettled and not stale, return the last trade as a placeholder during settling. - return useMemo(() => { - const { state, trade } = tradeObject - // If the trade is in a settled state, return it. - if (state === TradeState.INVALID) return INVALID_TRADE - if ((state !== TradeState.LOADING && state !== TradeState.SYNCING) || trade) return tradeObject - - const [currencyIn, currencyOut] = - tradeType === TradeType.EXACT_INPUT - ? [amountSpecified?.currency, otherCurrency] - : [otherCurrency, amountSpecified?.currency] - - // If the trade currencies have switched, consider it stale - do not return the last trade. - const isStale = - (currencyIn && !lastTrade?.inputAmount?.currency.equals(currencyIn)) || - (currencyOut && !lastTrade?.outputAmount?.currency.equals(currencyOut)) - if (isStale) return tradeObject - - return { state, trade: lastTrade } - }, [amountSpecified?.currency, lastTrade, otherCurrency, tradeObject, tradeType]) -} diff --git a/src/lib/hooks/swap/useSwapApproval.ts b/src/lib/hooks/swap/useSwapApproval.ts index 154144fa16..1508c0bfe8 100644 --- a/src/lib/hooks/swap/useSwapApproval.ts +++ b/src/lib/hooks/swap/useSwapApproval.ts @@ -4,9 +4,7 @@ import { Pair, Route as V2Route, Trade as V2Trade } from '@uniswap/v2-sdk' import { Pool, Route as V3Route, Trade as V3Trade } from '@uniswap/v3-sdk' import { SWAP_ROUTER_ADDRESSES, V2_ROUTER_ADDRESS, V3_ROUTER_ADDRESS } from 'constants/addresses' import useActiveWeb3React from 'hooks/useActiveWeb3React' -import { useERC20PermitFromTrade, UseERC20PermitState } from 'hooks/useERC20Permit' -import useTransactionDeadline from 'lib/hooks/useTransactionDeadline' -import { useCallback, useMemo } from 'react' +import { useMemo } from 'react' import { getTxOptimizedSwapRouter, SwapRouterVersion } from 'utils/getTxOptimizedSwapRouter' import { ApprovalState, useApproval, useApprovalStateForSpender } from '../useApproval' @@ -131,78 +129,3 @@ export function useSwapApprovalOptimizedTrade( } }, [trade, optimizedSwapRouter]) } - -export enum ApproveOrPermitState { - REQUIRES_APPROVAL, - PENDING_APPROVAL, - REQUIRES_SIGNATURE, - PENDING_SIGNATURE, - APPROVED, -} - -/** - * Returns all relevant statuses and callback functions for approvals. - * Considers both standard approval and ERC20 permit. - */ -export const useApproveOrPermit = ( - trade: - | V2Trade - | V3Trade - | Trade - | undefined, - allowedSlippage: Percent, - useIsPendingApproval: (token?: Token, spender?: string) => boolean, - amount?: CurrencyAmount // defaults to trade.maximumAmountIn(allowedSlippage) -) => { - const deadline = useTransactionDeadline() - - // Check approvals on ERC20 contract based on amount. - const [approval, getApproval] = useSwapApproval(trade, allowedSlippage, useIsPendingApproval, amount) - - // Check status of permit and whether token supports it. - const { - state: signatureState, - signatureData, - gatherPermitSignature, - } = useERC20PermitFromTrade(trade, allowedSlippage, deadline) - - // If permit is supported, trigger a signature, if not create approval transaction. - const handleApproveOrPermit = useCallback(async () => { - try { - if (signatureState === UseERC20PermitState.NOT_SIGNED && gatherPermitSignature) { - try { - return await gatherPermitSignature() - } catch (error) { - // Try to approve if gatherPermitSignature failed for any reason other than the user rejecting it. - if (error?.code !== 4001) { - return await getApproval() - } - } - } else { - return await getApproval() - } - } catch (e) { - // Swallow approval errors - user rejections do not need to be displayed. - } - }, [signatureState, gatherPermitSignature, getApproval]) - - const approvalState = useMemo(() => { - if (approval === ApprovalState.PENDING) { - return ApproveOrPermitState.PENDING_APPROVAL - } else if (signatureState === UseERC20PermitState.LOADING) { - return ApproveOrPermitState.PENDING_SIGNATURE - } else if (approval !== ApprovalState.NOT_APPROVED || signatureState === UseERC20PermitState.SIGNED) { - return ApproveOrPermitState.APPROVED - } else if (gatherPermitSignature) { - return ApproveOrPermitState.REQUIRES_SIGNATURE - } else { - return ApproveOrPermitState.REQUIRES_APPROVAL - } - }, [approval, gatherPermitSignature, signatureState]) - - return { - approvalState, - signatureData, - handleApproveOrPermit, - } -} diff --git a/src/lib/hooks/swap/useSwapInfo.tsx b/src/lib/hooks/swap/useSwapInfo.tsx deleted file mode 100644 index e1b20727c0..0000000000 --- a/src/lib/hooks/swap/useSwapInfo.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import { useAtomValue } from 'jotai/utils' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { useCurrencyBalances } from 'lib/hooks/useCurrencyBalance' -import useSlippage, { DEFAULT_SLIPPAGE, Slippage } from 'lib/hooks/useSlippage' -import useUSDCPriceImpact, { PriceImpact } from 'lib/hooks/useUSDCPriceImpact' -import { Field, swapAtom } from 'lib/state/swap' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { createContext, PropsWithChildren, useContext, useMemo } from 'react' -import { InterfaceTrade, TradeState } from 'state/routing/types' - -import { INVALID_TRADE, useBestTrade } from './useBestTrade' -import useWrapCallback, { WrapType } from './useWrapCallback' - -interface SwapField { - currency?: Currency - amount?: CurrencyAmount - balance?: CurrencyAmount - usdc?: CurrencyAmount -} - -interface SwapInfo { - [Field.INPUT]: SwapField - [Field.OUTPUT]: SwapField - trade: { - trade?: InterfaceTrade - state: TradeState - } - slippage: Slippage - impact?: PriceImpact -} - -// from the current swap inputs, compute the best trade and return it. -function useComputeSwapInfo(): SwapInfo { - const { type: wrapType } = useWrapCallback() - const isWrapping = wrapType === WrapType.WRAP || wrapType === WrapType.UNWRAP - const { independentField, amount, [Field.INPUT]: currencyIn, [Field.OUTPUT]: currencyOut } = useAtomValue(swapAtom) - const isExactIn = independentField === Field.INPUT - - const parsedAmount = useMemo( - () => tryParseCurrencyAmount(amount, (isExactIn ? currencyIn : currencyOut) ?? undefined), - [amount, isExactIn, currencyIn, currencyOut] - ) - const hasAmounts = currencyIn && currencyOut && parsedAmount && !isWrapping - const trade = useBestTrade( - isExactIn ? TradeType.EXACT_INPUT : TradeType.EXACT_OUTPUT, - hasAmounts ? parsedAmount : undefined, - hasAmounts ? (isExactIn ? currencyOut : currencyIn) : undefined - ) - - const amountIn = useMemo( - () => (isWrapping || isExactIn ? parsedAmount : trade.trade?.inputAmount), - [isExactIn, isWrapping, parsedAmount, trade.trade?.inputAmount] - ) - const amountOut = useMemo( - () => (isWrapping || !isExactIn ? parsedAmount : trade.trade?.outputAmount), - [isExactIn, isWrapping, parsedAmount, trade.trade?.outputAmount] - ) - - const { account } = useActiveWeb3React() - const [balanceIn, balanceOut] = useCurrencyBalances( - account, - useMemo(() => [currencyIn, currencyOut], [currencyIn, currencyOut]) - ) - - // Compute slippage and impact off of the trade so that it refreshes with the trade. - // (Using amountIn/amountOut would show (incorrect) intermediate values.) - const slippage = useSlippage(trade.trade) - const { inputUSDC, outputUSDC, impact } = useUSDCPriceImpact(trade.trade?.inputAmount, trade.trade?.outputAmount) - - return useMemo( - () => ({ - [Field.INPUT]: { - currency: currencyIn, - amount: amountIn, - balance: balanceIn, - usdc: inputUSDC, - }, - [Field.OUTPUT]: { - currency: currencyOut, - amount: amountOut, - balance: balanceOut, - usdc: outputUSDC, - }, - trade, - slippage, - impact, - }), - [ - amountIn, - amountOut, - balanceIn, - balanceOut, - currencyIn, - currencyOut, - impact, - inputUSDC, - outputUSDC, - slippage, - trade, - ] - ) -} - -const DEFAULT_SWAP_INFO: SwapInfo = { - [Field.INPUT]: {}, - [Field.OUTPUT]: {}, - trade: INVALID_TRADE, - slippage: DEFAULT_SLIPPAGE, -} - -const SwapInfoContext = createContext(DEFAULT_SWAP_INFO) - -export function SwapInfoProvider({ children, disabled }: PropsWithChildren<{ disabled?: boolean }>) { - const swapInfo = useComputeSwapInfo() - if (disabled) { - return {children} - } - return {children} -} - -/** Requires that SwapInfoUpdater be installed in the DOM tree. **/ -export default function useSwapInfo(): SwapInfo { - return useContext(SwapInfoContext) -} diff --git a/src/lib/hooks/swap/useSyncConvenienceFee.ts b/src/lib/hooks/swap/useSyncConvenienceFee.ts deleted file mode 100644 index a1b907f200..0000000000 --- a/src/lib/hooks/swap/useSyncConvenienceFee.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Percent } from '@uniswap/sdk-core' -import useActiveWeb3React from 'hooks/useActiveWeb3React' -import { useUpdateAtom } from 'jotai/utils' -import { feeOptionsAtom } from 'lib/state/swap' -import { useEffect } from 'react' - -export interface FeeOptions { - convenienceFee?: number - convenienceFeeRecipient?: string | string | { [chainId: number]: string } -} - -export default function useSyncConvenienceFee({ convenienceFee, convenienceFeeRecipient }: FeeOptions) { - const { chainId } = useActiveWeb3React() - const updateFeeOptions = useUpdateAtom(feeOptionsAtom) - - useEffect(() => { - if (convenienceFee && convenienceFeeRecipient) { - if (typeof convenienceFeeRecipient === 'string') { - updateFeeOptions({ - fee: new Percent(convenienceFee, 10_000), - recipient: convenienceFeeRecipient, - }) - return - } - if (chainId && convenienceFeeRecipient[chainId]) { - updateFeeOptions({ - fee: new Percent(convenienceFee, 10_000), - recipient: convenienceFeeRecipient[chainId], - }) - return - } - } - updateFeeOptions(undefined) - }, [chainId, convenienceFee, convenienceFeeRecipient, updateFeeOptions]) -} diff --git a/src/lib/hooks/swap/useSyncTokenDefaults.ts b/src/lib/hooks/swap/useSyncTokenDefaults.ts deleted file mode 100644 index 6faf422465..0000000000 --- a/src/lib/hooks/swap/useSyncTokenDefaults.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Currency } from '@uniswap/sdk-core' -import { nativeOnChain } from 'constants/tokens' -import { useUpdateAtom } from 'jotai/utils' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { useToken } from 'lib/hooks/useCurrency' -import useNativeCurrency from 'lib/hooks/useNativeCurrency' -import { Field, Swap, swapAtom } from 'lib/state/swap' -import { useCallback, useRef } from 'react' - -import useOnSupportedNetwork from '../useOnSupportedNetwork' -import { useIsTokenListLoaded } from '../useTokenList' - -export type DefaultAddress = string | { [chainId: number]: string | 'NATIVE' } | 'NATIVE' - -export interface TokenDefaults { - defaultInputTokenAddress?: DefaultAddress - defaultInputAmount?: number | string - defaultOutputTokenAddress?: DefaultAddress - defaultOutputAmount?: number | string -} - -function useDefaultToken( - defaultAddress: DefaultAddress | undefined, - chainId: number | undefined -): Currency | undefined { - let address = undefined - if (typeof defaultAddress === 'string') { - address = defaultAddress - } else if (typeof defaultAddress === 'object' && chainId) { - address = defaultAddress[chainId] - } - const token = useToken(address) - - const onSupportedNetwork = useOnSupportedNetwork() - - // Only use native currency if chain ID is in supported chains. ExtendedEther will error otherwise. - if (chainId && address === 'NATIVE' && onSupportedNetwork) { - return nativeOnChain(chainId) - } - return token ?? undefined -} - -export default function useSyncTokenDefaults({ - defaultInputTokenAddress, - defaultInputAmount, - defaultOutputTokenAddress, - defaultOutputAmount, -}: TokenDefaults) { - const updateSwap = useUpdateAtom(swapAtom) - const { chainId } = useActiveWeb3React() - const onSupportedNetwork = useOnSupportedNetwork() - const nativeCurrency = useNativeCurrency() - const defaultOutputToken = useDefaultToken(defaultOutputTokenAddress, chainId) - const defaultInputToken = - useDefaultToken(defaultInputTokenAddress, chainId) ?? - // Default the input token to the native currency if it is not the output token. - (defaultOutputToken !== nativeCurrency && onSupportedNetwork ? nativeCurrency : undefined) - - const setToDefaults = useCallback(() => { - const defaultSwapState: Swap = { - amount: '', - [Field.INPUT]: defaultInputToken, - [Field.OUTPUT]: defaultOutputToken, - independentField: Field.INPUT, - } - if (defaultInputToken && defaultInputAmount) { - defaultSwapState.amount = defaultInputAmount.toString() - } else if (defaultOutputToken && defaultOutputAmount) { - defaultSwapState.independentField = Field.OUTPUT - defaultSwapState.amount = defaultOutputAmount.toString() - } - updateSwap((swap) => ({ ...swap, ...defaultSwapState })) - }, [defaultInputAmount, defaultInputToken, defaultOutputAmount, defaultOutputToken, updateSwap]) - - const lastChainId = useRef(undefined) - const shouldSync = useIsTokenListLoaded() && chainId && chainId !== lastChainId.current - if (shouldSync) { - setToDefaults() - lastChainId.current = chainId - } -} diff --git a/src/lib/hooks/swap/useWrapCallback.tsx b/src/lib/hooks/swap/useWrapCallback.tsx deleted file mode 100644 index 82163df46e..0000000000 --- a/src/lib/hooks/swap/useWrapCallback.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { ContractTransaction } from '@ethersproject/contracts' -import { useWETHContract } from 'hooks/useContract' -import { useAtomValue } from 'jotai/utils' -import { Field, swapAtom } from 'lib/state/swap' -import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' -import { useMemo } from 'react' - -import { WRAPPED_NATIVE_CURRENCY } from '../../../constants/tokens' -import useActiveWeb3React from '../useActiveWeb3React' -import useCurrencyBalance from '../useCurrencyBalance' - -export enum WrapType { - NONE, - WRAP, - UNWRAP, -} -interface UseWrapCallbackReturns { - callback?: () => Promise - type: WrapType -} - -export default function useWrapCallback(): UseWrapCallbackReturns { - const { account, chainId } = useActiveWeb3React() - const wrappedNativeCurrencyContract = useWETHContract() - const { amount, [Field.INPUT]: inputCurrency, [Field.OUTPUT]: outputCurrency } = useAtomValue(swapAtom) - - const wrapType = useMemo(() => { - if (chainId && inputCurrency && outputCurrency) { - if (inputCurrency.isNative && WRAPPED_NATIVE_CURRENCY[chainId]?.equals(outputCurrency)) { - return WrapType.WRAP - } - if (outputCurrency.isNative && WRAPPED_NATIVE_CURRENCY[chainId]?.equals(inputCurrency)) { - return WrapType.UNWRAP - } - } - return WrapType.NONE - }, [chainId, inputCurrency, outputCurrency]) - - const parsedAmountIn = useMemo( - () => tryParseCurrencyAmount(amount, inputCurrency ?? undefined), - [inputCurrency, amount] - ) - const balanceIn = useCurrencyBalance(account, inputCurrency) - - const callback = useMemo(() => { - if ( - wrapType === WrapType.NONE || - !parsedAmountIn || - !balanceIn || - balanceIn.lessThan(parsedAmountIn) || - !wrappedNativeCurrencyContract - ) { - return - } - - return async () => - wrapType === WrapType.WRAP - ? wrappedNativeCurrencyContract.deposit({ value: `0x${parsedAmountIn.quotient.toString(16)}` }) - : wrappedNativeCurrencyContract.withdraw(`0x${parsedAmountIn.quotient.toString(16)}`) - }, [wrapType, parsedAmountIn, balanceIn, wrappedNativeCurrencyContract]) - - return useMemo(() => ({ callback, type: wrapType }), [callback, wrapType]) -} diff --git a/src/lib/hooks/transactions/index.tsx b/src/lib/hooks/transactions/index.tsx deleted file mode 100644 index ddf208c853..0000000000 --- a/src/lib/hooks/transactions/index.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { Token } from '@uniswap/sdk-core' -import { useAtomValue, useUpdateAtom } from 'jotai/utils' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { Transaction, TransactionInfo, transactionsAtom, TransactionType } from 'lib/state/transactions' -import ms from 'ms.macro' -import { useCallback } from 'react' -import invariant from 'tiny-invariant' - -import useBlockNumber from '../useBlockNumber' -import Updater from './updater' - -function isTransactionRecent(transaction: Transaction) { - return Date.now() - transaction.addedTime < ms`1d` -} - -export function usePendingTransactions() { - const { chainId } = useActiveWeb3React() - const txs = useAtomValue(transactionsAtom) - return (chainId ? txs[chainId] : null) ?? {} -} - -export function useAddTransaction() { - const { chainId } = useActiveWeb3React() - const blockNumber = useBlockNumber() - const updateTxs = useUpdateAtom(transactionsAtom) - - return useCallback( - (info: TransactionInfo) => { - invariant(chainId) - const txChainId = chainId - const { hash } = info.response - - updateTxs((chainTxs) => { - const txs = chainTxs[txChainId] || {} - txs[hash] = { addedTime: new Date().getTime(), lastCheckedBlockNumber: blockNumber, info } - chainTxs[chainId] = txs - }) - }, - [blockNumber, chainId, updateTxs] - ) -} - -/** Returns the hash of a pending approval transaction, if it exists. */ -export function usePendingApproval(token?: Token, spender?: string): string | undefined { - const { chainId } = useActiveWeb3React() - const txs = useAtomValue(transactionsAtom) - if (!chainId || !token || !spender) return undefined - - const chainTxs = txs[chainId] - if (!chainTxs) return undefined - - return Object.values(chainTxs).find( - (tx) => - tx && - tx.receipt === undefined && - tx.info.type === TransactionType.APPROVAL && - tx.info.tokenAddress === token.address && - tx.info.spenderAddress === spender && - isTransactionRecent(tx) - )?.info.response.hash -} - -export function TransactionsUpdater() { - const pendingTransactions = usePendingTransactions() - - const updateTxs = useUpdateAtom(transactionsAtom) - const onCheck = useCallback( - ({ chainId, hash, blockNumber }) => { - updateTxs((txs) => { - const tx = txs[chainId]?.[hash] - if (tx) { - tx.lastCheckedBlockNumber = tx.lastCheckedBlockNumber - ? Math.max(tx.lastCheckedBlockNumber, blockNumber) - : blockNumber - } - }) - }, - [updateTxs] - ) - const onReceipt = useCallback( - ({ chainId, hash, receipt }) => { - updateTxs((txs) => { - const tx = txs[chainId]?.[hash] - if (tx) { - tx.receipt = receipt - } - }) - }, - [updateTxs] - ) - - return -} diff --git a/src/lib/hooks/useActiveWeb3React.tsx b/src/lib/hooks/useActiveWeb3React.tsx deleted file mode 100644 index 4869c93a28..0000000000 --- a/src/lib/hooks/useActiveWeb3React.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { ExternalProvider, JsonRpcProvider, Web3Provider } from '@ethersproject/providers' -import { initializeConnector, Web3ReactHooks } from '@web3-react/core' -import { EIP1193 } from '@web3-react/eip1193' -import { EMPTY } from '@web3-react/empty' -import { Actions, Connector, Provider as Eip1193Provider, Web3ReactStore } from '@web3-react/types' -import { Url } from '@web3-react/url' -import { useAtom, WritableAtom } from 'jotai' -import { atom } from 'jotai' -import JsonRpcConnector from 'lib/utils/JsonRpcConnector' -import { createContext, PropsWithChildren, useContext, useEffect, useMemo } from 'react' - -type Web3ContextType = { - connector: Connector - library?: (JsonRpcProvider & { provider?: ExternalProvider }) | Web3Provider - chainId?: ReturnType - accounts?: ReturnType - account?: ReturnType - active?: ReturnType - activating?: ReturnType - error?: ReturnType - ensNames?: ReturnType - ensName?: ReturnType -} - -const EMPTY_CONNECTOR = initializeConnector(() => EMPTY) -const EMPTY_CONTEXT: Web3ContextType = { connector: EMPTY } -const jsonRpcConnectorAtom = atom<[Connector, Web3ReactHooks, Web3ReactStore]>(EMPTY_CONNECTOR) -const injectedConnectorAtom = atom<[Connector, Web3ReactHooks, Web3ReactStore]>(EMPTY_CONNECTOR) -const Web3Context = createContext(EMPTY_CONTEXT) - -export default function useActiveWeb3React() { - return useContext(Web3Context) -} - -function useConnector( - connectorAtom: WritableAtom<[Connector, Web3ReactHooks, Web3ReactStore], [Connector, Web3ReactHooks, Web3ReactStore]>, - Connector: T, - initializer: I | undefined -) { - const [connector, setConnector] = useAtom(connectorAtom) - useEffect(() => { - if (initializer) { - const [connector, hooks, store] = initializeConnector((actions) => new Connector(actions, initializer)) - connector.activate() - setConnector([connector, hooks, store]) - } else { - setConnector(EMPTY_CONNECTOR) - } - }, [Connector, initializer, setConnector]) - return connector -} - -interface ActiveWeb3ProviderProps { - provider?: Eip1193Provider | JsonRpcProvider - jsonRpcEndpoint?: string | JsonRpcProvider -} - -export function ActiveWeb3Provider({ - provider, - jsonRpcEndpoint, - children, -}: PropsWithChildren) { - const Injected = useMemo(() => { - if (provider) { - if (JsonRpcProvider.isProvider(provider)) return JsonRpcConnector - if (JsonRpcProvider.isProvider((provider as any).provider)) { - throw new Error('Eip1193Bridge is experimental: pass your ethers Provider directly') - } - } - return EIP1193 - }, [provider]) as { new (actions: Actions, initializer: typeof provider): Connector } - const injectedConnector = useConnector(injectedConnectorAtom, Injected, provider) - const JsonRpc = useMemo(() => { - if (JsonRpcProvider.isProvider(jsonRpcEndpoint)) return JsonRpcConnector - return Url - }, [jsonRpcEndpoint]) as { new (actions: Actions, initializer: typeof jsonRpcEndpoint): Connector } - const jsonRpcConnector = useConnector(jsonRpcConnectorAtom, JsonRpc, jsonRpcEndpoint) - const [connector, hooks] = injectedConnector[1].useIsActive() - ? injectedConnector - : jsonRpcConnector ?? EMPTY_CONNECTOR - - const library = hooks.useProvider() - - const accounts = hooks.useAccounts() - const account = hooks.useAccount() - const activating = hooks.useIsActivating() - const active = hooks.useIsActive() - const chainId = hooks.useChainId() - const ensNames = hooks.useENSNames() - const ensName = hooks.useENSName() - const error = hooks.useError() - const web3 = useMemo(() => { - if (connector === EMPTY || !(active || activating)) { - return EMPTY_CONTEXT - } - return { connector, library, chainId, accounts, account, active, activating, error, ensNames, ensName } - }, [account, accounts, activating, active, chainId, connector, ensName, ensNames, error, library]) - - // Log web3 errors to facilitate debugging. - useEffect(() => { - if (error) { - console.error('web3 error:', error) - } - }, [error]) - - return {children} -} diff --git a/src/lib/hooks/useCurrency.ts b/src/lib/hooks/useCurrency.ts index 8dd52f6cdb..5fc6a6c1ef 100644 --- a/src/lib/hooks/useCurrency.ts +++ b/src/lib/hooks/useCurrency.ts @@ -10,7 +10,6 @@ import { useMemo } from 'react' import { TOKEN_SHORTHANDS } from '../../constants/tokens' import { isAddress } from '../../utils' import { supportedChainId } from '../../utils/supportedChainId' -import { TokenMap, useTokenMap } from './useTokenList' // parse a name or symbol from a token response const BYTES32_REGEX = /^0x[a-fA-F0-9]{64}$/ @@ -71,6 +70,8 @@ export function useTokenFromNetwork(tokenAddress: string | null | undefined): To ]) } +type TokenMap = { [address: string]: Token } + /** * Returns a Token from the tokenAddress. * Returns null if token is loading or null was passed. @@ -85,16 +86,6 @@ export function useTokenFromMapOrNetwork(tokens: TokenMap, tokenAddress?: string return tokenFromNetwork ?? token } -/** - * Returns a Token from the tokenAddress. - * Returns null if token is loading or null was passed. - * Returns undefined if tokenAddress is invalid or token does not exist. - */ -export function useToken(tokenAddress?: string | null): Token | null | undefined { - const tokens = useTokenMap() - return useTokenFromMapOrNetwork(tokens, tokenAddress) -} - /** * Returns a Currency from the currencyId. * Returns null if currency is loading or null was passed. @@ -119,13 +110,3 @@ export function useCurrencyFromMap(tokens: TokenMap, currencyId?: string | null) return isNative ? nativeCurrency : token } - -/** - * Returns a Currency from the currencyId. - * Returns null if currency is loading or null was passed. - * Returns undefined if currencyId is invalid or token does not exist. - */ -export default function useCurrency(currencyId?: string | null): Currency | null | undefined { - const tokens = useTokenMap() - return useCurrencyFromMap(tokens, currencyId) -} diff --git a/src/lib/hooks/useCurrencyColor.ts b/src/lib/hooks/useCurrencyColor.ts deleted file mode 100644 index 3ba557f767..0000000000 --- a/src/lib/hooks/useCurrencyColor.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Currency } from '@uniswap/sdk-core' -import { useTheme } from 'lib/theme' -import Vibrant from 'node-vibrant/lib/bundle.js' -import { useEffect, useState } from 'react' - -import useCurrencyLogoURIs from './useCurrencyLogoURIs' - -const colors = new Map() - -/** - * Extracts the prominent color from a token. - * NB: If cached, this function returns synchronously; using a callback allows sync or async returns. - */ -async function getColorFromLogoURIs(logoURIs: string[], cb: (color: string | undefined) => void = () => void 0) { - const key = logoURIs[0] - let color = colors.get(key) - - if (!color) { - for (const logoURI of logoURIs) { - let uri = logoURI - if (logoURI.startsWith('http')) { - // Color extraction must use a CORS-compatible resource, but the resource may already be cached. - // Adds a dummy parameter to force a different browser resource cache entry. Without this, color extraction prevents resource caching. - uri += '?color' - } - - color = await getColorFromUriPath(uri) - if (color) break - } - } - - colors.set(key, color) - return cb(color) -} - -async function getColorFromUriPath(uri: string): Promise { - try { - const palette = await Vibrant.from(uri).getPalette() - return palette.Vibrant?.hex - } catch {} - return -} - -export function usePrefetchCurrencyColor(token?: Currency) { - const theme = useTheme() - const logoURIs = useCurrencyLogoURIs(token) - - useEffect(() => { - if (theme.tokenColorExtraction && token) { - getColorFromLogoURIs(logoURIs) - } - }, [token, logoURIs, theme.tokenColorExtraction]) -} - -export default function useCurrencyColor(token?: Currency) { - const [color, setColor] = useState(undefined) - const theme = useTheme() - const logoURIs = useCurrencyLogoURIs(token) - - useEffect(() => { - let stale = false - - if (theme.tokenColorExtraction && token) { - getColorFromLogoURIs(logoURIs, (color) => { - if (!stale && color) { - setColor(color) - } - }) - } - - return () => { - stale = true - setColor(undefined) - } - }, [token, logoURIs, theme.tokenColorExtraction]) - - return color -} diff --git a/src/lib/hooks/useHasFocus.ts b/src/lib/hooks/useHasFocus.ts deleted file mode 100644 index 03e7cc9510..0000000000 --- a/src/lib/hooks/useHasFocus.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' - -export default function useHasFocus(node: Node | null | undefined): boolean { - useEffect(() => { - if (node instanceof HTMLElement) { - // tabIndex is required to receive blur events from non-button elements. - node.tabIndex = node.tabIndex || -1 - // Without explicitly omitting outline, Safari will now outline this node when focused. - node.style.outline = node.style.outline || 'none' - } - }, [node]) - const [hasFocus, setHasFocus] = useState(node?.contains(document?.activeElement) ?? false) - const onFocus = useCallback(() => setHasFocus(true), []) - const onBlur = useCallback((e) => setHasFocus(node?.contains(e.relatedTarget) ?? false), [node]) - useEffect(() => { - node?.addEventListener('focusin', onFocus) - node?.addEventListener('focusout', onBlur) - return () => { - node?.removeEventListener('focusin', onFocus) - node?.removeEventListener('focusout', onBlur) - } - }, [node, onFocus, onBlur]) - return hasFocus -} diff --git a/src/lib/hooks/useHasHover.ts b/src/lib/hooks/useHasHover.ts deleted file mode 100644 index 610ceefe3c..0000000000 --- a/src/lib/hooks/useHasHover.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' - -export default function useHasHover(node: Node | null | undefined): boolean { - const [hasHover, setHasHover] = useState(false) - const onMouseEnter = useCallback(() => setHasHover(true), []) - const onMouseLeave = useCallback((e) => setHasHover(false), []) - useEffect(() => { - node?.addEventListener('mouseenter', onMouseEnter) - node?.addEventListener('mouseleave', onMouseLeave) - return () => { - node?.removeEventListener('mouseenter', onMouseEnter) - node?.removeEventListener('mouseleave', onMouseLeave) - } - }, [node, onMouseEnter, onMouseLeave]) - return hasHover -} diff --git a/src/lib/hooks/useIsValidBlock.ts b/src/lib/hooks/useIsValidBlock.ts index 1ad259d412..f972614cec 100644 --- a/src/lib/hooks/useIsValidBlock.ts +++ b/src/lib/hooks/useIsValidBlock.ts @@ -1,8 +1,8 @@ +import useActiveWeb3React from 'hooks/useActiveWeb3React' import { atomWithImmer } from 'jotai/immer' import { useAtomValue, useUpdateAtom } from 'jotai/utils' import { useCallback } from 'react' -import useActiveWeb3React from './useActiveWeb3React' import useBlockNumber from './useBlockNumber' // The oldest block (per chain) to be considered valid. diff --git a/src/lib/hooks/useNativeEvent.ts b/src/lib/hooks/useNativeEvent.ts deleted file mode 100644 index 1d30e5adaf..0000000000 --- a/src/lib/hooks/useNativeEvent.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useEffect } from 'react' - -export default function useNativeEvent( - element: HTMLElement | null, - type: K, - listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, - options?: boolean | AddEventListenerOptions | undefined -) { - useEffect(() => { - element?.addEventListener(type, listener, options) - return () => element?.removeEventListener(type, listener, options) - }, [element, type, listener, options]) -} diff --git a/src/lib/hooks/useOnSupportedNetwork.ts b/src/lib/hooks/useOnSupportedNetwork.ts deleted file mode 100644 index 6a5039f7d6..0000000000 --- a/src/lib/hooks/useOnSupportedNetwork.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ALL_SUPPORTED_CHAIN_IDS } from 'constants/chains' -import { useMemo } from 'react' - -import useActiveWeb3React from './useActiveWeb3React' - -function useOnSupportedNetwork() { - const { chainId } = useActiveWeb3React() - return useMemo(() => Boolean(chainId && ALL_SUPPORTED_CHAIN_IDS.includes(chainId)), [chainId]) -} - -export default useOnSupportedNetwork diff --git a/src/lib/hooks/usePoll.ts b/src/lib/hooks/usePoll.ts deleted file mode 100644 index 448fb8e978..0000000000 --- a/src/lib/hooks/usePoll.ts +++ /dev/null @@ -1,88 +0,0 @@ -import ms from 'ms.macro' -import { useEffect, useMemo, useState } from 'react' - -const DEFAULT_POLLING_INTERVAL = ms`15s` -const DEFAULT_KEEP_UNUSED_DATA_FOR = ms`10s` - -interface PollingOptions { - // If true, any cached result will be returned, but no new fetch will be initiated. - debounce?: boolean - - // If stale, any cached result will be returned, and a new fetch will be initiated. - isStale?: (value: T) => boolean - - pollingInterval?: number - keepUnusedDataFor?: number -} - -interface CacheEntry { - ttl: number | null // null denotes a pending fetch - result?: T -} - -export default function usePoll( - fetch: () => Promise, - key = '', - { - debounce = false, - isStale, - pollingInterval = DEFAULT_POLLING_INTERVAL, - keepUnusedDataFor = DEFAULT_KEEP_UNUSED_DATA_FOR, - }: PollingOptions -): T | undefined { - const cache = useMemo(() => new Map>(), []) - const [, setData] = useState<{ key: string; result?: T }>({ key }) - - useEffect(() => { - if (debounce) return - - let timeout: number - - const entry = cache.get(key) - if (entry) { - // If there is not a pending fetch (and there should be), queue one. - if (entry.ttl) { - if (isStale && entry?.result !== undefined ? isStale(entry.result) : false) { - poll() // stale results should be refetched immediately - } else if (entry.ttl && entry.ttl + keepUnusedDataFor > Date.now()) { - timeout = setTimeout(poll, Math.max(0, entry.ttl - Date.now())) - } - } - } else { - // If there is no cached entry, trigger a poll immediately. - poll() - } - setData({ key, result: entry?.result }) - - return () => { - clearTimeout(timeout) - timeout = 0 - } - - async function poll(ttl = Date.now() + pollingInterval) { - timeout = setTimeout(poll, pollingInterval) // queue the next poll - cache.set(key, { ttl: null, ...cache.get(key) }) // mark the entry as a pending fetch - - // Always set the result in the cache, but only set it as data if the key is still being queried. - const result = await fetch() - cache.set(key, { ttl, result }) - if (timeout) setData((data) => (data.key === key ? { key, result } : data)) - } - }, [cache, debounce, fetch, isStale, keepUnusedDataFor, key, pollingInterval]) - - useEffect(() => { - // Cleanup stale entries when a new key is used. - void key - - const now = Date.now() - cache.forEach(({ ttl }, key) => { - if (ttl && ttl + keepUnusedDataFor <= now) { - cache.delete(key) - } - }) - }, [cache, keepUnusedDataFor, key]) - - // Use data.result to force a re-render, but actually retrieve the data from the cache. - // This gives the _first_ render access to a new result, avoiding lag introduced by React. - return cache.get(key)?.result -} diff --git a/src/lib/hooks/useScrollbar.ts b/src/lib/hooks/useScrollbar.ts deleted file mode 100644 index 5962e3af61..0000000000 --- a/src/lib/hooks/useScrollbar.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { css } from 'lib/theme' -import { useMemo } from 'react' - -const overflowCss = css` - overflow-y: scroll; -` - -/** Customizes the scrollbar for vertical overflow. */ -const scrollbarCss = (padded: boolean) => css` - overflow-y: scroll; - - ::-webkit-scrollbar { - width: 1.25em; - } - - ::-webkit-scrollbar-thumb { - background: radial-gradient( - closest-corner at 0.25em 0.25em, - ${({ theme }) => theme.interactive} 0.25em, - transparent 0.25em - ), - linear-gradient( - to bottom, - #ffffff00 0.25em, - ${({ theme }) => theme.interactive} 0.25em, - ${({ theme }) => theme.interactive} calc(100% - 0.25em), - #ffffff00 calc(100% - 0.25em) - ), - radial-gradient( - closest-corner at 0.25em calc(100% - 0.25em), - ${({ theme }) => theme.interactive} 0.25em, - #ffffff00 0.25em - ); - background-clip: padding-box; - border: none; - ${padded ? 'border-right' : 'border-left'}: 0.75em solid transparent; - } - - @supports not selector(::-webkit-scrollbar-thumb) { - scrollbar-color: ${({ theme }) => theme.interactive} transparent; - } -` - -interface ScrollbarOptions { - padded?: boolean -} - -export default function useScrollbar(element: HTMLElement | null, { padded = false }: ScrollbarOptions = {}) { - return useMemo( - // NB: The css must be applied on an element's first render. WebKit will not re-apply overflow - // properties until any transitions have ended, so waiting a frame for state would cause jank. - () => (hasOverflow(element) ? scrollbarCss(padded) : overflowCss), - [element, padded] - ) - - function hasOverflow(element: HTMLElement | null) { - if (!element) return true - return element.scrollHeight > element.clientHeight - } -} diff --git a/src/lib/hooks/useSlippage.ts b/src/lib/hooks/useSlippage.ts deleted file mode 100644 index 2483088cc7..0000000000 --- a/src/lib/hooks/useSlippage.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Currency, Percent, TradeType } from '@uniswap/sdk-core' -import useAutoSlippageTolerance, { DEFAULT_AUTO_SLIPPAGE } from 'hooks/useAutoSlippageTolerance' -import { useAtomValue } from 'jotai/utils' -import { autoSlippageAtom, maxSlippageAtom } from 'lib/state/settings' -import { useMemo } from 'react' -import { InterfaceTrade } from 'state/routing/types' - -export function toPercent(maxSlippage: number | undefined): Percent | undefined { - if (!maxSlippage) return undefined - const numerator = Math.floor(maxSlippage * 100) - return new Percent(numerator, 10_000) -} - -export interface Slippage { - auto: boolean - allowed: Percent - warning?: 'warning' | 'error' -} - -export const DEFAULT_SLIPPAGE = { auto: true, allowed: DEFAULT_AUTO_SLIPPAGE } - -/** Returns the allowed slippage, and whether it is auto-slippage. */ -export default function useSlippage(trade: InterfaceTrade | undefined): Slippage { - const shouldUseAutoSlippage = useAtomValue(autoSlippageAtom) - const autoSlippage = useAutoSlippageTolerance(shouldUseAutoSlippage ? trade : undefined) - const maxSlippageValue = useAtomValue(maxSlippageAtom) - const maxSlippage = useMemo(() => toPercent(maxSlippageValue), [maxSlippageValue]) - return useMemo(() => { - const auto = shouldUseAutoSlippage || !maxSlippage - const allowed = shouldUseAutoSlippage ? autoSlippage : maxSlippage ?? autoSlippage - const warning = auto ? undefined : getSlippageWarning(allowed) - if (auto && allowed === DEFAULT_AUTO_SLIPPAGE) { - return DEFAULT_SLIPPAGE - } - return { auto, allowed, warning } - }, [autoSlippage, maxSlippage, shouldUseAutoSlippage]) -} - -export const MAX_VALID_SLIPPAGE = new Percent(1, 2) -export const MIN_HIGH_SLIPPAGE = new Percent(1, 100) - -export function getSlippageWarning(slippage?: Percent): 'warning' | 'error' | undefined { - if (slippage?.greaterThan(MAX_VALID_SLIPPAGE)) return 'error' - if (slippage?.greaterThan(MIN_HIGH_SLIPPAGE)) return 'warning' - return -} diff --git a/src/lib/hooks/useTokenList/index.tsx b/src/lib/hooks/useTokenList/index.tsx deleted file mode 100644 index a02f34a749..0000000000 --- a/src/lib/hooks/useTokenList/index.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { Token } from '@uniswap/sdk-core' -import { TokenInfo, TokenList } from '@uniswap/token-lists' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import resolveENSContentHash from 'lib/utils/resolveENSContentHash' -import { createContext, PropsWithChildren, useCallback, useContext, useEffect, useMemo, useState } from 'react' -import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo' - -import fetchTokenList from './fetchTokenList' -import { ChainTokenMap, tokensToChainTokenMap } from './utils' -import { validateTokens } from './validateTokenList' - -export { useQueryTokens } from './useQueryTokens' - -export const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org' - -const MISSING_PROVIDER = Symbol() -const ChainTokenMapContext = createContext(MISSING_PROVIDER) - -function useChainTokenMapContext() { - const chainTokenMap = useContext(ChainTokenMapContext) - if (chainTokenMap === MISSING_PROVIDER) { - throw new Error('TokenList hooks must be wrapped in a ') - } - return chainTokenMap -} - -export function useIsTokenListLoaded() { - return Boolean(useChainTokenMapContext()) -} - -export default function useTokenList(): WrappedTokenInfo[] { - const { chainId } = useActiveWeb3React() - const chainTokenMap = useChainTokenMapContext() - const tokenMap = chainId && chainTokenMap?.[chainId] - return useMemo(() => { - if (!tokenMap) return [] - return Object.values(tokenMap).map(({ token }) => token) - }, [tokenMap]) -} - -export type TokenMap = { [address: string]: Token } - -export function useTokenMap(): TokenMap { - const { chainId } = useActiveWeb3React() - const chainTokenMap = useChainTokenMapContext() - const tokenMap = chainId && chainTokenMap?.[chainId] - return useMemo(() => { - if (!tokenMap) return {} - return Object.entries(tokenMap).reduce((map, [address, { token }]) => { - map[address] = token - return map - }, {} as TokenMap) - }, [tokenMap]) -} - -export function TokenListProvider({ - list = DEFAULT_TOKEN_LIST, - children, -}: PropsWithChildren<{ list?: string | TokenInfo[] }>) { - // Error boundaries will not catch (non-rendering) async errors, but it should still be shown - const [error, setError] = useState() - if (error) throw error - - const [chainTokenMap, setChainTokenMap] = useState() - - useEffect(() => setChainTokenMap(undefined), [list]) - - const { chainId, library } = useActiveWeb3React() - const resolver = useCallback( - (ensName: string) => { - if (library && chainId === 1) { - return resolveENSContentHash(ensName, library) - } - throw new Error('Could not construct mainnet ENS resolver') - }, - [chainId, library] - ) - - useEffect(() => { - // If the list was already loaded, don't reload it. - if (chainTokenMap) return - - let stale = false - activateList(list) - return () => { - stale = true - } - - async function activateList(list: string | TokenInfo[]) { - try { - let tokens: TokenList | TokenInfo[] - if (typeof list === 'string') { - tokens = await fetchTokenList(list, resolver) - } else { - tokens = await validateTokens(list) - } - // tokensToChainTokenMap also caches the fetched tokens, so it must be invoked even if stale. - const map = tokensToChainTokenMap(tokens) - if (!stale) { - setChainTokenMap(map) - setError(undefined) - } - } catch (e: unknown) { - if (!stale) { - // Do not update the token map, in case the map was already resolved without error on mainnet. - setError(e as Error) - } - } - } - }, [chainTokenMap, list, resolver]) - - return {children} -} diff --git a/src/lib/hooks/useTokenList/useQueryTokens.ts b/src/lib/hooks/useTokenList/useQueryTokens.ts deleted file mode 100644 index 46162b74b4..0000000000 --- a/src/lib/hooks/useTokenList/useQueryTokens.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { nativeOnChain } from 'constants/tokens' -import useDebounce from 'hooks/useDebounce' -import useActiveWeb3React from 'lib/hooks/useActiveWeb3React' -import { useTokenBalances } from 'lib/hooks/useCurrencyBalance' -import { useMemo } from 'react' -import { WrappedTokenInfo } from 'state/lists/wrappedTokenInfo' - -import { getTokenFilter } from './filtering' -import { tokenComparator, useSortTokensByQuery } from './sorting' - -export function useQueryTokens(query: string, tokens: WrappedTokenInfo[]) { - const { chainId, account } = useActiveWeb3React() - const balances = useTokenBalances(account, tokens) - const sortedTokens = useMemo( - // Create a new array because sort is in-place and returns a referentially equivalent array. - () => Array.from(tokens).sort(tokenComparator.bind(null, balances)), - [balances, tokens] - ) - - const debouncedQuery = useDebounce(query, 200) - const filter = useMemo(() => getTokenFilter(debouncedQuery), [debouncedQuery]) - const filteredTokens = useMemo(() => sortedTokens.filter(filter), [filter, sortedTokens]) - - const queriedTokens = useSortTokensByQuery(debouncedQuery, filteredTokens) - - const native = useMemo(() => chainId && nativeOnChain(chainId), [chainId]) - return useMemo(() => { - if (native && filter(native)) { - return [native, ...queriedTokens] - } - return queriedTokens - }, [filter, native, queriedTokens]) -} diff --git a/src/lib/hooks/useTransactionDeadline.ts b/src/lib/hooks/useTransactionDeadline.ts deleted file mode 100644 index 63129fc9a9..0000000000 --- a/src/lib/hooks/useTransactionDeadline.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BigNumber } from '@ethersproject/bignumber' -import { L2_CHAIN_IDS } from 'constants/chains' -import { DEFAULT_DEADLINE_FROM_NOW, L2_DEADLINE_FROM_NOW } from 'constants/misc' -import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp' -import { useAtom } from 'jotai' -import { transactionTtlAtom } from 'lib/state/settings' -import { useMemo } from 'react' - -import useActiveWeb3React from './useActiveWeb3React' - -/** Returns the default transaction TTL for the chain, in minutes. */ -export function useDefaultTransactionTtl(): number { - const { chainId } = useActiveWeb3React() - if (chainId && L2_CHAIN_IDS.includes(chainId)) return L2_DEADLINE_FROM_NOW / 60 - return DEFAULT_DEADLINE_FROM_NOW / 60 -} - -/** Returns the user-inputted transaction TTL, in minutes. */ -export function useTransactionTtl(): [number | undefined, (ttl?: number) => void] { - return useAtom(transactionTtlAtom) -} - -// combines the block timestamp with the user setting to give the deadline that should be used for any submitted transaction -export default function useTransactionDeadline(): BigNumber | undefined { - const [ttl] = useTransactionTtl() - const defaultTtl = useDefaultTransactionTtl() - - const blockTimestamp = useCurrentBlockTimestamp() - return useMemo(() => { - if (!blockTimestamp) return undefined - return blockTimestamp.add((ttl || defaultTtl) /* in seconds */ * 60) - }, [blockTimestamp, defaultTtl, ttl]) -} diff --git a/src/lib/hooks/useUSDCPriceImpact.ts b/src/lib/hooks/useUSDCPriceImpact.ts deleted file mode 100644 index 7760035933..0000000000 --- a/src/lib/hooks/useUSDCPriceImpact.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Currency, CurrencyAmount, Percent, Token } from '@uniswap/sdk-core' -import { useUSDCValue } from 'hooks/useUSDCPrice' -import { useMemo } from 'react' -import { computeFiatValuePriceImpact } from 'utils/computeFiatValuePriceImpact' -import { getPriceImpactWarning } from 'utils/prices' - -export interface PriceImpact { - percent: Percent - warning?: 'warning' | 'error' - toString(): string -} - -/** - * Computes input/output USDC equivalents and the price impact. - * Returns the price impact as a human readable string. - */ -export default function useUSDCPriceImpact( - inputAmount: CurrencyAmount | undefined, - outputAmount: CurrencyAmount | undefined -): { - inputUSDC?: CurrencyAmount - outputUSDC?: CurrencyAmount - impact?: PriceImpact -} { - const inputUSDC = useUSDCValue(inputAmount) ?? undefined - const outputUSDC = useUSDCValue(outputAmount) ?? undefined - return useMemo(() => { - const priceImpact = computeFiatValuePriceImpact(inputUSDC, outputUSDC) - const impact = priceImpact - ? { - percent: priceImpact, - warning: getPriceImpactWarning(priceImpact), - toString: () => toHumanReadablePriceImpact(priceImpact), - } - : undefined - return { inputUSDC, outputUSDC, impact } - }, [inputUSDC, outputUSDC]) -} - -function toHumanReadablePriceImpact(priceImpact: Percent): string { - const sign = priceImpact.lessThan(0) ? '+' : '' - const number = parseFloat(priceImpact.multiply(-1)?.toSignificant(3)) - return `${sign}${number}%` -} diff --git a/src/lib/icons/index.tsx b/src/lib/icons/index.tsx deleted file mode 100644 index ad741df194..0000000000 --- a/src/lib/icons/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import MissingTokenIcon from 'lib/assets/missing-token-image.png' -import { ReactComponent as RouterIcon } from 'lib/assets/svg/auto_router.svg' -import { ReactComponent as CheckIcon } from 'lib/assets/svg/check.svg' -import { ReactComponent as ExpandoIcon } from 'lib/assets/svg/expando.svg' -import { ReactComponent as InlineSpinnerIcon } from 'lib/assets/svg/inline_spinner.svg' -import { ReactComponent as LogoIcon } from 'lib/assets/svg/logo.svg' -import { ReactComponent as SpinnerIcon } from 'lib/assets/svg/spinner.svg' -import { ReactComponent as WalletIcon } from 'lib/assets/svg/wallet.svg' -import { loadingCss } from 'lib/css/loading' -import styled, { Color, css, keyframes } from 'lib/theme' -import { FunctionComponent, SVGProps } from 'react' -/* eslint-disable no-restricted-imports */ -import { Icon as FeatherIcon } from 'react-feather' -import { - AlertTriangle as AlertTriangleIcon, - ArrowDown as ArrowDownIcon, - ArrowRight as ArrowRightIcon, - ArrowUp as ArrowUpIcon, - BarChart2 as BarChart2Icon, - CheckCircle as CheckCircleIcon, - ChevronDown as ChevronDownIcon, - Clock as ClockIcon, - ExternalLink as LinkIcon, - HelpCircle as HelpCircleIcon, - Info as InfoIcon, - Settings as SettingsIcon, - Slash as SlashIcon, - Trash2 as Trash2Icon, - X as XIcon, - XOctagon as XOctagonIcon, -} from 'react-feather' -/* eslint-enable no-restricted-imports */ - -type SVGIcon = FunctionComponent> - -const StyledImage = styled.img` - height: 1em; - width: 1em; -` -function icon(Icon: FeatherIcon | SVGIcon) { - return styled(Icon)<{ color?: Color }>` - clip-path: stroke-box; - height: 1em; - stroke: ${({ color = 'currentColor', theme }) => theme[color]}; - width: 1em; - ` -} - -export const largeIconCss = css<{ iconSize: number }>` - display: flex; - - svg { - align-self: center; - height: ${({ iconSize }) => iconSize}em; - width: ${({ iconSize }) => iconSize}em; - } -` - -const LargeWrapper = styled.div<{ iconSize: number }>` - height: 1em; - width: ${({ iconSize }) => iconSize}em; - ${largeIconCss} -` - -export type Icon = ReturnType | typeof LargeIcon - -interface LargeIconProps { - icon?: Icon - color?: Color - size?: number - className?: string -} - -export function LargeIcon({ icon: Icon, color, size = 1.2, className }: LargeIconProps) { - return ( - - {Icon && } - - ) -} - -export const AlertTriangle = icon(AlertTriangleIcon) -export const ArrowDown = icon(ArrowDownIcon) -export const ArrowRight = icon(ArrowRightIcon) -export const ArrowUp = icon(ArrowUpIcon) -export const CheckCircle = icon(CheckCircleIcon) -export const BarChart = icon(BarChart2Icon) -export const ChevronDown = icon(ChevronDownIcon) -export const Clock = icon(ClockIcon) -export const HelpCircle = icon(HelpCircleIcon) -export const Info = icon(InfoIcon) -export const Link = icon(LinkIcon) -export const AutoRouter = icon(RouterIcon) -export const Settings = icon(SettingsIcon) -export const Slash = icon(SlashIcon) -export const Trash2 = icon(Trash2Icon) -export const Wallet = icon(WalletIcon) -export const X = icon(XIcon) -export const XOctagon = icon(XOctagonIcon) -export const MissingToken = (props: React.ImgHTMLAttributes) => ( - -) - -export const Check = styled(icon(CheckIcon))` - circle { - fill: ${({ theme }) => theme.active}; - stroke: none; - } -` - -export const Expando = styled(icon(ExpandoIcon))<{ open: boolean }>` - .left, - .right { - transition: transform 0.25s ease-in-out; - will-change: transform; - } - - .left { - transform: ${({ open }) => (open ? undefined : 'translateX(-25%)')}; - } - - .right { - transform: ${({ open }) => (open ? undefined : 'translateX(25%)')}; - } -` - -export const Logo = styled(icon(LogoIcon))` - fill: ${({ theme }) => theme.secondary}; - stroke: none; -` - -const rotate = keyframes` - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -` - -export const Spinner = styled(icon(SpinnerIcon))<{ color?: Color }>` - animation: 2s ${rotate} linear infinite; - stroke: ${({ color = 'active', theme }) => theme[color]}; - stroke-linecap: round; - stroke-width: 2; -` - -export const InlineSpinner = styled(icon(InlineSpinnerIcon))<{ color?: Color }>` - animation: ${rotate} 1s cubic-bezier(0.83, 0, 0.17, 1) infinite; - color: ${({ color = 'active', theme }) => theme[color]}; - fill: ${({ color = 'active', theme }) => theme[color]}; - - #track { - stroke: ${({ theme }) => theme.secondary}; - ${loadingCss}; - } -` diff --git a/src/lib/index.tsx b/src/lib/index.tsx deleted file mode 100644 index 389236fb76..0000000000 --- a/src/lib/index.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import Swap, { SwapProps } from './components/Swap' -import Widget, { WidgetProps } from './components/Widget' - -export type { ErrorHandler } from './components/Error/ErrorBoundary' -export type { FeeOptions } from './hooks/swap/useSyncConvenienceFee' -export type { DefaultAddress, TokenDefaults } from './hooks/swap/useSyncTokenDefaults' -export type { Theme } from './theme' -export { darkTheme, lightTheme } from './theme' -export type { Provider as EthersProvider } from '@ethersproject/abstract-provider' -export type { TokenInfo } from '@uniswap/token-lists' -export type { Provider as Eip1193Provider } from '@web3-react/types' -export type { SupportedLocale } from 'constants/locales' -export { SUPPORTED_LOCALES } from 'constants/locales' - -export type SwapWidgetProps = SwapProps & WidgetProps - -export function SwapWidget(props: SwapWidgetProps) { - return ( - - - - ) -} diff --git a/src/lib/lib.d.ts b/src/lib/lib.d.ts deleted file mode 100644 index e8f69a830f..0000000000 --- a/src/lib/lib.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -declare module '*.avif' { - const src: string - export default src -} - -declare module '*.bmp' { - const src: string - export default src -} - -declare module '*.gif' { - const src: string - export default src -} - -declare module '*.jpg' { - const src: string - export default src -} - -declare module '*.jpeg' { - const src: string - export default src -} - -declare module '*.png' { - const src: string - export default src -} - -declare module '*.webp' { - const src: string - export default src -} - -declare module '*.svg' { - import * as React from 'react' - - export const ReactComponent: React.FunctionComponent & { title?: string }> - - const src: string - export default src -} diff --git a/src/lib/state/atoms.ts b/src/lib/state/atoms.ts deleted file mode 100644 index da9b26e432..0000000000 --- a/src/lib/state/atoms.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-types */ -import { Draft } from 'immer' -import { atom, WritableAtom } from 'jotai' -import { withImmer } from 'jotai/immer' - -/** - * Creates a derived atom whose value is the picked object property. - * By default, the setter acts as a primitive atom's, changing the original atom. - * A custom setter may also be passed, which uses an Immer Draft so that it may be mutated directly. - */ -export function pickAtom, Update>( - anAtom: WritableAtom, - key: Key, - setter: (draft: Draft[Key], update: Update) => Draft[Key] -): WritableAtom -export function pickAtom, Update extends Value[Key]>( - anAtom: WritableAtom, - key: Key, - setter?: (draft: Draft[Key], update: Update) => Draft[Key] -): WritableAtom -export function pickAtom, Update extends Value[Key]>( - anAtom: WritableAtom, - key: Key, - setter: (draft: Draft[Key], update: Update) => Draft[Key] = (draft, update) => - update as Draft[Key] -): WritableAtom { - return atom( - (get) => get(anAtom)[key], - (get, set, update: Update) => - set(withImmer(anAtom), (value) => { - const derived = setter(value[key], update) - value[key] = derived - }) - ) -} - -/** Sets a togglable atom to invert its state at the next render. */ -export function setTogglable(draft: boolean) { - return !draft -} diff --git a/src/lib/state/settings.ts b/src/lib/state/settings.ts deleted file mode 100644 index e6092ac9d7..0000000000 --- a/src/lib/state/settings.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { atomWithReset } from 'jotai/utils' - -import { pickAtom, setTogglable } from './atoms' - -interface Settings { - autoSlippage: boolean // if true, slippage will use the default calculation - maxSlippage: number | undefined // expressed as a percent - transactionTtl: number | undefined - mockTogglable: boolean - clientSideRouter: boolean // whether to use the client-side router or query the remote API -} - -const initialSettings: Settings = { - autoSlippage: true, - maxSlippage: undefined, - transactionTtl: undefined, - mockTogglable: true, - clientSideRouter: false, -} - -export const settingsAtom = atomWithReset(initialSettings) -export const autoSlippageAtom = pickAtom(settingsAtom, 'autoSlippage') -export const maxSlippageAtom = pickAtom(settingsAtom, 'maxSlippage') -export const transactionTtlAtom = pickAtom(settingsAtom, 'transactionTtl') -export const mockTogglableAtom = pickAtom(settingsAtom, 'mockTogglable', setTogglable) -export const clientSideRouterAtom = pickAtom(settingsAtom, 'clientSideRouter') diff --git a/src/lib/state/swap.ts b/src/lib/state/swap.ts deleted file mode 100644 index 2a2b0efe6e..0000000000 --- a/src/lib/state/swap.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Currency } from '@uniswap/sdk-core' -import { FeeOptions } from '@uniswap/v3-sdk' -import { SupportedChainId } from 'constants/chains' -import { nativeOnChain } from 'constants/tokens' -import { atom } from 'jotai' -import { atomWithImmer } from 'jotai/immer' - -export enum Field { - INPUT = 'INPUT', - OUTPUT = 'OUTPUT', -} - -export interface Swap { - independentField: Field - amount: string - [Field.INPUT]?: Currency - [Field.OUTPUT]?: Currency -} - -export const swapAtom = atomWithImmer({ - independentField: Field.INPUT, - amount: '', - [Field.INPUT]: nativeOnChain(SupportedChainId.MAINNET), -}) - -// If set to a transaction hash, that transaction will display in a status dialog. -export const displayTxHashAtom = atom(undefined) - -export const feeOptionsAtom = atom(undefined) diff --git a/src/lib/state/transactions.ts b/src/lib/state/transactions.ts deleted file mode 100644 index 9a0fdb9eab..0000000000 --- a/src/lib/state/transactions.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { TransactionReceipt, TransactionResponse } from '@ethersproject/abstract-provider' -import { Currency, CurrencyAmount, TradeType } from '@uniswap/sdk-core' -import { atomWithImmer } from 'jotai/immer' - -export enum TransactionType { - APPROVAL, - SWAP, - WRAP, -} - -interface BaseTransactionInfo { - type: TransactionType - response: TransactionResponse -} - -export interface ApprovalTransactionInfo extends BaseTransactionInfo { - type: TransactionType.APPROVAL - tokenAddress: string - spenderAddress: string -} - -export interface SwapTransactionInfo extends BaseTransactionInfo { - type: TransactionType.SWAP - tradeType: TradeType - inputCurrencyAmount: CurrencyAmount - outputCurrencyAmount: CurrencyAmount -} - -export interface InputSwapTransactionInfo extends SwapTransactionInfo { - tradeType: TradeType.EXACT_INPUT - expectedOutputCurrencyAmount: string - minimumOutputCurrencyAmount: string -} - -export interface OutputSwapTransactionInfo extends SwapTransactionInfo { - tradeType: TradeType.EXACT_OUTPUT - expectedInputCurrencyAmount: string - maximumInputCurrencyAmount: string -} - -export interface WrapTransactionInfo extends BaseTransactionInfo { - type: TransactionType.WRAP - unwrapped: boolean - currencyAmountRaw: string - chainId?: number -} - -export type TransactionInfo = ApprovalTransactionInfo | SwapTransactionInfo | WrapTransactionInfo - -export interface Transaction { - addedTime: number - lastCheckedBlockNumber?: number - receipt?: TransactionReceipt - info: T -} - -export const transactionsAtom = atomWithImmer<{ - [chainId: string]: { [hash: string]: Transaction } -}>({}) diff --git a/src/lib/theme/dynamic.tsx b/src/lib/theme/dynamic.tsx deleted file mode 100644 index 47b295ae7c..0000000000 --- a/src/lib/theme/dynamic.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { darken, lighten, opacify, transparentize } from 'polished' -import { readableColor } from 'polished' -import { ReactNode, useMemo } from 'react' -import { hex } from 'wcag-contrast' - -import { ThemedProvider, useTheme } from './styled' -import { Colors, ComputedTheme } from './theme' - -type DynamicColors = Pick - -const black = 'hsl(0, 0%, 0%)' -const white = 'hsl(0, 0%, 100%)' - -const light: DynamicColors = { - // surface - interactive: transparentize(1 - 0.54, black), - outline: transparentize(1 - 0.24, black), - - // text - primary: black, - secondary: transparentize(1 - 0.64, black), - onInteractive: white, -} - -const dark: DynamicColors = { - // surface - interactive: transparentize(1 - 0.48, white), - outline: transparentize(1 - 0.12, white), - - // text - primary: white, - secondary: transparentize(1 - 0.6, white), - onInteractive: black, -} - -export function getDynamicTheme(theme: ComputedTheme, color: string): ComputedTheme { - const colors = { light, dark }[readableColor(color, 'light', 'dark', false) as 'light' | 'dark'] - return { - ...theme, - ...colors, - module: color, - onHover: (color: string) => (color === colors.primary ? transparentize(0.4, colors.primary) : opacify(0.25, color)), - } -} - -function getAccessibleColor(theme: ComputedTheme, color: string) { - const dynamic = getDynamicTheme(theme, color) - let { primary } = dynamic - let AAscore = hex(color, primary) - const contrastify = hex(color, '#000') > hex(color, '#fff') ? darken : lighten - while (AAscore < 3) { - color = contrastify(0.005, color) - primary = getDynamicTheme(theme, color).primary - AAscore = hex(color, primary) - } - return color -} - -interface DynamicThemeProviderProps { - color?: string - children: ReactNode -} - -export function DynamicThemeProvider({ color, children }: DynamicThemeProviderProps) { - const theme = useTheme() - const value = useMemo(() => { - if (!color) { - return theme - } - - const accessibleColor = getAccessibleColor(theme, color) - return getDynamicTheme(theme, accessibleColor) - }, [theme, color]) - return ( - -
{children}
-
- ) -} diff --git a/src/lib/theme/index.tsx b/src/lib/theme/index.tsx deleted file mode 100644 index 4e6667b191..0000000000 --- a/src/lib/theme/index.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import 'lib/assets/fonts.scss' - -import { mix, transparentize } from 'polished' -import { createContext, ReactNode, useContext, useMemo, useState } from 'react' - -import styled, { ThemedProvider } from './styled' -import { Colors, ComputedTheme, Theme } from './theme' - -export default styled -export * from './dynamic' -export * from './layer' -export * from './styled' -export * from './theme' -export * as ThemedText from './type' - -const white = 'hsl(0, 0%, 100%)' -const black = 'hsl(0, 0%, 0%)' - -const brandLight = 'hsl(331.3, 100%, 50%)' -const brandDark = 'hsl(215, 79%, 51.4%)' -export const brand = brandLight - -const stateColors = { - active: 'hsl(215, 79%, 51.4%)', - success: 'hsl(145, 63.4%, 41.8%)', - warning: 'hsl(43, 89.9%, 53.5%)', - error: 'hsl(0, 98%, 62.2%)', -} - -export const lightTheme: Colors = { - // surface - accent: brandLight, - container: 'hsl(220, 23%, 97.5%)', - module: 'hsl(231, 14%, 90%)', - interactive: 'hsl(229, 13%, 83%)', - outline: 'hsl(225, 7%, 78%)', - dialog: white, - - // text - onAccent: white, - primary: black, - secondary: 'hsl(227, 10%, 37.5%)', - hint: 'hsl(224, 9%, 57%)', - onInteractive: black, - - // state - ...stateColors, - - currentColor: 'currentColor', -} - -export const darkTheme: Colors = { - // surface - accent: brandDark, - container: 'hsl(220, 10.7%, 11%)', - module: 'hsl(222, 10.2%, 19.2%)', - interactive: 'hsl(224, 10%, 28%)', - outline: 'hsl(227, 10%, 37.5%)', - dialog: black, - - // text - onAccent: white, - primary: white, - secondary: 'hsl(224, 8.7%, 57.1%)', - hint: 'hsl(225, 10%, 47.1%)', - onInteractive: white, - - // state - ...stateColors, - - currentColor: 'currentColor', -} - -export const defaultTheme = { - borderRadius: 1, - fontFamily: { - font: '"Inter", sans-serif', - variable: '"InterVariable", sans-serif', - }, - fontFamilyCode: 'IBM Plex Mono', - tokenColorExtraction: false, - ...lightTheme, -} - -export function useSystemTheme() { - const prefersDark = window.matchMedia('(prefers-color-scheme: dark)') - const [systemTheme, setSystemTheme] = useState(prefersDark.matches ? darkTheme : lightTheme) - prefersDark.addEventListener('change', (e) => { - setSystemTheme(e.matches ? darkTheme : lightTheme) - }) - return systemTheme -} - -const ThemeContext = createContext(toComputedTheme(defaultTheme)) - -interface ThemeProviderProps { - theme?: Theme - children: ReactNode -} - -export function ThemeProvider({ theme, children }: ThemeProviderProps) { - const contextTheme = useContext(ThemeContext) - const value = useMemo(() => { - return toComputedTheme({ - ...contextTheme, - ...theme, - } as Required) - }, [contextTheme, theme]) - return ( - - {children} - - ) -} - -function toComputedTheme(theme: Required): ComputedTheme { - return { - ...theme, - borderRadius: clamp( - Number.isFinite(theme.borderRadius) ? (theme.borderRadius as number) : theme.borderRadius ? 1 : 0 - ), - onHover: (color: string) => - color === theme.primary ? transparentize(0.4, theme.primary) : mix(0.16, theme.primary, color), - } - - function clamp(value: number) { - return Math.min(Math.max(value, 0), 1) - } -} diff --git a/src/lib/theme/layer.ts b/src/lib/theme/layer.ts deleted file mode 100644 index be1d88f601..0000000000 --- a/src/lib/theme/layer.ts +++ /dev/null @@ -1,6 +0,0 @@ -export enum Layer { - UNDERLAYER = -1, - OVERLAY = 100, - DIALOG = 1000, - TOOLTIP = 2000, -} diff --git a/src/lib/theme/styled.ts b/src/lib/theme/styled.ts deleted file mode 100644 index a0c61f7552..0000000000 --- a/src/lib/theme/styled.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable no-restricted-imports */ -import styledDefault, { - css as styledCss, - keyframes as styledKeyframes, - ThemedBaseStyledInterface, - ThemedCssFunction, - ThemeProvider as StyledProvider, - ThemeProviderComponent, - useTheme as useStyled, -} from 'styled-components/macro' - -import { ComputedTheme } from './theme' - -export const css = styledCss as unknown as ThemedCssFunction -export const keyframes = styledKeyframes -export const useTheme = useStyled as unknown as () => ComputedTheme -export const ThemedProvider = StyledProvider as unknown as ThemeProviderComponent - -// nextjs imports all of styled-components/macro instead of its default. Check for and resolve this at runtime. -const styled = (styledDefault instanceof Function - ? styledDefault - : (styledDefault as { default: typeof styledDefault }).default) as unknown as ThemedBaseStyledInterface -export default styled diff --git a/src/lib/theme/theme.ts b/src/lib/theme/theme.ts deleted file mode 100644 index 210130c50f..0000000000 --- a/src/lib/theme/theme.ts +++ /dev/null @@ -1,45 +0,0 @@ -export interface Colors { - // surface - accent: string - container: string - module: string - interactive: string - outline: string - dialog: string - - // text - primary: string - onAccent: string - secondary: string - hint: string - onInteractive: string - - // state - active: string - success: string - warning: string - error: string - - currentColor: 'currentColor' -} - -export type Color = keyof Colors - -export interface Attributes { - borderRadius: boolean | number - fontFamily: - | string - | { - font: string - variable: string - } - fontFamilyCode: string - tokenColorExtraction: boolean -} - -export interface Theme extends Partial, Partial {} - -export interface ComputedTheme extends Omit, Colors { - borderRadius: number - onHover: (color: string) => string -} diff --git a/src/lib/theme/type.tsx b/src/lib/theme/type.tsx deleted file mode 100644 index e202ab9453..0000000000 --- a/src/lib/theme/type.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import { Text, TextProps as TextPropsWithCss } from 'rebass' - -import styled, { useTheme } from './styled' -import { Color } from './theme' - -type TextProps = Omit & { - color?: Color - userSelect?: true -} - -const TextWrapper = styled(Text)<{ color?: Color; lineHeight: string; noWrap?: true; userSelect?: true }>` - color: ${({ color = 'currentColor', theme }) => theme[color as Color]}; - // Avoid the need for placeholders by setting min-height to line-height. - min-height: ${({ lineHeight }) => lineHeight}; - // user-select is set to 'none' at the root element (Widget), but is desired for displayed data. - // user-select must be configured through styled-components for cross-browser compat (eg to auto-generate prefixed properties). - user-select: ${({ userSelect }) => userSelect && 'text'}; - white-space: ${({ noWrap }) => noWrap && 'nowrap'}; -` - -const TransitionTextWrapper = styled(TextWrapper)` - transition: font-size 0.25s ease-out, line-height 0.25s ease-out; -` - -export function H1(props: TextProps) { - return ( - - ) -} - -export function H2(props: TextProps) { - return ( - - ) -} - -export function H3(props: TextProps) { - return ( - - ) -} - -export function Subhead1(props: TextProps) { - return ( - - ) -} - -export function Subhead2(props: TextProps) { - return ( - - ) -} - -export function Body1(props: TextProps) { - return -} - -export function Body2(props: TextProps) { - return -} - -export function Caption(props: TextProps) { - return -} - -export function Badge(props: TextProps) { - return -} - -export function ButtonLarge(props: TextProps) { - return ( - - ) -} - -export function ButtonMedium(props: TextProps) { - return ( - - ) -} - -export function ButtonSmall(props: TextProps) { - return ( - - ) -} - -export function TransitionButton(props: TextProps & { buttonSize: 'small' | 'medium' | 'large' }) { - const className = `button button-${props.buttonSize}` - const fontSize = { small: 14, medium: 16, large: 20 }[props.buttonSize] - const lineHeight = `${fontSize}px` - return ( - - ) -} - -export function Code(props: TextProps) { - const { fontFamilyCode } = useTheme() - return ( - - ) -} diff --git a/src/lib/utils/JsonRpcConnector.ts b/src/lib/utils/JsonRpcConnector.ts deleted file mode 100644 index 2826d8734d..0000000000 --- a/src/lib/utils/JsonRpcConnector.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { JsonRpcProvider } from '@ethersproject/providers' -import { Actions, Connector, ProviderConnectInfo, ProviderRpcError } from '@web3-react/types' - -function parseChainId(chainId: string) { - return Number.parseInt(chainId, 16) -} - -export default class JsonRpcConnector extends Connector { - constructor(actions: Actions, public customProvider: JsonRpcProvider) { - super(actions) - customProvider - .on('connect', ({ chainId }: ProviderConnectInfo): void => { - this.actions.update({ chainId: parseChainId(chainId) }) - }) - .on('disconnect', (error: ProviderRpcError): void => { - this.actions.reportError(error) - }) - .on('chainChanged', (chainId: string): void => { - this.actions.update({ chainId: parseChainId(chainId) }) - }) - .on('accountsChanged', (accounts: string[]): void => { - this.actions.update({ accounts }) - }) - } - - async activate() { - this.actions.startActivation() - - try { - const [{ chainId }, accounts] = await Promise.all([ - this.customProvider.getNetwork(), - this.customProvider.listAccounts(), - ]) - this.actions.update({ chainId, accounts }) - } catch (e) { - this.actions.reportError(e) - } - } -} diff --git a/src/lib/utils/animations.ts b/src/lib/utils/animations.ts deleted file mode 100644 index aa72da08ce..0000000000 --- a/src/lib/utils/animations.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { RefObject } from 'react' - -export function isAnimating(node: Animatable | Document) { - return (node.getAnimations().length ?? 0) > 0 -} - -export const UNMOUNTING = 'unmounting' - -/** - * Delays a node's unmounting until any animations on that node are finished, so that an unmounting - * animation may be applied. If there is no animation, this is a no-op. - * - * CSS should target the UNMOUNTING class to determine when to apply an unmounting animation. - */ -export function delayUnmountForAnimation(node: RefObject) { - const current = node.current - const parent = current?.parentElement - const removeChild = parent?.removeChild - if (parent && removeChild) { - parent.removeChild = function (child: T) { - if ((child as Node) === current) { - current.classList.add(UNMOUNTING) - if (isAnimating(current)) { - current.addEventListener('animationend', () => { - removeChild.call(parent, child) - }) - } else { - removeChild.call(parent, child) - } - return child - } else { - return removeChild.call(parent, child) as T - } - } - } -} diff --git a/tsconfig.base.json b/tsconfig.base.json deleted file mode 100644 index 745c204ea2..0000000000 --- a/tsconfig.base.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "compilerOptions": { - "target": "es5", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, - "module": "esnext", - "strict": true, - "alwaysStrict": true, - "strictNullChecks": true, - "noUnusedLocals": false, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitThis": true, - "noImplicitReturns": true, - "useUnknownInCatchVariables": false, - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "downlevelIteration": true, - "allowSyntheticDefaultImports": true, - "types": ["react-spring", "jest"] - }, - "exclude": ["node_modules", "cypress"], -} diff --git a/tsconfig.json b/tsconfig.json index 92d39058f7..a42484eaba 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,30 @@ { - "extends": "./tsconfig.base.json", "compilerOptions": { + "allowJs": true, + "allowSyntheticDefaultImports": true, + "alwaysStrict": true, + "baseUrl": "src", + "downlevelIteration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, "jsx": "react-jsx", + "lib": ["dom", "dom.iterable", "esnext"], + "module": "esnext", + "moduleResolution": "node", "noEmit": true, - "baseUrl": "src" + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noUnusedLocals": false, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "strictNullChecks": true, + "target": "es5", + "types": ["react-spring", "jest"], + "useUnknownInCatchVariables": false }, "exclude": ["node_modules", "cypress"], "include": ["src/**/*"] diff --git a/tsconfig.lib.json b/tsconfig.lib.json deleted file mode 100644 index 14ae231f8f..0000000000 --- a/tsconfig.lib.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "extends": "./tsconfig.base.json", - "compilerOptions": { - "jsx": "react-jsx", - "emitDeclarationOnly": true, - "declaration": true, - "declarationDir": "dts", - "baseUrl": "src/lib", - "paths": { - "lib/*": ["./*"], - "abis/*": ["../abis/*"], - "assets/*": ["../assets/*"], - "constants/*": ["../constants/*"], - "hooks/*": ["../hooks/*"], - "locales/*": ["../locales/*"], - "state/*": ["../state/*"], - "types/*": ["../types/*"], - "utils/*": ["../utils/*"] - } - }, - "exclude": ["node_modules", "src/**/*.test.*"], - "include": ["src/lib/**/*.d.ts", "src/lib/index.tsx"] -} diff --git a/yarn.lock b/yarn.lock index 444d3b8279..51904a21d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,7 +23,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.5.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.5.5": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== @@ -57,7 +57,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.15.5", "@babel/core@^7.7.5", "@babel/core@^7.8.4": +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.5", "@babel/core@^7.8.4": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf" integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA== @@ -191,7 +191,7 @@ dependencies: "@babel/types" "^7.16.7" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": +"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== @@ -840,7 +840,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.16.7" -"@babel/plugin-transform-react-constant-elements@^7.12.1", "@babel/plugin-transform-react-constant-elements@^7.14.5": +"@babel/plugin-transform-react-constant-elements@^7.12.1": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.7.tgz#19e9e4c2df2f6c3e6b3aea11778297d81db8df62" integrity sha512-lF+cfsyTgwWkcw715J88JhMYJ5GpysYNLhLP1PkvkhTRN7B3e74R/1KsDxFxhRpSn0UUD3IWM4GvdBR2PEbbQQ== @@ -1069,7 +1069,7 @@ core-js-compat "^3.6.2" semver "^5.5.0" -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.15.6", "@babel/preset-env@^7.16.11", "@babel/preset-env@^7.8.4": +"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.11", "@babel/preset-env@^7.8.4": version "7.16.11" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982" integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g== @@ -1173,7 +1173,7 @@ "@babel/plugin-transform-react-jsx-source" "^7.12.1" "@babel/plugin-transform-react-pure-annotations" "^7.12.1" -"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.14.5", "@babel/preset-react@^7.16.7": +"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852" integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA== @@ -1193,7 +1193,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typescript" "^7.12.1" -"@babel/preset-typescript@^7.16.0", "@babel/preset-typescript@^7.16.7": +"@babel/preset-typescript@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9" integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ== @@ -1280,7 +1280,7 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" -"@babel/types@^7.0.0", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": +"@babel/types@^7.0.0", "@babel/types@^7.11.5", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== @@ -1288,11 +1288,6 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@base2/pretty-print-object@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.0.tgz#860ce718b0b73f4009e153541faff2cb6b85d047" - integrity sha512-4Th98KlMHr5+JkxfcoDT//6vY8vM+iSPrLNpHhRyLx2CFYi8e2RfqPLdpbnpo0Q5lQC5hNB79yes07zb02fvCw== - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -3265,61 +3260,6 @@ redux-thunk "^2.4.1" reselect "^4.1.5" -"@rollup/plugin-alias@^3.1.9": - version "3.1.9" - resolved "https://registry.yarnpkg.com/@rollup/plugin-alias/-/plugin-alias-3.1.9.tgz#a5d267548fe48441f34be8323fb64d1d4a1b3fdf" - integrity sha512-QI5fsEvm9bDzt32k39wpOwZhVzRcL5ydcffUHMyLVaVaLeC70I8TJZ17F1z1eMoLu4E/UOcH9BWVkKpIKdrfiw== - dependencies: - slash "^3.0.0" - -"@rollup/plugin-babel@^5.3.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879" - integrity sha512-9uIC8HZOnVLrLHxayq/PTzw+uS25E14KPUBh5ktF+18Mjo5yK0ToMMx6epY0uEgkjwJw0aBW4x2horYXh8juWw== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@rollup/pluginutils" "^3.1.0" - -"@rollup/plugin-commonjs@^21.0.1": - version "21.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-21.0.1.tgz#1e57c81ae1518e4df0954d681c642e7d94588fee" - integrity sha512-EA+g22lbNJ8p5kuZJUYyhhDK7WgJckW5g4pNN7n4mAFUM96VuwUnNT3xr2Db2iCZPI1pJPbGyfT5mS9T1dHfMg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - commondir "^1.0.1" - estree-walker "^2.0.1" - glob "^7.1.6" - is-reference "^1.2.1" - magic-string "^0.25.7" - resolve "^1.17.0" - -"@rollup/plugin-eslint@^8.0.1": - version "8.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-eslint/-/plugin-eslint-8.0.1.tgz#bf7462f96027613729b8a805caaa951dc23c333e" - integrity sha512-rTMAY4tKGBdbkHHQDaVhXNJg9tRmW7ihRAg7NQHiPUv13NFYBygIr+OYgpVNwSnGOH146BgCITSBAoMxMQGPTQ== - dependencies: - "@rollup/pluginutils" "^4.0.0" - eslint "^7.12.0" - -"@rollup/plugin-json@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3" - integrity sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw== - dependencies: - "@rollup/pluginutils" "^3.0.8" - -"@rollup/plugin-node-resolve@^13.1.3": - version "13.1.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.1.3.tgz#2ed277fb3ad98745424c1d2ba152484508a92d79" - integrity sha512-BdxNk+LtmElRo5d06MGY4zoepyrXX1tkzX2hrnPEZ53k78GuOMWLqmJDGIIOPwVRIFZrLQOo+Yr6KtCuLIA0AQ== - dependencies: - "@rollup/pluginutils" "^3.1.0" - "@types/resolve" "1.17.1" - builtin-modules "^3.1.0" - deepmerge "^4.2.2" - is-module "^1.0.0" - resolve "^1.19.0" - "@rollup/plugin-node-resolve@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca" @@ -3339,31 +3279,6 @@ "@rollup/pluginutils" "^3.1.0" magic-string "^0.25.7" -"@rollup/plugin-replace@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-3.0.1.tgz#f774550f482091719e52e9f14f67ffc0046a883d" - integrity sha512-989J5oRzf3mm0pO/0djTijdfEh9U3n63BIXN5X7T4U9BP+fN4oxQ6DvDuBvFaHA6scaHQRclqmKQEkBhB7k7Hg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - magic-string "^0.25.7" - -"@rollup/plugin-typescript@^8.3.0": - version "8.3.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz#bc1077fa5897b980fc27e376c4e377882c63e68b" - integrity sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA== - dependencies: - "@rollup/pluginutils" "^3.1.0" - resolve "^1.17.0" - -"@rollup/plugin-url@^6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-url/-/plugin-url-6.1.0.tgz#1234bba9aa30b5972050bdfcf8fcbb1cb8070465" - integrity sha512-FJNWBnBB7nLzbcaGmu1no+U/LlRR67TtgfRFP+VEKSrWlDTE6n9jMns/N4Q/VL6l4x6kTHQX4HQfwTcldaAfHQ== - dependencies: - "@rollup/pluginutils" "^3.1.0" - make-dir "^3.1.0" - mime "^2.4.6" - "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" @@ -3373,14 +3288,6 @@ estree-walker "^1.0.1" picomatch "^2.2.2" -"@rollup/pluginutils@^4.0.0", "@rollup/pluginutils@^4.1.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.1.2.tgz#ed5821c15e5e05e32816f5fb9ec607cdf5a75751" - integrity sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ== - dependencies: - estree-walker "^2.0.1" - picomatch "^2.2.2" - "@samverschueren/stream-to-observable@^0.3.0": version "0.3.1" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" @@ -3424,24 +3331,6 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@skidding/launch-editor@^2.2.3": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@skidding/launch-editor/-/launch-editor-2.2.3.tgz#553d3bcf3ce468bd0ee46cb081276342e120d2b3" - integrity sha512-0SuGEsWdulnbryUJ6humogFuuDMWMb4VJyhOc3FGVkibxVdECYDDkGx8VjS/NePZSegNONDIVhCEVZLTv4ycTQ== - dependencies: - chalk "^2.3.0" - shell-quote "^1.6.1" - -"@skidding/webpack-hot-middleware@^2.25.0": - version "2.25.0" - resolved "https://registry.yarnpkg.com/@skidding/webpack-hot-middleware/-/webpack-hot-middleware-2.25.0.tgz#da8b5d3eb36cce6cc02ad4331655a62967ac9342" - integrity sha512-iLyReNFoov9k6nYR1u8g22BFcodkXGPlCZXA1l5Gf7HaToPi6GH8oFJLkyVGyaaLNSPx7kia3jf8SMpShE2rCA== - dependencies: - ansi-html "0.0.7" - html-entities "^1.2.0" - querystring "^0.2.0" - strip-ansi "^3.0.0" - "@styled-system/background@^5.1.2": version "5.1.2" resolved "https://registry.npmjs.org/@styled-system/background/-/background-5.1.2.tgz" @@ -3554,81 +3443,41 @@ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg== -"@svgr/babel-plugin-add-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18" - integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA== - "@svgr/babel-plugin-remove-jsx-attribute@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== -"@svgr/babel-plugin-remove-jsx-attribute@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89" - integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw== - "@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== -"@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba" - integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA== - "@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ== -"@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee" - integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ== - "@svgr/babel-plugin-svg-dynamic-title@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg== -"@svgr/babel-plugin-svg-dynamic-title@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f" - integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg== - "@svgr/babel-plugin-svg-em-dimensions@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw== -"@svgr/babel-plugin-svg-em-dimensions@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce" - integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA== - "@svgr/babel-plugin-transform-react-native-svg@^5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q== -"@svgr/babel-plugin-transform-react-native-svg@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9" - integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ== - "@svgr/babel-plugin-transform-svg-component@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ== -"@svgr/babel-plugin-transform-svg-component@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f" - integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg== - "@svgr/babel-preset@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" @@ -3643,20 +3492,6 @@ "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0" "@svgr/babel-plugin-transform-svg-component" "^5.5.0" -"@svgr/babel-preset@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627" - integrity sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^6.0.0" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.0.0" - "@svgr/babel-plugin-svg-dynamic-title" "^6.0.0" - "@svgr/babel-plugin-svg-em-dimensions" "^6.0.0" - "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0" - "@svgr/babel-plugin-transform-svg-component" "^6.2.0" - "@svgr/core@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" @@ -3666,15 +3501,6 @@ camelcase "^6.2.0" cosmiconfig "^7.0.0" -"@svgr/core@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.0.tgz#187a7930695635382c1ab42f476a1d4d45a65994" - integrity sha512-n5PrYAPoTpWGykqa8U05/TVTHOrVR/TxrUJ5EWHP9Db6vR3qnqzwAVLiFT1+slA7zQoJTXafQb+akwThf9SxGw== - dependencies: - "@svgr/plugin-jsx" "^6.2.0" - camelcase "^6.2.0" - cosmiconfig "^7.0.1" - "@svgr/hast-util-to-babel-ast@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" @@ -3682,14 +3508,6 @@ dependencies: "@babel/types" "^7.12.6" -"@svgr/hast-util-to-babel-ast@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.0.0.tgz#423329ad866b6c169009cc82b5e28ffee80c857c" - integrity sha512-S+TxtCdDyRGafH1VG1t/uPZ87aOYOHzWL8kqz4FoSZcIbzWA6rnOmjNViNiDzqmEpzp2PW5o5mZfvC9DiVZhTQ== - dependencies: - "@babel/types" "^7.15.6" - entities "^3.0.1" - "@svgr/plugin-jsx@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" @@ -3700,16 +3518,6 @@ "@svgr/hast-util-to-babel-ast" "^5.5.0" svg-parser "^2.0.2" -"@svgr/plugin-jsx@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.0.tgz#5e41a75b12b34cb66509e63e535606161770ff42" - integrity sha512-QJDEe7K5Hkd4Eewu4pcjiOKTCtjB47Ol6lDLXVhf+jEewi+EKJAaAmM+bNixfW6LSNEg8RwOYQN3GZcprqKfHw== - dependencies: - "@babel/core" "^7.15.5" - "@svgr/babel-preset" "^6.2.0" - "@svgr/hast-util-to-babel-ast" "^6.0.0" - svg-parser "^2.0.2" - "@svgr/plugin-svgo@^5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" @@ -3719,30 +3527,6 @@ deepmerge "^4.2.2" svgo "^1.2.2" -"@svgr/plugin-svgo@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c" - integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q== - dependencies: - cosmiconfig "^7.0.1" - deepmerge "^4.2.2" - svgo "^2.5.0" - -"@svgr/rollup@^6.2.0": - version "6.2.0" - resolved "https://registry.yarnpkg.com/@svgr/rollup/-/rollup-6.2.0.tgz#8966f32f53ad788c378ef306dfa49a796d68db49" - integrity sha512-rYcS8Z15nrciZPYkkpOADGNfIPDOL8KSSHy9EURQycIVsUoRIue81quF24DNZpe8WYvmH1fjf7ntk5y1nrXqjg== - dependencies: - "@babel/core" "^7.15.5" - "@babel/plugin-transform-react-constant-elements" "^7.14.5" - "@babel/preset-env" "^7.15.6" - "@babel/preset-react" "^7.14.5" - "@babel/preset-typescript" "^7.16.0" - "@svgr/core" "^6.2.0" - "@svgr/plugin-jsx" "^6.2.0" - "@svgr/plugin-svgo" "^6.2.0" - rollup-pluginutils "^2.8.2" - "@svgr/webpack@5.5.0": version "5.5.0" resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640" @@ -3831,19 +3615,6 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@trysound/sax@0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" - integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== - -"@ts-type/package-dts@^1.0.58": - version "1.0.58" - resolved "https://registry.yarnpkg.com/@ts-type/package-dts/-/package-dts-1.0.58.tgz#75f6fdf5f1e8f262a5081b90346439b4c4bc8d01" - integrity sha512-Ry5RPZDAnSz/gyLtjd2a2yNC07CZ/PCOsuDzYj3phOolIgEH68HXRw6SbsDlavnVUEenDYj5GUM10gQ5iVEbVQ== - dependencies: - "@types/semver" "^7.3.9" - ts-type "^2.1.4" - "@typechain/ethers-v5@^7.0.0": version "7.0.1" resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-7.0.1.tgz#f9ae60ae5bd9e8ea8a996f66244147e8e74034ae" @@ -4158,13 +3929,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/fs-extra@^8.0.1": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f" - integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== - dependencies: - "@types/node" "*" - "@types/geojson@*": version "7946.0.8" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.8.tgz#30744afdb385e2945e22f3b033f897f76b1f12ca" @@ -4210,13 +3974,6 @@ dependencies: "@types/node" "*" -"@types/http-proxy@^1.17.5": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.7.tgz#30ea85cc2c868368352a37f0d0d3581e24834c6f" - integrity sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w== - dependencies: - "@types/node" "*" - "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" @@ -4468,13 +4225,6 @@ dependencies: "@types/node" "*" -"@types/resolve@1.17.1": - version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" - integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== - dependencies: - "@types/node" "*" - "@types/retry@*": version "0.12.1" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" @@ -4492,11 +4242,6 @@ dependencies: "@types/node" "*" -"@types/semver@^7.3.9": - version "7.3.9" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc" - integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ== - "@types/sinonjs__fake-timers@^6.0.2": version "6.0.3" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.3.tgz#79df6f358ae8f79e628fe35a63608a0ea8e7cf08" @@ -5450,16 +5195,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarn-tool/resolve-package@^1.0.40": - version "1.0.42" - resolved "https://registry.yarnpkg.com/@yarn-tool/resolve-package/-/resolve-package-1.0.42.tgz#4a72c1a77b7035dc86250744d2cdbc16292bc4f8" - integrity sha512-1BAsoiD6jGAaPc7mRH0UxIVXgRSTv7fnhwfKkaFUYpqsU4ZR7KIigZTMcb2bujtlzKQbNneMPQGjiqe3F8cmlw== - dependencies: - "@ts-type/package-dts" "^1.0.58" - pkg-dir "< 6 >= 5" - tslib "^2.3.1" - upath2 "^3.1.12" - "@zeit/schemas@2.6.0": version "2.6.0" resolved "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz" @@ -5541,11 +5276,6 @@ aes-js@^3.1.2: resolved "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== -after@0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= - agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -5846,11 +5576,6 @@ array.prototype.flatmap@^1.2.4: es-abstract "^1.18.0-next.1" function-bind "^1.1.1" -arraybuffer.slice@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" - integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== - arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" @@ -6273,7 +5998,7 @@ babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -backo2@1.0.2, backo2@^1.0.2: +backo2@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= @@ -6295,11 +6020,6 @@ base-x@^3.0.2: dependencies: safe-buffer "^5.0.1" -base64-arraybuffer@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" - integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= - base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" @@ -6310,11 +6030,6 @@ base64-sol@1.0.1: resolved "https://registry.npmjs.org/base64-sol/-/base64-sol-1.0.1.tgz" integrity sha512-ld3cCNMeXt4uJXmLZBHFGMvVpK9KsLVEhPpFRXnvSVAqABKbuNZg/+dsq3NuM+wxFLb/UrVkz7m1ciWmkMfTbg== -base64id@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" - integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= - base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -6354,13 +6069,6 @@ bech32@1.1.4: resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== -better-assert@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" - integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= - dependencies: - callsite "1.0.0" - bfj@^7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2" @@ -6417,11 +6125,6 @@ blob-util@^2.0.2: resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ== -blob@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" - integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== - bluebird@3.7.2, bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -6860,11 +6563,6 @@ caller-path@^2.0.0: dependencies: caller-callsite "^2.0.0" -callsite@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" - integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= - callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -6953,7 +6651,7 @@ chalk@2.4.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -7048,11 +6746,6 @@ chardet@^0.7.0: resolved "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - check-more-types@2.24.0, check-more-types@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" @@ -7078,7 +6771,7 @@ chokidar@3.5.1: optionalDependencies: fsevents "~2.3.1" -"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1, chokidar@^3.4.3, chokidar@^3.5.1, chokidar@^3.5.2: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1, chokidar@^3.4.3, chokidar@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== @@ -7394,7 +7087,7 @@ color@^3.0.0: color-convert "^1.9.3" color-string "^1.6.0" -colorette@^1.1.0, colorette@^1.2.1, colorette@^1.2.2: +colorette@^1.2.1, colorette@^1.2.2: version "1.4.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== @@ -7425,7 +7118,7 @@ command-line-args@^4.0.7: find-replace "^1.0.3" typical "^2.6.1" -commander@*, commander@7, commander@^7.2.0: +commander@*, commander@7: version "7.2.0" resolved "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== @@ -7460,26 +7153,11 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-bind@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= - -component-emitter@^1.2.1, component-emitter@~1.3.0: +component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== -component-inherit@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= - compose-function@3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f" @@ -7605,11 +7283,6 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - cookie@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" @@ -7662,12 +7335,7 @@ core-js@^2.4.0: resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.1.3: - version "3.21.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.21.1.tgz#f2e0ddc1fc43da6f904706e8e955bc19d06a0d94" - integrity sha512-FRq5b/VMrWlrmCzwRrpDYNxyHP9BcAZC+xHJaqTgIE5091ZV1NTmyh0sGOg5XqpnHvR0svdy0sv1gWA1zmhxig== - -core-js@^3.15.1, core-js@^3.6.5: +core-js@^3.6.5: version "3.18.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.1.tgz#289d4be2ce0085d40fc1244c0b1a54c00454622f" integrity sha512-vJlUi/7YdlCZeL6fXvWNaLUPh/id12WXj3MbkMw5uOyF0PfWPBNOCNbs53YqgrvtujLNlt9JQpruyIKkUZ+PKA== @@ -7721,7 +7389,7 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: +cosmiconfig@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== @@ -7818,11 +7486,6 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -crypt@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -7946,7 +7609,7 @@ css-tree@1.0.0-alpha.37: mdn-data "2.0.4" source-map "^0.6.1" -css-tree@^1.1.2, css-tree@^1.1.3: +css-tree@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== @@ -8071,7 +7734,7 @@ cssnano@^4.1.10: is-resolvable "^1.0.0" postcss "^7.0.0" -csso@^4.0.2, csso@^4.2.0: +csso@^4.0.2: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== @@ -8530,20 +8193,6 @@ debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@~3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -8623,11 +8272,6 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -define-lazy-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" - integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== - define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -8670,20 +8314,6 @@ del@^4.1.1: pify "^4.0.1" rimraf "^2.6.3" -del@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" - integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== - dependencies: - globby "^10.0.1" - graceful-fs "^4.2.2" - is-glob "^4.0.1" - is-path-cwd "^2.2.0" - is-path-inside "^3.0.1" - p-map "^3.0.0" - rimraf "^3.0.0" - slash "^3.0.0" - delaunator@5: version "5.0.0" resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.0.tgz#60f052b28bd91c9b4566850ebf7756efe821d81b" @@ -9075,46 +8705,6 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -engine.io-client@~3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.3.3.tgz#aeb45695ced81b787a8a10c92b0bc226b1cb3c53" - integrity sha512-PXIgpzb1brtBzh8Q6vCjzCMeu4nfEPmaDm+L3Qb2sVHwLkxC1qRiBMSjOB0NJNjZ0hbPNUKQa+s8J2XxLOIEeQ== - dependencies: - component-emitter "1.2.1" - component-inherit "0.0.3" - debug "~3.1.0" - engine.io-parser "~2.1.1" - has-cors "1.1.0" - indexof "0.0.1" - parseqs "0.0.5" - parseuri "0.0.5" - ws "~6.1.0" - xmlhttprequest-ssl "~1.6.3" - yeast "0.1.2" - -engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" - integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== - dependencies: - after "0.8.2" - arraybuffer.slice "~0.0.7" - base64-arraybuffer "0.1.5" - blob "0.0.5" - has-binary2 "~1.0.2" - -engine.io@~3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.3.2.tgz#18cbc8b6f36e9461c5c0f81df2b830de16058a59" - integrity sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w== - dependencies: - accepts "~1.3.4" - base64id "1.0.0" - cookie "0.3.1" - debug "~3.1.0" - engine.io-parser "~2.1.0" - ws "~6.1.0" - enhanced-resolve@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" @@ -9136,11 +8726,6 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4" - integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q== - errno@^0.1.3, errno@~0.1.7: version "0.1.8" resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" @@ -9215,11 +8800,6 @@ es6-iterator@2.0.3, es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promisify@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.1.1.tgz#46837651b7b06bf6fff893d03f29393668d01621" - integrity sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg== - es6-symbol@^3.1.1, es6-symbol@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" @@ -9462,7 +9042,7 @@ eslint-webpack-plugin@^2.5.2: normalize-path "^3.0.0" schema-utils "^3.0.0" -eslint@^7.11.0, eslint@^7.12.0: +eslint@^7.11.0: version "7.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== @@ -9561,11 +9141,6 @@ estree-walker@^1.0.1: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== -estree-walker@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -10055,7 +9630,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.0.0, fast-glob@^3.0.3, fast-glob@^3.1.1: +fast-glob@^3.1.1: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== @@ -10230,7 +9805,7 @@ find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.3.1, find-cache-dir@^3.3.2: +find-cache-dir@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== @@ -10274,22 +9849,6 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-up@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.2.0.tgz#f3b81d633fa83bebe64f83a8bab357f86d5914be" - integrity sha512-yWHzMzXCaFoABSnFTCPKNFlYoq4mSga9QLRRKOCLSJ33hSkzROB14ITbAWW0QDQDyuzsPQ33S1DsOWQb/oW1yA== - dependencies: - locate-path "^7.0.0" - path-exists "^5.0.0" - firebase@^9.1.3: version "9.1.3" resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.1.3.tgz#11557f812f53edab5053ed0bd4dd344f2ae7fb5f" @@ -10360,13 +9919,6 @@ follow-redirects@^1.0.0, follow-redirects@^1.10.0: resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz" integrity sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg== -for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -10454,15 +10006,6 @@ from@~0: resolved "https://registry.npmjs.org/from/-/from-0.1.7.tgz" integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= -fs-extra@10.0.0, fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^6.0.1" - universalify "^2.0.0" - fs-extra@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -10498,11 +10041,6 @@ fs-minipass@^2.0.0: dependencies: minipass "^3.0.0" -fs-monkey@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" - integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== - fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -10670,7 +10208,7 @@ glob@^6.0.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: +glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -10725,20 +10263,6 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globby@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" - integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" @@ -10763,20 +10287,6 @@ globby@11.0.3: merge2 "^1.3.0" slash "^3.0.0" -globby@^10.0.1: - version "10.0.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" - integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@^11.0.3: version "11.0.4" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" @@ -10817,7 +10327,7 @@ got@^9.6.0: to-readable-stream "^1.0.0" url-parse-lax "^3.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== @@ -10920,18 +10430,6 @@ has-bigints@^1.0.1: resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== -has-binary2@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" - integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== - dependencies: - isarray "2.0.1" - -has-cors@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -11092,7 +10590,7 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" -html-entities@^1.2.0, html-entities@^1.2.1, html-entities@^1.3.1: +html-entities@^1.2.1, html-entities@^1.3.1: version "1.4.0" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.4.0.tgz#cfbd1b01d2afaf9adca1b10ae7dffab98c71d2dc" integrity sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA== @@ -11226,18 +10724,7 @@ http-proxy-middleware@0.19.1: lodash "^4.17.11" micromatch "^3.1.10" -http-proxy-middleware@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz#7ef3417a479fb7666a571e09966c66a39bd2c15f" - integrity sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg== - dependencies: - "@types/http-proxy" "^1.17.5" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.17.0, http-proxy@^1.18.1: +http-proxy@^1.17.0: version "1.18.1" resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== @@ -11326,7 +10813,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4: +ignore@^5.1.4: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -11384,7 +10871,7 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-from@3.0.0, import-from@^3.0.0: +import-from@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-3.0.0.tgz#055cfec38cd5a27d8057ca51376d7d3bf0891966" integrity sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ== @@ -11434,11 +10921,6 @@ indexes-of@^1.0.1: resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= -indexof@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= - infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -11636,12 +11118,12 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.6: +is-buffer@^1.1.4, is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: +is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== @@ -11728,7 +11210,7 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= -is-docker@^2.0.0, is-docker@^2.1.1: +is-docker@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== @@ -11867,7 +11349,7 @@ is-observable@^1.1.0: dependencies: symbol-observable "^1.1.0" -is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: +is-path-cwd@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== @@ -11886,7 +11368,7 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" -is-path-inside@^3.0.1, is-path-inside@^3.0.2: +is-path-inside@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== @@ -11896,16 +11378,6 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-plain-object@3.0.1, is-plain-object@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" - integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== - is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -11928,13 +11400,6 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-reference@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" - integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== - dependencies: - "@types/estree" "*" - is-regex@^1.0.4, is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -12062,11 +11527,6 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= -isarray@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= - isarray@^2.0.1: version "2.0.5" resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz" @@ -13157,20 +12617,6 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -locate-path@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.0.0.tgz#f0a60c8dd7ef0f737699eb9461b9567a92bc97da" - integrity sha512-+cg2yXqDUKfo4hsFxwa3G1cBJeA+gs1vD8FyV9/odWoUlQe/4syxHQ5DPtKjtfm6gnKbZzjCqzX03kXosvZB1w== - dependencies: - p-locate "^6.0.0" - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -13388,7 +12834,7 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: +make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -13417,13 +12863,6 @@ makeerror@1.0.x: dependencies: tmpl "1.0.x" -map-age-cleaner@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" - integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== - dependencies: - p-defer "^1.0.0" - map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" @@ -13455,15 +12894,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -md5@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" - integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== - dependencies: - charenc "0.0.2" - crypt "0.0.2" - is-buffer "~1.1.6" - mdast-add-list-metadata@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz" @@ -13486,21 +12916,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -mem@^8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mem/-/mem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122" - integrity sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA== - dependencies: - map-age-cleaner "^0.1.3" - mimic-fn "^3.1.0" - -memfs@^3.2.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" - integrity sha512-BEE62uMfKOavX3iG7GYX43QJ+hAeeWnwIAuJ/R6q96jaMtiLzhsxHJC8B1L7fK7Pt/vXDRwb3SG/yBpNGDPqzg== - dependencies: - fs-monkey "1.0.3" - "memoize-one@>=3.1.1 <6": version "5.2.1" resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz" @@ -13532,7 +12947,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.2.3, merge2@^1.3.0: +merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -13627,7 +13042,7 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.30, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.32" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.32.tgz#1d00e89e7de7fe02008db61001d9e02852670fd5" integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== @@ -13639,7 +13054,7 @@ mime@1.6.0, mime@^1.3.4: resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.4, mime@^2.4.6: +mime@^2.4.4: version "2.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== @@ -13654,11 +13069,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.1.0.tgz#65755145bbf3e36954b949c16450427451d5ca74" - integrity sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ== - mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -14190,11 +13600,6 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= -object-component@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" - integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= - object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -14258,7 +13663,7 @@ object.fromentries@^2.0.4: es-abstract "^1.18.0-next.2" has "^1.0.3" -object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0, object.getownpropertydescriptors@^2.1.1: +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz#1bd63aeacf0d5d2d2f31b5e393b03a7c601a23f7" integrity sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ== @@ -14339,15 +13744,6 @@ open@^7.0.2: is-docker "^2.0.0" is-wsl "^2.1.1" -open@^8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/open/-/open-8.2.1.tgz#82de42da0ccbf429bc12d099dad2e0975e14e8af" - integrity sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ== - dependencies: - define-lazy-prop "^2.0.0" - is-docker "^2.1.1" - is-wsl "^2.2.0" - "openzeppelin-solidity-2.3.0@npm:openzeppelin-solidity@2.3.0": version "2.3.0" resolved "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-2.3.0.tgz" @@ -14419,7 +13815,7 @@ os-browserify@^0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: +os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= @@ -14434,11 +13830,6 @@ p-cancelable@^1.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= - p-each-series@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" @@ -14470,13 +13861,6 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" - integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== - dependencies: - yocto-queue "^1.0.0" - p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -14498,32 +13882,11 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-locate@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" - integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== - dependencies: - p-limit "^4.0.0" - p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== - dependencies: - aggregate-error "^3.0.0" - p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -14670,20 +14033,6 @@ parse5@6.0.1: resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== -parseqs@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" - integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= - dependencies: - better-assert "~1.0.0" - -parseuri@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" - integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= - dependencies: - better-assert "~1.0.0" - parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -14730,11 +14079,6 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-exists@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" - integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== - path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -14745,13 +14089,6 @@ path-is-inside@1.0.2, path-is-inside@^1.0.2: resolved "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= -path-is-network-drive@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/path-is-network-drive/-/path-is-network-drive-1.0.13.tgz#c9aa0183eb72c328aa83f43def93ddcb9d7ec4d4" - integrity sha512-Hg74mRN6mmXV+gTm3INjFK40ncAmC/Lo4qoQaSZ+GT3hZzlKdWQSqAjqyPeW0SvObP2W073WyYEBWY9d3wOm3A== - dependencies: - tslib "^2.3.1" - path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -14779,13 +14116,6 @@ path-root@^0.1.1: dependencies: path-root-regex "^0.1.0" -path-strip-sep@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/path-strip-sep/-/path-strip-sep-1.0.10.tgz#2be4e789406b298af8709ff79af716134b733b98" - integrity sha512-JpCy+8LAJQQTO1bQsb/84s1g+/Stm3h39aOpPRBQ/paMUGVPPZChLTOTKHoaCkc/6sKuF7yVsnq5Pe1S6xQGcA== - dependencies: - tslib "^2.3.1" - path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -14833,16 +14163,6 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pem@^1.14.4: - version "1.14.4" - resolved "https://registry.yarnpkg.com/pem/-/pem-1.14.4.tgz#a68c70c6e751ccc5b3b5bcd7af78b0aec1177ff9" - integrity sha512-v8lH3NpirgiEmbOqhx0vwQTxwi0ExsiWBGYh0jYNq7K6mQuO4gI6UEFlr6fLAdv9TPXRt6GqiwE37puQdIDS8g== - dependencies: - es6-promisify "^6.0.0" - md5 "^2.2.1" - os-tmpdir "^1.0.1" - which "^2.0.2" - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -14914,13 +14234,6 @@ pixelmatch@^4.0.2: dependencies: pngjs "^3.0.0" -"pkg-dir@< 6 >= 5": - version "5.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" - integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== - dependencies: - find-up "^5.0.0" - pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -15959,15 +15272,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== -query-string@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - query-string@6.13.5: version "6.13.5" resolved "https://registry.npmjs.org/query-string/-/query-string-6.13.5.tgz" @@ -16093,59 +15397,6 @@ react-confetti@^6.0.0: dependencies: tween-functions "^1.2.0" -react-cosmos-playground2@^5.6.3: - version "5.6.3" - resolved "https://registry.yarnpkg.com/react-cosmos-playground2/-/react-cosmos-playground2-5.6.3.tgz#83a93cbe08a07fc659813d760ee5a82ef306deb3" - integrity sha512-NeW8M3RC7vETTTpkDsPZlyVpYXQzDq5ssXxdQIx7p6xplXOwzYjY1gzTRdXMVy7XWPp3KGvGoqNt045NstCL2g== - -react-cosmos-plugin@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/react-cosmos-plugin/-/react-cosmos-plugin-5.6.0.tgz#03c0eda6be9075e5c91d7557aca054340a694b77" - integrity sha512-3yphEQ8nDDMiCChenz9sPyABqz/Z7daGhl1xElKpVKWziwX8OKoMxHFr4DrTZgxnRy4dTPyTsC20O0tLEfSD/A== - -react-cosmos-shared2@^5.6.3: - version "5.6.3" - resolved "https://registry.yarnpkg.com/react-cosmos-shared2/-/react-cosmos-shared2-5.6.3.tgz#1c3e5dfd99db6a1adbf8fdfb07e3cb84230c02a4" - integrity sha512-GtvkQTLkzRdC6s6Y59ZuK2f/5JUxiEFZEANdPoyuTJpzBEPEVHRO4VCI0yLy3nx39wzi74CmXco4P3Ls9EZe3A== - dependencies: - lodash "^4.17.21" - query-string "5.1.1" - react-element-to-jsx-string "^14.3.2" - react-is "^17.0.2" - socket.io-client "2.2.0" - -react-cosmos@^5.6.6: - version "5.6.6" - resolved "https://registry.yarnpkg.com/react-cosmos/-/react-cosmos-5.6.6.tgz#93d66e347a63da7dfe046c2cb23221dcf815ce9d" - integrity sha512-RMLRjl2gFq9370N6QszjPRMaT5WsEBEkJBsFbz56h00xPnJAxsab8gu5yj6yDDDSFibL/jBgxjJLdqbF00HMNw== - dependencies: - "@skidding/launch-editor" "^2.2.3" - "@skidding/webpack-hot-middleware" "^2.25.0" - chokidar "^3.5.2" - core-js "^3.15.1" - express "^4.17.1" - fs-extra "10.0.0" - glob "^7.1.7" - http-proxy-middleware "^2.0.0" - import-from "^3.0.0" - lodash "^4.17.21" - micromatch "^4.0.4" - open "^8.2.1" - pem "^1.14.4" - pkg-up "^3.1.0" - react-cosmos-playground2 "^5.6.3" - react-cosmos-plugin "^5.6.0" - react-cosmos-shared2 "^5.6.3" - react-error-overlay "6.0.9" - regenerator-runtime "^0.13.7" - resolve-from "^5.0.0" - slash "^3.0.0" - socket.io "2.2.0" - url-parse "^1.5.1" - util.promisify "^1.1.1" - webpack-dev-middleware "^4.3.0" - yargs "^16.2.0" - react-dev-utils@^11.0.3: version "11.0.4" resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a" @@ -16185,14 +15436,6 @@ react-dom@^17.0.1: object-assign "^4.1.1" scheduler "^0.20.2" -react-element-to-jsx-string@^14.3.2: - version "14.3.2" - resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.2.tgz#c0000ed54d1f8b4371731b669613f2d4e0f63d5c" - integrity sha512-WZbvG72cjLXAxV7VOuSzuHEaI3RHj10DZu8EcKQpkKcAj7+qAkG5XUeSdX5FXrA0vPrlx0QsnAzZEBJwzV0e+w== - dependencies: - "@base2/pretty-print-object" "1.0.0" - is-plain-object "3.0.1" - react-error-boundary@^3.1.0: version "3.1.3" resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.3.tgz#276bfa05de8ac17b863587c9e0647522c25e2a0b" @@ -16200,7 +15443,7 @@ react-error-boundary@^3.1.0: dependencies: "@babel/runtime" "^7.12.5" -react-error-overlay@6.0.9, react-error-overlay@^6.0.9: +react-error-overlay@^6.0.9: version "6.0.9" resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== @@ -17026,56 +16269,6 @@ rollup-plugin-babel@^4.3.3: "@babel/helper-module-imports" "^7.0.0" rollup-pluginutils "^2.8.1" -rollup-plugin-copy@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz#f1228a3ffb66ffad8606e2f3fb7ff23141ed3286" - integrity sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ== - dependencies: - "@types/fs-extra" "^8.0.1" - colorette "^1.1.0" - fs-extra "^8.1.0" - globby "10.0.1" - is-plain-object "^3.0.0" - -rollup-plugin-delete@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-delete/-/rollup-plugin-delete-2.0.0.tgz#262acf80660d48c3b167fb0baabd0c3ab985c153" - integrity sha512-/VpLMtDy+8wwRlDANuYmDa9ss/knGsAgrDhM+tEwB1npHwNu4DYNmDfUL55csse/GHs9Q+SMT/rw9uiaZ3pnzA== - dependencies: - del "^5.1.0" - -rollup-plugin-dts@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-4.1.0.tgz#63b1e7de3970bb6d50877e60df2150a3892bc49c" - integrity sha512-rriXIm3jdUiYeiAAd1Fv+x2AxK6Kq6IybB2Z/IdoAW95fb4uRUurYsEYKa8L1seedezDeJhy8cfo8FEL9aZzqg== - dependencies: - magic-string "^0.25.7" - optionalDependencies: - "@babel/code-frame" "^7.16.0" - -rollup-plugin-multi-input@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-multi-input/-/rollup-plugin-multi-input-1.3.1.tgz#07b903b618c005871fea1bd0c4efae7d1aac4fa1" - integrity sha512-bPsxHR6dUney7zsCAAlfkq7lbuy5xph2CvUstSv88oqhtRiLWXwVjiA1Gb4HVjC6I9sJI2eZeQlozXa+GXJKDA== - dependencies: - core-js "^3.1.3" - fast-glob "^3.0.0" - lodash "^4.17.11" - -rollup-plugin-node-externals@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-externals/-/rollup-plugin-node-externals-3.1.2.tgz#1604aa28384a8771735168fe900d6f00f450d0fa" - integrity sha512-2y5lNDI2QNLTntYDOcLzyEVJYszDyQkd2WiRTGQ/6Hdfgt/fSQb5V5trsgBMEkxs2eaunQ0aAW29Ki6jMNutIg== - dependencies: - find-up "^6.2.0" - -rollup-plugin-scss@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-scss/-/rollup-plugin-scss-3.0.0.tgz#35ad0adc614217e0278e702d8a674820faa0929e" - integrity sha512-UldNaNHEon2a5IusHvj/Nnwc7q13YDvbFxz5pfNbHBNStxGoUNyM+0XwAA/UafJ1u8XRPGdBMrhWFthrrGZdWQ== - dependencies: - rollup-pluginutils "^2.3.3" - rollup-plugin-terser@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-5.3.1.tgz#8c650062c22a8426c64268548957463bf981b413" @@ -17087,19 +16280,7 @@ rollup-plugin-terser@^5.3.1: serialize-javascript "^4.0.0" terser "^4.6.2" -rollup-plugin-typescript2@^0.31.1: - version "0.31.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.2.tgz#463aa713a7e2bf85b92860094b9f7fb274c5a4d8" - integrity sha512-hRwEYR1C8xDGVVMFJQdEVnNAeWRvpaY97g5mp3IeLnzhNXzSVq78Ye/BJ9PAaUfN4DXa/uDnqerifMOaMFY54Q== - dependencies: - "@rollup/pluginutils" "^4.1.2" - "@yarn-tool/resolve-package" "^1.0.40" - find-cache-dir "^3.3.2" - fs-extra "^10.0.0" - resolve "^1.20.0" - tslib "^2.3.1" - -rollup-pluginutils@^2.3.3, rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: +rollup-pluginutils@^2.8.1, rollup-pluginutils@^2.8.2: version "2.8.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== @@ -17115,13 +16296,6 @@ rollup@^1.31.1: "@types/node" "*" acorn "^7.1.0" -rollup@^2.63.0: - version "2.63.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.63.0.tgz#fe2f7fec2133f3fab9e022b9ac245628d817c6bb" - integrity sha512-nps0idjmD+NXl6OREfyYXMn/dar3WGcyKn+KBzPdaLecub3x/LrId0wUcthcr8oZUAcZAR8NKcfGGFlNgGL1kQ== - optionalDependencies: - fsevents "~2.3.2" - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -17528,7 +16702,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@1.7.2, shell-quote@^1.6.1: +shell-quote@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== @@ -17635,52 +16809,6 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socket.io-adapter@~1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9" - integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== - -socket.io-client@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7" - integrity sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA== - dependencies: - backo2 "1.0.2" - base64-arraybuffer "0.1.5" - component-bind "1.0.0" - component-emitter "1.2.1" - debug "~3.1.0" - engine.io-client "~3.3.1" - has-binary2 "~1.0.2" - has-cors "1.1.0" - indexof "0.0.1" - object-component "0.0.3" - parseqs "0.0.5" - parseuri "0.0.5" - socket.io-parser "~3.3.0" - to-array "0.1.4" - -socket.io-parser@~3.3.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6" - integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg== - dependencies: - component-emitter "~1.3.0" - debug "~3.1.0" - isarray "2.0.1" - -socket.io@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.2.0.tgz#f0f633161ef6712c972b307598ecd08c9b1b4d5b" - integrity sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w== - dependencies: - debug "~4.1.0" - engine.io "~3.3.1" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.2.0" - socket.io-parser "~3.3.0" - sockjs-client@^1.5.0: version "1.5.1" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.5.1.tgz#256908f6d5adfb94dabbdbd02c66362cca0f9ea6" @@ -18316,19 +17444,6 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -svgo@^2.5.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" - integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== - dependencies: - "@trysound/sax" "0.2.0" - commander "^7.2.0" - css-select "^4.1.3" - css-tree "^1.1.3" - csso "^4.2.0" - picocolors "^1.0.0" - stable "^0.1.8" - swap-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-2.0.2.tgz#671aedb3c9c137e2985ef51c51f9e98445bf70d9" @@ -18568,11 +17683,6 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== -to-array@0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -18711,14 +17821,6 @@ ts-pnp@1.2.0, ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -ts-type@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/ts-type/-/ts-type-2.1.4.tgz#d268d52ac054ef3076bf1c3b2fde0d4d5496e6a3" - integrity sha512-wnajiiIMhn/RHJ1oPld95siKmMJrOgaT6+rMmC8vO1LORgDFEzKP2nBmEFM5b4XVe7Q0J5KcU9oRJFzju7UzrA== - dependencies: - tslib "^2.3.1" - typedarray-dts "^1.0.0" - tsconfig-paths@^3.9.0: version "3.10.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz#79ae67a68c15289fdf5c51cb74f397522d795ed7" @@ -18733,7 +17835,7 @@ tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@~2.3.0: +tslib@^2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@~2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== @@ -18860,11 +17962,6 @@ typechain@^5.0.0: prettier "^2.1.2" ts-essentials "^7.0.1" -typedarray-dts@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typedarray-dts/-/typedarray-dts-1.0.0.tgz#9dec9811386dbfba964c295c2606cf9a6b982d06" - integrity sha512-Ka0DBegjuV9IPYFT1h0Qqk5U4pccebNIJCGl8C5uU7xtOs+jpJvKGAY4fHGK25hTmXZOEUl9Cnsg5cS6K/b5DA== - typedarray-to-buffer@3.1.5, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" @@ -19074,15 +18171,6 @@ untildify@^4.0.0: resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== -upath2@^3.1.12: - version "3.1.12" - resolved "https://registry.yarnpkg.com/upath2/-/upath2-3.1.12.tgz#441b3dfbadde21731017bd1b7beb169498efd0a9" - integrity sha512-yC3eZeCyCXFWjy7Nu4pgjLhXNYjuzuUmJiRgSSw6TJp8Emc+E4951HGPJf+bldFC5SL7oBLeNbtm1fGzXn2gxw== - dependencies: - path-is-network-drive "^1.0.13" - path-strip-sep "^1.0.10" - tslib "^2.3.1" - upath@^1.1.1, upath@^1.1.2, upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" @@ -19223,17 +18311,6 @@ util.promisify@1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -util.promisify@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" - integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - for-each "^0.3.3" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.1" - util.promisify@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" @@ -19543,18 +18620,6 @@ webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-middleware@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz#179cc40795882cae510b1aa7f3710cbe93c9333e" - integrity sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w== - dependencies: - colorette "^1.2.2" - mem "^8.1.1" - memfs "^3.2.2" - mime-types "^2.1.30" - range-parser "^1.2.1" - schema-utils "^3.0.0" - webpack-dev-server@3.11.1: version "3.11.1" resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.1.tgz#c74028bf5ba8885aaf230e48a20e8936ab8511f0" @@ -20021,13 +19086,6 @@ ws@^6.2.1: dependencies: async-limiter "~1.0.0" -ws@~6.1.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" - integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== - dependencies: - async-limiter "~1.0.0" - x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/x-is-string/-/x-is-string-0.1.0.tgz" @@ -20071,11 +19129,6 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xmlhttprequest-ssl@~1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6" - integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q== - xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: version "4.0.2" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" @@ -20170,7 +19223,7 @@ yargs@^15.3.1, yargs@^15.4.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.1.1, yargs@^16.2.0: +yargs@^16.1.1: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -20204,11 +19257,6 @@ yauzl@^2.10.0: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" -yeast@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= - yn@3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" @@ -20219,11 +19267,6 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -yocto-queue@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" - integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== - zustand@^4.0.0-beta.3: version "4.0.0-beta.3" resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.0.0-beta.3.tgz#16dc82b48b65ed61fe2bae5dea4501f49bd450c7"