Skip to content

Instantly share code, notes, and snippets.

@sambacha
Created October 28, 2021 19:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sambacha/807e2f56dd8a72aee542201248fe5996 to your computer and use it in GitHub Desktop.
Save sambacha/807e2f56dd8a72aee542201248fe5996 to your computer and use it in GitHub Desktop.
diff --git a/.prettierrc b/.prettierrc
index 31ba22d..c9788e8 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"semi": false,
"singleQuote": true,
- "printWidth": 120
+ "printWidth": 120,
+ "endOfLine": "auto"
}
diff --git a/.storybook/main.ts b/.storybook/main.ts
deleted file mode 100644
index 89de166..0000000
--- a/.storybook/main.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-const { dirname, join, parse, resolve } = require('path')
-const { existsSync } = require('fs')
-
-module.exports = {
- stories: ['../src/**/*.stories.@(ts|tsx)'],
- addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/preset-create-react-app'],
- typescript: {
- check: true,
- checkOptions: {},
- reactDocgen: 'react-docgen-typescript',
- reactDocgenTypescriptOptions: {
- shouldExtractLiteralValuesFromEnum: true,
- propFilter: prop => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true)
- }
- }
-}
diff --git a/.storybook/manager.ts b/.storybook/manager.ts
deleted file mode 100644
index 10d4ed1..0000000
--- a/.storybook/manager.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { addons } from '@storybook/addons'
-import { light } from './theme'
-
-addons.setConfig({ theme: light })
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
deleted file mode 100644
index ebaf852..0000000
--- a/.storybook/preview.tsx
+++ /dev/null
@@ -1,77 +0,0 @@
-import { ThemeProvider as SCThemeProvider } from 'styled-components'
-import { Story } from '@storybook/react/types-6-0'
-import React from 'react'
-import { FixedGlobalStyle, theme, ThemedGlobalStyle } from '../src/theme'
-import * as storybookThemes from './theme'
-
-export const parameters = {
- actions: { argTypesRegex: '^on[A-Z].*' },
- dependencies: {
- withStoriesOnly: true,
- hideEmpty: true
- },
- docs: {
- theme: storybookThemes.light
- },
- viewport: {
- viewports: {
- mobile: {
- name: 'iPhone X',
- styles: {
- width: '375px',
- height: '812px'
- }
- },
- tablet: {
- name: 'iPad',
- styles: {
- width: '768px',
- height: '1024px'
- }
- },
- laptop: {
- name: 'Laptop',
- styles: {
- width: '1024px',
- height: '768px'
- }
- },
- desktop: {
- name: 'Desktop',
- styles: {
- width: '1440px',
- height: '1024px'
- }
- }
- }
- }
-}
-
-export const globalTypes = {
- theme: {
- name: 'Theme',
- description: 'Global theme for components',
- defaultValue: 'light',
- toolbar: {
- icon: 'circlehollow',
- items: ['light', 'dark']
- }
- }
-}
-
-const withProviders = (Component: Story, context: Record<string, any>) => {
- const THEME = theme(context.globals.theme === 'dark')
- return (
- <>
- <FixedGlobalStyle />
- <SCThemeProvider theme={THEME}>
- <ThemedGlobalStyle />
- <main>
- <Component />
- </main>
- </SCThemeProvider>
- </>
- )
-}
-
-export const decorators = [withProviders]
diff --git a/.storybook/theme.ts b/.storybook/theme.ts
deleted file mode 100644
index 3e57432..0000000
--- a/.storybook/theme.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { create } from '@storybook/theming'
-
-// this themes the storybook UI
-const uniswapBaseTheme = {
- brandTitle: 'Uniswap Design',
- brandUrl: 'https://uniswap.org',
- brandImage: 'https://ipfs.io/ipfs/QmNa8mQkrNKp1WEEeGjFezDmDeodkWRevGFN8JCV7b4Xir'
-}
-export const light = create({
- base: 'light',
- ...uniswapBaseTheme
-})
-
-// export const dark = create({
-// base: 'dark',
-// ...uniswapBaseTheme,
-// })
diff --git a/cypress/integration/add-liquidity.test.ts b/cypress/integration/add-liquidity.test.ts
deleted file mode 100644
index 9703c6c..0000000
--- a/cypress/integration/add-liquidity.test.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-describe('Add Liquidity', () => {
- it('loads the two correct tokens', () => {
- cy.visit('/add/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85-0xc778417E063141139Fce010982780140Aa0cD5Ab')
- cy.get('#add-liquidity-input-tokena .token-symbol-container').should('contain.text', 'MKR')
- cy.get('#add-liquidity-input-tokenb .token-symbol-container').should('contain.text', 'ETH')
- })
-
- it('does not crash if ETH is duplicated', () => {
- cy.visit('/add/0xc778417E063141139Fce010982780140Aa0cD5Ab-0xc778417E063141139Fce010982780140Aa0cD5Ab')
- cy.get('#add-liquidity-input-tokena .token-symbol-container').should('contain.text', 'ETH')
- cy.get('#add-liquidity-input-tokenb .token-symbol-container').should('not.contain.text', 'ETH')
- })
-
- it('token not in storage is loaded', () => {
- cy.visit('/add/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.get('#add-liquidity-input-tokena .token-symbol-container').should('contain.text', 'SKL')
- cy.get('#add-liquidity-input-tokenb .token-symbol-container').should('contain.text', 'MKR')
- })
-
- it('single token can be selected', () => {
- cy.visit('/add/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d')
- cy.get('#add-liquidity-input-tokena .token-symbol-container').should('contain.text', 'SKL')
- cy.visit('/add/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.get('#add-liquidity-input-tokena .token-symbol-container').should('contain.text', 'MKR')
- })
-
- it('redirects /add/token-token to add/token/token', () => {
- cy.visit('/add/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.url().should(
- 'contain',
- '/add/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85'
- )
- })
-
- it('redirects /add/WETH-token to /add/WETH-address/token', () => {
- cy.visit('/add/0xc778417E063141139Fce010982780140Aa0cD5Ab-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.url().should(
- 'contain',
- '/add/0xc778417E063141139Fce010982780140Aa0cD5Ab/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85'
- )
- })
-
- it('redirects /add/token-WETH to /add/token/WETH-address', () => {
- cy.visit('/add/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85-0xc778417E063141139Fce010982780140Aa0cD5Ab')
- cy.url().should(
- 'contain',
- '/add/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85/0xc778417E063141139Fce010982780140Aa0cD5Ab'
- )
- })
-})
diff --git a/cypress/integration/landing.test.ts b/cypress/integration/landing.test.ts
deleted file mode 100644
index a8e5db2..0000000
--- a/cypress/integration/landing.test.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { TEST_ADDRESS_NEVER_USE_SHORTENED } from '../support/commands'
-
-describe('Landing Page', () => {
- beforeEach(() => cy.visit('/'))
- it('loads swap page', () => {
- cy.get('#swap-page')
- })
-
- it('redirects to url /swap', () => {
- cy.url().should('include', '/swap')
- })
-
- it('allows navigation to pool', () => {
- cy.get('#pool-nav-link').click()
- cy.url().should('include', '/pool')
- })
-
- it('is connected', () => {
- cy.get('#web3-status-connected').click()
- cy.get('#web3-account-identifier-row').contains(TEST_ADDRESS_NEVER_USE_SHORTENED)
- })
-})
diff --git a/cypress/integration/lists.test.ts b/cypress/integration/lists.test.ts
deleted file mode 100644
index 5d83e2d..0000000
--- a/cypress/integration/lists.test.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-describe('Lists', () => {
- beforeEach(() => {
- cy.visit('/swap')
- })
-
- // @TODO check if default lists are active when we have them
- it('change list', () => {
- cy.get('#swap-currency-output .open-currency-select-button').click()
- cy.get('.list-token-manage-button').click()
- })
-})
diff --git a/cypress/integration/migrate-v1.test.ts b/cypress/integration/migrate-v1.test.ts
deleted file mode 100644
index 3625048..0000000
--- a/cypress/integration/migrate-v1.test.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-describe('Migrate V1 Liquidity', () => {
- describe('Remove V1 liquidity', () => {
- it('renders the correct page', () => {
- cy.visit('/remove/v1/0x93bB63aFe1E0180d0eF100D774B473034fd60C36')
- cy.get('#remove-v1-exchange').should('contain', 'MKR/ETH')
- })
- })
-})
diff --git a/cypress/integration/pool.test.ts b/cypress/integration/pool.test.ts
deleted file mode 100644
index 5969abc..0000000
--- a/cypress/integration/pool.test.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-describe('Pool', () => {
- beforeEach(() => cy.visit('/pool'))
- it('add liquidity links to /add/ETH', () => {
- cy.get('#join-pool-button').click()
- cy.url().should('contain', '/add/ETH')
- })
-
- it('import pool links to /import', () => {
- cy.get('#import-pool-link').click()
- cy.url().should('contain', '/find')
- })
-})
diff --git a/cypress/integration/remove-liquidity.test.ts b/cypress/integration/remove-liquidity.test.ts
deleted file mode 100644
index 63c8e1a..0000000
--- a/cypress/integration/remove-liquidity.test.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-describe('Remove Liquidity', () => {
- it('redirects', () => {
- cy.visit('/remove/0xc778417E063141139Fce010982780140Aa0cD5Ab-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.url().should(
- 'contain',
- '/remove/0xc778417E063141139Fce010982780140Aa0cD5Ab/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85'
- )
- })
-
- it('eth remove', () => {
- cy.visit('/remove/ETH/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'ETH')
- cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'MKR')
- })
-
- it('eth remove swap order', () => {
- cy.visit('/remove/0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85/ETH')
- cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'MKR')
- cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'ETH')
- })
-
- it('loads the two correct tokens', () => {
- cy.visit('/remove/0xc778417E063141139Fce010982780140Aa0cD5Ab-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'WETH')
- cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'MKR')
- })
-
- it('does not crash if ETH is duplicated', () => {
- cy.visit('/remove/0xc778417E063141139Fce010982780140Aa0cD5Ab-0xc778417E063141139Fce010982780140Aa0cD5Ab')
- cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'WETH')
- cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'WETH')
- })
-
- it('token not in storage is loaded', () => {
- cy.visit('/remove/0xb290b2f9f8f108d03ff2af3ac5c8de6de31cdf6d-0xF9bA5210F91D0474bd1e1DcDAeC4C58E359AaD85')
- cy.get('#remove-liquidity-tokena-symbol').should('contain.text', 'SKL')
- cy.get('#remove-liquidity-tokenb-symbol').should('contain.text', 'MKR')
- })
-})
diff --git a/cypress/integration/send.test.ts b/cypress/integration/send.test.ts
deleted file mode 100644
index 35b8dee..0000000
--- a/cypress/integration/send.test.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-describe('Send', () => {
- it('should redirect', () => {
- cy.visit('/send')
- cy.url().should('include', '/swap')
- })
-
- it('should redirect with url params', () => {
- cy.visit('/send?outputCurrency=ETH&recipient=bob.argent.xyz')
- cy.url().should('contain', '/swap?outputCurrency=ETH&recipient=bob.argent.xyz')
- })
-})
diff --git a/cypress/integration/swap.test.ts b/cypress/integration/swap.test.ts
deleted file mode 100644
index c8e2c4b..0000000
--- a/cypress/integration/swap.test.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-describe('Swap', () => {
- beforeEach(() => {
- cy.visit('/swap')
- })
- it('can enter an amount into input', () => {
- cy.get('#swap-currency-input .token-amount-input').type('0.001', { delay: 200 }).should('have.value', '0.001')
- })
-
- it('zero swap amount', () => {
- cy.get('#swap-currency-input .token-amount-input').type('0.0', { delay: 200 }).should('have.value', '0.0')
- })
-
- it('invalid swap amount', () => {
- cy.get('#swap-currency-input .token-amount-input').type('\\', { delay: 200 }).should('have.value', '')
- })
-
- it('can enter an amount into output', () => {
- cy.get('#swap-currency-output .token-amount-input').type('0.001', { delay: 200 }).should('have.value', '0.001')
- })
-
- it('zero output amount', () => {
- cy.get('#swap-currency-output .token-amount-input').type('0.0', { delay: 200 }).should('have.value', '0.0')
- })
-
- it('can swap ETH for DAI', () => {
- cy.get('#swap-currency-output .open-currency-select-button').click()
- cy.get('.token-item-0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735').should('be.visible')
- cy.get('.token-item-0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735').click({ force: true })
- cy.get('#swap-currency-input .token-amount-input').should('be.visible')
- cy.get('#swap-currency-input .token-amount-input').type('0.001', { force: true, delay: 200 })
- cy.get('#swap-currency-output .token-amount-input').should('not.equal', '')
- cy.get('#swap-button').click()
- cy.get('#confirm-swap-or-send').should('contain', 'Confirm Swap')
- })
-
- it('add a recipient does not exist unless in expert mode', () => {
- cy.get('#add-recipient-button').should('not.exist')
- })
-
- describe('expert mode', () => {
- beforeEach(() => {
- cy.window().then((win) => {
- cy.stub(win, 'prompt').returns('confirm')
- })
- cy.get('#open-settings-dialog-button').click()
- cy.get('#toggle-expert-mode-button').click()
- cy.get('#confirm-expert-mode').click()
- })
-
- it('add a recipient is visible', () => {
- cy.get('#add-recipient-button').should('be.visible')
- })
-
- it('add a recipient', () => {
- cy.get('#add-recipient-button').click()
- cy.get('#recipient').should('exist')
- })
-
- it('remove recipient', () => {
- cy.get('#add-recipient-button').click()
- cy.get('#remove-recipient-button').click()
- cy.get('#recipient').should('not.exist')
- })
- })
-})
diff --git a/cypress/support/commands.d.ts b/cypress/support/commands.d.ts
deleted file mode 100644
index e7eba62..0000000
--- a/cypress/support/commands.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-export const TEST_ADDRESS_NEVER_USE: string
-
-export const TEST_ADDRESS_NEVER_USE_SHORTENED: string
-
-// declare namespace Cypress {
-// // eslint-disable-next-line @typescript-eslint/class-name-casing
-// interface cy {
-// additionalCommands(): void
-// }
-// }
diff --git a/cypress/support/commands.js b/cypress/support/commands.js
deleted file mode 100644
index 8e4316a..0000000
--- a/cypress/support/commands.js
+++ /dev/null
@@ -1,82 +0,0 @@
-// ***********************************************
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-
-import { JsonRpcProvider } from '@ethersproject/providers'
-import { Wallet } from '@ethersproject/wallet'
-import { _Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
-
-// never send real ether to this, obviously
-const PRIVATE_KEY_TEST_NEVER_USE = '0xad20c82497421e9784f18460ad2fe84f73569068e98e270b3e63743268af5763'
-
-// address of the above key
-export const TEST_ADDRESS_NEVER_USE = '0x0fF2D1eFd7A57B7562b2bf27F3f37899dB27F4a5'
-
-export const TEST_ADDRESS_NEVER_USE_SHORTENED = '0x0fF2...F4a5'
-
-class CustomizedBridge extends _Eip1193Bridge {
- async sendAsync(...args) {
- console.debug('sendAsync called', ...args)
- return this.send(...args)
- }
- async send(...args) {
- console.debug('send called', ...args)
- const isCallbackForm = typeof args[0] === 'object' && typeof args[1] === 'function'
- let callback
- let method
- let params
- if (isCallbackForm) {
- callback = args[1]
- method = args[0].method
- params = args[0].params
- } else {
- method = args[0]
- params = args[1]
- }
- if (method === 'eth_requestAccounts' || method === 'eth_accounts') {
- if (isCallbackForm) {
- callback({ result: [TEST_ADDRESS_NEVER_USE] })
- } else {
- return Promise.resolve([TEST_ADDRESS_NEVER_USE])
- }
- }
- if (method === 'eth_chainId') {
- if (isCallbackForm) {
- callback(null, { result: '0x4' })
- } else {
- return Promise.resolve('0x4')
- }
- }
- try {
- const result = await super.send(method, params)
- console.debug('result received', method, params, result)
- if (isCallbackForm) {
- callback(null, { result })
- } else {
- return result
- }
- } catch (error) {
- if (isCallbackForm) {
- callback(error, null)
- } else {
- throw error
- }
- }
- }
-}
-
-// sets up the injected provider to be a mock ethereum provider with the given mnemonic/index
-Cypress.Commands.overwrite('visit', (original, url, options) => {
- return original(url.startsWith('/') && url.length > 2 && !url.startsWith('/#') ? `/#${url}` : url, {
- ...options,
- onBeforeLoad(win) {
- options && options.onBeforeLoad && options.onBeforeLoad(win)
- win.localStorage.clear()
- const provider = new JsonRpcProvider('https://rinkeby.infura.io/v3/4bf032f2d38a4ed6bb975b80d6340847', 4)
- const signer = new Wallet(PRIVATE_KEY_TEST_NEVER_USE, provider)
- win.ethereum = new CustomizedBridge(signer, provider)
- },
- })
-})
diff --git a/cypress/support/index.js b/cypress/support/index.js
deleted file mode 100644
index 3d834eb..0000000
--- a/cypress/support/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// ***********************************************************
-// This file is processed and loaded automatically before your test files.
-//
-// You can read more here:
-// https://on.cypress.io/configuration
-// ***********************************************************
-
-// Import commands.ts using ES2015 syntax:
-import './commands'
diff --git a/package.json b/package.json
index dd18e3e..eee32fd 100644
--- a/package.json
+++ b/package.json
@@ -10,15 +10,6 @@
"@reach/dialog": "^0.10.3",
"@reach/portal": "^0.10.3",
"@reduxjs/toolkit": "^1.3.5",
- "@storybook/addon-actions": "^6.1.17",
- "@storybook/addon-essentials": "^6.1.17",
- "@storybook/addon-links": "^6.1.17",
- "@storybook/addons": "^6.1.17",
- "@storybook/components": "^6.1.17",
- "@storybook/preset-create-react-app": "^3.1.5",
- "@storybook/preset-typescript": "^3.0.0",
- "@storybook/react": "^6.1.17",
- "@storybook/theming": "^6.1.17",
"@styled-system/css": "^5.1.5",
"@types/jest": "^25.2.1",
"@types/lodash.flatmap": "^4.5.6",
diff --git a/public/index.html b/public/index.html
index 7edc597..f2c9a9c 100644
--- a/public/index.html
+++ b/public/index.html
@@ -24,7 +24,7 @@
Learn how to configure a non-root public URL by running `npm run build`.
-->
- <title>Uniswap Interface</title>
+ <title>Uniswap Info</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
diff --git a/src/components/AccountDetails/Transaction.tsx b/src/components/AccountDetails/Transaction.tsx
deleted file mode 100644
index 8ffe6ad..0000000
--- a/src/components/AccountDetails/Transaction.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-import { CheckCircle, Triangle } from 'react-feather'
-
-import { useActiveWeb3React } from '../../hooks'
-import { getEtherscanLink } from '../../utils'
-import { ExternalLink } from '../../theme'
-import { useAllTransactions } from '../../state/transactions/hooks'
-import { RowFixed } from '../Row'
-import Loader from '../Loader'
-
-const TransactionWrapper = styled.div``
-
-const TransactionStatusText = styled.div`
- margin-right: 0.5rem;
- display: flex;
- align-items: center;
- :hover {
- text-decoration: underline;
- }
-`
-
-const TransactionState = styled(ExternalLink)<{ pending: boolean; success?: boolean }>`
- display: flex;
- justify-content: space-between;
- align-items: center;
- text-decoration: none !important;
- border-radius: 0.5rem;
- padding: 0.25rem 0rem;
- font-weight: 500;
- font-size: 0.825rem;
- color: ${({ theme }) => theme.primary1};
-`
-
-const IconWrapper = styled.div<{ pending: boolean; success?: boolean }>`
- color: ${({ pending, success, theme }) => (pending ? theme.primary1 : success ? theme.green1 : theme.red1)};
-`
-
-export default function Transaction({ hash }: { hash: string }) {
- const { chainId } = useActiveWeb3React()
- const allTransactions = useAllTransactions()
-
- const tx = allTransactions?.[hash]
- const summary = tx?.summary
- const pending = !tx?.receipt
- const success = !pending && tx && (tx.receipt?.status === 1 || typeof tx.receipt?.status === 'undefined')
-
- if (!chainId) return null
-
- return (
- <TransactionWrapper>
- <TransactionState href={getEtherscanLink(chainId, hash, 'transaction')} pending={pending} success={success}>
- <RowFixed>
- <TransactionStatusText>{summary ?? hash} ↗</TransactionStatusText>
- </RowFixed>
- <IconWrapper pending={pending} success={success}>
- {pending ? <Loader /> : success ? <CheckCircle size="16" /> : <Triangle size="16" />}
- </IconWrapper>
- </TransactionState>
- </TransactionWrapper>
- )
-}
diff --git a/src/components/AccountDetails/index.tsx b/src/components/AccountDetails/index.tsx
index caa7611..4c13dfa 100644
--- a/src/components/AccountDetails/index.tsx
+++ b/src/components/AccountDetails/index.tsx
@@ -1,13 +1,8 @@
-import React, { useCallback, useContext } from 'react'
-import { useDispatch } from 'react-redux'
-import styled, { ThemeContext } from 'styled-components'
+import React from 'react'
+import styled from 'styled-components'
import { useActiveWeb3React } from '../../hooks'
-import { AppDispatch } from '../../state'
-import { clearAllTransactions } from '../../state/transactions/actions'
import { shortenAddress } from '../../utils'
-import { AutoRow } from '../Row'
import Copy from './Copy'
-import Transaction from './Transaction'
import { SUPPORTED_WALLETS } from '../../constants'
import { ReactComponent as Close } from '../../assets/images/x.svg'
import { getEtherscanLink } from '../../utils'
@@ -19,7 +14,7 @@ import PortisIcon from '../../assets/images/portisIcon.png'
import Identicon from '../Identicon'
import { ButtonSecondary } from '../Button'
import { ExternalLink as LinkIcon } from 'react-feather'
-import { ExternalLink, LinkStyledButton, TYPE } from '../../theme'
+import { ExternalLink } from '../../theme'
const HeaderRow = styled.div`
${({ theme }) => theme.flexRowNoWrap};
@@ -92,22 +87,6 @@ const YourAccount = styled.div`
}
`
-const LowerSection = styled.div`
- ${({ theme }) => theme.flexColumnNoWrap}
- padding: 1.5rem;
- flex-grow: 1;
- overflow: auto;
- background-color: ${({ theme }) => theme.bg2};
- border-bottom-left-radius: 20px;
- border-bottom-right-radius: 20px;
-
- h5 {
- margin: 0;
- font-weight: 400;
- color: ${({ theme }) => theme.text3};
- }
-`
-
const AccountControl = styled.div`
display: flex;
justify-content: space-between;
@@ -179,10 +158,6 @@ const IconWrapper = styled.div<{ size?: number }>`
`};
`
-const TransactionListWrapper = styled.div`
- ${({ theme }) => theme.flexColumnNoWrap};
-`
-
const WalletAction = styled(ButtonSecondary)`
width: fit-content;
font-weight: 400;
@@ -199,34 +174,14 @@ const MainWalletAction = styled(WalletAction)`
color: ${({ theme }) => theme.primary1};
`
-function renderTransactions(transactions: string[]) {
- return (
- <TransactionListWrapper>
- {transactions.map((hash, i) => {
- return <Transaction key={i} hash={hash} />
- })}
- </TransactionListWrapper>
- )
-}
-
interface AccountDetailsProps {
toggleWalletModal: () => void
- pendingTransactions: string[]
- confirmedTransactions: string[]
ENSName?: string
openOptions: () => void
}
-export default function AccountDetails({
- toggleWalletModal,
- pendingTransactions,
- confirmedTransactions,
- ENSName,
- openOptions,
-}: AccountDetailsProps) {
+export default function AccountDetails({ toggleWalletModal, ENSName, openOptions }: AccountDetailsProps) {
const { chainId, account, connector } = useActiveWeb3React()
- const theme = useContext(ThemeContext)
- const dispatch = useDispatch<AppDispatch>()
function formatConnectorName() {
const { ethereum } = window
@@ -284,10 +239,6 @@ export default function AccountDetails({
return null
}
- const clearAllTransactionsCallback = useCallback(() => {
- if (chainId) dispatch(clearAllTransactions({ chainId }))
- }, [dispatch, chainId])
-
return (
<>
<UpperSection>
@@ -391,20 +342,6 @@ export default function AccountDetails({
</YourAccount>
</AccountSection>
</UpperSection>
- {!!pendingTransactions.length || !!confirmedTransactions.length ? (
- <LowerSection>
- <AutoRow mb={'1rem'} style={{ justifyContent: 'space-between' }}>
- <TYPE.body>Recent Transactions</TYPE.body>
- <LinkStyledButton onClick={clearAllTransactionsCallback}>(clear all)</LinkStyledButton>
- </AutoRow>
- {renderTransactions(pendingTransactions)}
- {renderTransactions(confirmedTransactions)}
- </LowerSection>
- ) : (
- <LowerSection>
- <TYPE.body color={theme.text1}>Your transactions will appear here...</TYPE.body>
- </LowerSection>
- )}
</>
)
}
diff --git a/src/components/Button/Button.stories.tsx b/src/components/Button/Button.stories.tsx
deleted file mode 100644
index 8b5bb18..0000000
--- a/src/components/Button/Button.stories.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import { Story } from '@storybook/react/types-6-0'
-import styled from 'styled-components'
-import React from 'react'
-import {
- ButtonConfirmed,
- ButtonDropdown,
- ButtonDropdownGrey,
- ButtonDropdownLight,
- ButtonEmpty,
- ButtonError,
- ButtonGray,
- ButtonLight,
- ButtonOutlined,
- ButtonPink,
- ButtonPrimary,
- ButtonRadio,
- ButtonSecondary,
- ButtonUNIGradient,
- ButtonWhite,
-} from './index'
-
-const wrapperCss = styled.main`
- font-size: 2em;
- margin: 3em;
- max-width: 300px;
-`
-
-export default {
- title: 'Buttons',
- argTypes: {
- disabled: { control: { type: 'boolean' } },
- onClick: { action: 'clicked' },
- },
- decorators: [
- (Component: Story) => (
- <div css={wrapperCss}>
- <Component />
- </div>
- ),
- ],
-}
-
-const Unicorn = () => (
- <span role="img" aria-label="unicorn">
- 🦄
- </span>
-)
-
-export const Radio = () => (
- <ButtonRadio>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonRadio>
-)
-export const DropdownLight = () => (
- <ButtonDropdownLight>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonDropdownLight>
-)
-export const DropdownGrey = () => (
- <ButtonDropdownGrey>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonDropdownGrey>
-)
-export const Dropdown = () => (
- <ButtonDropdown>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonDropdown>
-)
-export const Error = () => (
- <ButtonError>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonError>
-)
-export const Confirmed = () => (
- <ButtonConfirmed>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonConfirmed>
-)
-export const White = () => (
- <ButtonWhite>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonWhite>
-)
-export const Empty = () => (
- <ButtonEmpty>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonEmpty>
-)
-export const Outlined = () => (
- <ButtonOutlined>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonOutlined>
-)
-export const UNIGradient = () => (
- <ButtonUNIGradient>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonUNIGradient>
-)
-export const Pink = () => (
- <ButtonPink>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonPink>
-)
-export const Secondary = () => (
- <ButtonSecondary>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonSecondary>
-)
-export const Gray = () => (
- <ButtonGray>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonGray>
-)
-export const Light = () => (
- <ButtonLight>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonLight>
-)
-export const Primary = () => (
- <ButtonPrimary>
- <Unicorn />
- &nbsp;UNISWAP&nbsp;
- <Unicorn />
- </ButtonPrimary>
-)
diff --git a/src/components/CurrencyInputPanel/index.tsx b/src/components/CurrencyInputPanel/index.tsx
deleted file mode 100644
index a960fff..0000000
--- a/src/components/CurrencyInputPanel/index.tsx
+++ /dev/null
@@ -1,248 +0,0 @@
-import { Currency, Pair } from '@uniswap/sdk'
-import React, { useState, useCallback } from 'react'
-import styled from 'styled-components'
-import { darken } from 'polished'
-import { useCurrencyBalance } from '../../state/wallet/hooks'
-import CurrencySearchModal from '../SearchModal/CurrencySearchModal'
-import CurrencyLogo from '../CurrencyLogo'
-import DoubleCurrencyLogo from '../DoubleLogo'
-import { RowBetween } from '../Row'
-import { TYPE } from '../../theme'
-import { Input as NumericalInput } from '../NumericalInput'
-import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
-
-import { useActiveWeb3React } from '../../hooks'
-import { useTranslation } from 'react-i18next'
-import useTheme from '../../hooks/useTheme'
-
-const InputRow = styled.div<{ selected: boolean }>`
- ${({ theme }) => theme.flexRowNoWrap}
- align-items: center;
- padding: ${({ selected }) => (selected ? '0.75rem 0.5rem 0.75rem 1rem' : '0.75rem 0.75rem 0.75rem 1rem')};
-`
-
-const CurrencySelect = styled.button<{ selected: boolean }>`
- align-items: center;
- height: 2.2rem;
- font-size: 20px;
- font-weight: 500;
- background-color: ${({ selected, theme }) => (selected ? theme.bg1 : theme.primary1)};
- color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
- border-radius: 12px;
- box-shadow: ${({ selected }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
- outline: none;
- cursor: pointer;
- user-select: none;
- border: none;
- padding: 0 0.5rem;
-
- :focus,
- :hover {
- background-color: ${({ selected, theme }) => (selected ? theme.bg2 : darken(0.05, theme.primary1))};
- }
-`
-
-const LabelRow = styled.div`
- ${({ theme }) => theme.flexRowNoWrap}
- align-items: center;
- color: ${({ theme }) => theme.text1};
- font-size: 0.75rem;
- line-height: 1rem;
- padding: 0rem 1rem 0.75rem 1rem;
- span:hover {
- cursor: pointer;
- color: ${({ theme }) => darken(0.2, theme.text2)};
- }
-`
-
-const Aligner = styled.span`
- display: flex;
- align-items: center;
- justify-content: space-between;
-`
-
-const StyledDropDown = styled(DropDown)<{ selected: boolean }>`
- margin: 0 0.25rem 0 0.5rem;
- height: 35%;
-
- path {
- stroke: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
- stroke-width: 1.5px;
- }
-`
-
-const InputPanel = styled.div<{ hideInput?: boolean }>`
- ${({ theme }) => theme.flexColumnNoWrap}
- position: relative;
- border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
- background-color: ${({ theme }) => theme.bg2};
- z-index: 1;
-`
-
-const Container = styled.div<{ hideInput: boolean }>`
- border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
- border: 1px solid ${({ theme }) => theme.bg2};
- background-color: ${({ theme }) => theme.bg1};
-`
-
-const StyledTokenName = styled.span<{ active?: boolean }>`
- ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')}
- font-size: ${({ active }) => (active ? '20px' : '16px')};
-`
-
-const StyledBalanceMax = styled.button`
- height: 28px;
- background-color: ${({ theme }) => theme.primary5};
- border: 1px solid ${({ theme }) => theme.primary5};
- border-radius: 0.5rem;
- font-size: 0.875rem;
-
- font-weight: 500;
- cursor: pointer;
- margin-right: 0.5rem;
- color: ${({ theme }) => theme.primaryText1};
- :hover {
- border: 1px solid ${({ theme }) => theme.primary1};
- }
- :focus {
- border: 1px solid ${({ theme }) => theme.primary1};
- outline: none;
- }
-
- ${({ theme }) => theme.mediaWidth.upToExtraSmall`
- margin-right: 0.5rem;
- `};
-`
-
-interface CurrencyInputPanelProps {
- value: string
- onUserInput: (value: string) => void
- onMax?: () => void
- showMaxButton: boolean
- label?: string
- onCurrencySelect?: (currency: Currency) => void
- currency?: Currency | null
- disableCurrencySelect?: boolean
- hideBalance?: boolean
- pair?: Pair | null
- hideInput?: boolean
- otherCurrency?: Currency | null
- id: string
- showCommonBases?: boolean
- customBalanceText?: string
-}
-
-export default function CurrencyInputPanel({
- value,
- onUserInput,
- onMax,
- showMaxButton,
- label = 'Input',
- onCurrencySelect,
- currency,
- disableCurrencySelect = false,
- hideBalance = false,
- pair = null, // used for double token logo
- hideInput = false,
- otherCurrency,
- id,
- showCommonBases,
- customBalanceText,
-}: CurrencyInputPanelProps) {
- const { t } = useTranslation()
-
- const [modalOpen, setModalOpen] = useState(false)
- const { account } = useActiveWeb3React()
- const selectedCurrencyBalance = useCurrencyBalance(account ?? undefined, currency ?? undefined)
- const theme = useTheme()
-
- const handleDismissSearch = useCallback(() => {
- setModalOpen(false)
- }, [setModalOpen])
-
- return (
- <InputPanel id={id}>
- <Container hideInput={hideInput}>
- <InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={disableCurrencySelect}>
- {!hideInput && (
- <>
- <NumericalInput
- className="token-amount-input"
- value={value}
- onUserInput={(val) => {
- onUserInput(val)
- }}
- />
- {account && currency && showMaxButton && label !== 'To' && (
- <StyledBalanceMax onClick={onMax}>MAX</StyledBalanceMax>
- )}
- </>
- )}
- <CurrencySelect
- selected={!!currency}
- className="open-currency-select-button"
- onClick={() => {
- if (!disableCurrencySelect) {
- setModalOpen(true)
- }
- }}
- >
- <Aligner>
- {pair ? (
- <DoubleCurrencyLogo currency0={pair.token0} currency1={pair.token1} size={24} margin={true} />
- ) : currency ? (
- <CurrencyLogo currency={currency} size={'24px'} />
- ) : null}
- {pair ? (
- <StyledTokenName className="pair-name-container">
- {pair?.token0.symbol}:{pair?.token1.symbol}
- </StyledTokenName>
- ) : (
- <StyledTokenName className="token-symbol-container" active={Boolean(currency && currency.symbol)}>
- {(currency && currency.symbol && currency.symbol.length > 20
- ? currency.symbol.slice(0, 4) +
- '...' +
- currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length)
- : currency?.symbol) || t('selectToken')}
- </StyledTokenName>
- )}
- {!disableCurrencySelect && <StyledDropDown selected={!!currency} />}
- </Aligner>
- </CurrencySelect>
- </InputRow>
- {!hideInput && (
- <LabelRow>
- <RowBetween>
- <TYPE.body color={theme.text2} fontWeight={500} fontSize={14}>
- {label}
- </TYPE.body>
- {account && (
- <TYPE.body
- onClick={onMax}
- color={theme.text2}
- fontWeight={500}
- fontSize={14}
- style={{ display: 'inline', cursor: 'pointer' }}
- >
- {!hideBalance && !!currency && selectedCurrencyBalance
- ? (customBalanceText ?? 'Balance: ') + selectedCurrencyBalance?.toSignificant(6)
- : ' -'}
- </TYPE.body>
- )}
- </RowBetween>
- </LabelRow>
- )}
- </Container>
- {!disableCurrencySelect && onCurrencySelect && (
- <CurrencySearchModal
- isOpen={modalOpen}
- onDismiss={handleDismissSearch}
- onCurrencySelect={onCurrencySelect}
- selectedCurrency={currency}
- otherSelectedCurrency={otherCurrency}
- showCommonBases={showCommonBases}
- />
- )}
- </InputPanel>
- )
-}
diff --git a/src/components/Header/UniBalanceContent.tsx b/src/components/Header/UniBalanceContent.tsx
deleted file mode 100644
index 300681a..0000000
--- a/src/components/Header/UniBalanceContent.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-import { ChainId, TokenAmount } from '@uniswap/sdk'
-import React, { useMemo } from 'react'
-import { X } from 'react-feather'
-import styled from 'styled-components'
-import tokenLogo from '../../assets/images/token-logo.png'
-import { UNI } from '../../constants'
-import { useTotalSupply } from '../../data/TotalSupply'
-import { useActiveWeb3React } from '../../hooks'
-import { useMerkleDistributorContract } from '../../hooks/useContract'
-import useCurrentBlockTimestamp from '../../hooks/useCurrentBlockTimestamp'
-import { useTotalUniEarned } from '../../state/stake/hooks'
-import { useAggregateUniBalance, useTokenBalance } from '../../state/wallet/hooks'
-import { ExternalLink, StyledInternalLink, TYPE, UniTokenAnimated } from '../../theme'
-import { computeUniCirculation } from '../../utils/computeUniCirculation'
-import useUSDCPrice from '../../utils/useUSDCPrice'
-import { AutoColumn } from '../Column'
-import { RowBetween } from '../Row'
-import { Break, CardBGImage, CardNoise, CardSection, DataCard } from '../earn/styled'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
-`
-
-const ModalUpper = styled(DataCard)`
- box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
- background: radial-gradient(76.02% 75.41% at 1.84% 0%, #ff007a 0%, #021d43 100%);
- padding: 0.5rem;
-`
-
-const StyledClose = styled(X)`
- position: absolute;
- right: 16px;
- top: 16px;
-
- :hover {
- cursor: pointer;
- }
-`
-
-/**
- * Content for balance stats modal
- */
-export default function UniBalanceContent({ setShowUniBalanceModal }: { setShowUniBalanceModal: any }) {
- const { account, chainId } = useActiveWeb3React()
- const uni = chainId ? UNI[chainId] : undefined
-
- const total = useAggregateUniBalance()
- const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, uni)
- const uniToClaim: TokenAmount | undefined = useTotalUniEarned()
-
- const totalSupply: TokenAmount | undefined = useTotalSupply(uni)
- const uniPrice = useUSDCPrice(uni)
- const blockTimestamp = useCurrentBlockTimestamp()
- const unclaimedUni = useTokenBalance(useMerkleDistributorContract()?.address, uni)
- const circulation: TokenAmount | undefined = useMemo(
- () =>
- blockTimestamp && uni && chainId === ChainId.MAINNET
- ? computeUniCirculation(uni, blockTimestamp, unclaimedUni)
- : totalSupply,
- [blockTimestamp, chainId, totalSupply, unclaimedUni, uni]
- )
-
- return (
- <ContentWrapper gap="lg">
- <ModalUpper>
- <CardBGImage />
- <CardNoise />
- <CardSection gap="md">
- <RowBetween>
- <TYPE.white color="white">Your UNI Breakdown</TYPE.white>
- <StyledClose stroke="white" onClick={() => setShowUniBalanceModal(false)} />
- </RowBetween>
- </CardSection>
- <Break />
- {account && (
- <>
- <CardSection gap="sm">
- <AutoColumn gap="md" justify="center">
- <UniTokenAnimated width="48px" src={tokenLogo} />{' '}
- <TYPE.white fontSize={48} fontWeight={600} color="white">
- {total?.toFixed(2, { groupSeparator: ',' })}
- </TYPE.white>
- </AutoColumn>
- <AutoColumn gap="md">
- <RowBetween>
- <TYPE.white color="white">Balance:</TYPE.white>
- <TYPE.white color="white">{uniBalance?.toFixed(2, { groupSeparator: ',' })}</TYPE.white>
- </RowBetween>
- <RowBetween>
- <TYPE.white color="white">Unclaimed:</TYPE.white>
- <TYPE.white color="white">
- {uniToClaim?.toFixed(4, { groupSeparator: ',' })}{' '}
- {uniToClaim && uniToClaim.greaterThan('0') && (
- <StyledInternalLink onClick={() => setShowUniBalanceModal(false)} to="/uni">
- (claim)
- </StyledInternalLink>
- )}
- </TYPE.white>
- </RowBetween>
- </AutoColumn>
- </CardSection>
- <Break />
- </>
- )}
- <CardSection gap="sm">
- <AutoColumn gap="md">
- <RowBetween>
- <TYPE.white color="white">UNI price:</TYPE.white>
- <TYPE.white color="white">${uniPrice?.toFixed(2) ?? '-'}</TYPE.white>
- </RowBetween>
- <RowBetween>
- <TYPE.white color="white">UNI in circulation:</TYPE.white>
- <TYPE.white color="white">{circulation?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
- </RowBetween>
- <RowBetween>
- <TYPE.white color="white">Total Supply</TYPE.white>
- <TYPE.white color="white">{totalSupply?.toFixed(0, { groupSeparator: ',' })}</TYPE.white>
- </RowBetween>
- {uni && uni.chainId === ChainId.MAINNET ? (
- <ExternalLink href={`https://uniswap.info/token/${uni.address}`}>View UNI Analytics</ExternalLink>
- ) : null}
- </AutoColumn>
- </CardSection>
- </ModalUpper>
- </ContentWrapper>
- )
-}
diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx
index 6c00dc9..81a4101 100644
--- a/src/components/Header/index.tsx
+++ b/src/components/Header/index.tsx
@@ -1,9 +1,8 @@
-import { ChainId, TokenAmount } from '@uniswap/sdk'
-import React, { useState } from 'react'
+import { ChainId } from '@uniswap/sdk'
+import React from 'react'
import { Text } from 'rebass'
import { NavLink } from 'react-router-dom'
import { darken } from 'polished'
-import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
@@ -11,10 +10,7 @@ import Logo from '../../assets/svg/logo.svg'
import LogoDark from '../../assets/svg/logo_white.svg'
import { useActiveWeb3React } from '../../hooks'
import { useDarkModeManager } from '../../state/user/hooks'
-import { useETHBalances, useAggregateUniBalance } from '../../state/wallet/hooks'
-import { CardNoise } from '../earn/styled'
-import { CountUp } from 'use-count-up'
-import { TYPE, ExternalLink } from '../../theme'
+import { useETHBalances } from '../../state/wallet/hooks'
import { YellowCard } from '../Card'
import { Moon, Sun } from 'react-feather'
@@ -22,14 +18,6 @@ import Menu from '../Menu'
import Row, { RowFixed } from '../Row'
import Web3Status from '../Web3Status'
-import ClaimModal from '../claim/ClaimModal'
-import { useToggleSelfClaimModal, useShowClaimPopup } from '../../state/application/hooks'
-import { useUserHasAvailableClaim } from '../../state/claim/hooks'
-import { useUserHasSubmittedClaim } from '../../state/transactions/hooks'
-import { Dots } from '../swap/styleds'
-import Modal from '../Modal'
-import UniBalanceContent from './UniBalanceContent'
-import usePrevious from '../../hooks/usePrevious'
const HeaderFrame = styled.div`
display: grid;
@@ -132,29 +120,6 @@ const AccountElement = styled.div<{ active: boolean }>`
}
`
-const UNIAmount = styled(AccountElement)`
- color: white;
- padding: 4px 8px;
- height: 36px;
- font-weight: 500;
- background-color: ${({ theme }) => theme.bg3};
- background: radial-gradient(174.47% 188.91% at 1.84% 0%, #ff007a 0%, #2172e5 100%), #edeef2;
-`
-
-const UNIWrapper = styled.span`
- width: fit-content;
- position: relative;
- cursor: pointer;
-
- :hover {
- opacity: 0.8;
- }
-
- :active {
- opacity: 0.9;
- }
-`
-
const HideSmall = styled.span`
${({ theme }) => theme.mediaWidth.upToSmall`
display: none;
@@ -180,7 +145,7 @@ const BalanceText = styled(Text)`
`};
`
-const Title = styled.a`
+const Title = styled(NavLink)`
display: flex;
align-items: center;
pointer-events: auto;
@@ -212,42 +177,16 @@ const StyledNavLink = styled(NavLink).attrs({
outline: none;
cursor: pointer;
text-decoration: none;
- color: ${({ theme }) => theme.text2};
- font-size: 1rem;
- width: fit-content;
- margin: 0 12px;
- font-weight: 500;
-
- &.${activeClassName} {
- border-radius: 12px;
- font-weight: 600;
- color: ${({ theme }) => theme.text1};
- }
-
- :hover,
- :focus {
- color: ${({ theme }) => darken(0.1, theme.text1)};
- }
-`
-
-const StyledExternalLink = styled(ExternalLink).attrs({
- activeClassName,
-})<{ isActive?: boolean }>`
- ${({ theme }) => theme.flexRowNoWrap}
- align-items: left;
- border-radius: 3rem;
- outline: none;
- cursor: pointer;
- text-decoration: none;
- color: ${({ theme }) => theme.text2};
+ color: ${({ theme }) => theme.text3};
font-size: 1rem;
width: fit-content;
- margin: 0 12px;
- font-weight: 500;
+ margin: 0 6px;
+ padding: 8px 12px;
+ font-weight: 600;
&.${activeClassName} {
border-radius: 12px;
- font-weight: 600;
+ background-color: ${({ theme }) => theme.bg2};
color: ${({ theme }) => theme.text1};
}
@@ -255,10 +194,6 @@ const StyledExternalLink = styled(ExternalLink).attrs({
:focus {
color: ${({ theme }) => darken(0.1, theme.text1)};
}
-
- ${({ theme }) => theme.mediaWidth.upToExtraSmall`
- display: none;
-`}
`
export const StyledMenuButton = styled.button`
@@ -299,64 +234,35 @@ const NETWORK_LABELS: { [chainId in ChainId]?: string } = {
export default function Header() {
const { account, chainId } = useActiveWeb3React()
- const { t } = useTranslation()
const userEthBalance = useETHBalances(account ? [account] : [])?.[account ?? '']
// const [isDark] = useDarkModeManager()
const [darkMode, toggleDarkMode] = useDarkModeManager()
- const toggleClaimModal = useToggleSelfClaimModal()
-
- const availableClaim: boolean = useUserHasAvailableClaim(account)
-
- const { claimTxn } = useUserHasSubmittedClaim(account ?? undefined)
-
- const aggregateBalance: TokenAmount | undefined = useAggregateUniBalance()
-
- const [showUniBalanceModal, setShowUniBalanceModal] = useState(false)
- const showClaimPopup = useShowClaimPopup()
-
- const countUpValue = aggregateBalance?.toFixed(0) ?? '0'
- const countUpValuePrevious = usePrevious(countUpValue) ?? '0'
-
return (
<HeaderFrame>
- <ClaimModal />
- <Modal isOpen={showUniBalanceModal} onDismiss={() => setShowUniBalanceModal(false)}>
- <UniBalanceContent setShowUniBalanceModal={setShowUniBalanceModal} />
- </Modal>
<HeaderRow>
- <Title href=".">
+ <Title to="/">
<UniIcon>
<img width={'24px'} src={darkMode ? LogoDark : Logo} alt="logo" />
</UniIcon>
</Title>
<HeaderLinks>
- <StyledNavLink id={`swap-nav-link`} to={'/swap'}>
- {t('swap')}
+ <StyledNavLink id={`pool-nav-link`} to={'/'} isActive={(match, { pathname }) => pathname === '/'}>
+ Overview
+ </StyledNavLink>
+ <StyledNavLink id={`swap-nav-link`} to={'/protocol'}>
+ Protocol
</StyledNavLink>
- <StyledNavLink
- id={`pool-nav-link`}
- to={'/pool'}
- isActive={(match, { pathname }) =>
- Boolean(match) ||
- pathname.startsWith('/add') ||
- pathname.startsWith('/remove') ||
- pathname.startsWith('/create') ||
- pathname.startsWith('/find')
- }
- >
- {t('pool')}
+ <StyledNavLink id={`stake-nav-link`} to={'/pools'}>
+ Pools
</StyledNavLink>
- <StyledNavLink id={`stake-nav-link`} to={'/uni'}>
- UNI
+ <StyledNavLink id={`stake-nav-link`} to={'/tokens'}>
+ Tokens
</StyledNavLink>
- <StyledNavLink id={`stake-nav-link`} to={'/vote'}>
- Vote
+ <StyledNavLink id={`stake-nav-link`} to={'/wallet'}>
+ Wallet
</StyledNavLink>
- <StyledExternalLink id={`stake-nav-link`} href={'https://uniswap.info'}>
- Charts <span style={{ fontSize: '11px' }}>↗</span>
- </StyledExternalLink>
</HeaderLinks>
</HeaderRow>
<HeaderControls>
@@ -366,42 +272,6 @@ export default function Header() {
<NetworkCard title={NETWORK_LABELS[chainId]}>{NETWORK_LABELS[chainId]}</NetworkCard>
)}
</HideSmall>
- {availableClaim && !showClaimPopup && (
- <UNIWrapper onClick={toggleClaimModal}>
- <UNIAmount active={!!account && !availableClaim} style={{ pointerEvents: 'auto' }}>
- <TYPE.white padding="0 2px">
- {claimTxn && !claimTxn?.receipt ? <Dots>Claiming UNI</Dots> : 'Claim UNI'}
- </TYPE.white>
- </UNIAmount>
- <CardNoise />
- </UNIWrapper>
- )}
- {!availableClaim && aggregateBalance && (
- <UNIWrapper onClick={() => setShowUniBalanceModal(true)}>
- <UNIAmount active={!!account && !availableClaim} style={{ pointerEvents: 'auto' }}>
- {account && (
- <HideSmall>
- <TYPE.white
- style={{
- paddingRight: '.4rem',
- }}
- >
- <CountUp
- key={countUpValue}
- isCounting
- start={parseFloat(countUpValuePrevious)}
- end={parseFloat(countUpValue)}
- thousandsSeparator={','}
- duration={1}
- />
- </TYPE.white>
- </HideSmall>
- )}
- UNI
- </UNIAmount>
- <CardNoise />
- </UNIWrapper>
- )}
<AccountElement active={!!account} style={{ pointerEvents: 'auto' }}>
{account && userEthBalance ? (
<BalanceText style={{ flexShrink: 0 }} pl="0.75rem" pr="0.5rem" fontWeight={500}>
diff --git a/src/components/InputStepCounter/InputStepCounter.tsx b/src/components/InputStepCounter/InputStepCounter.tsx
deleted file mode 100644
index 61e3852..0000000
--- a/src/components/InputStepCounter/InputStepCounter.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import React, { useState, useCallback, useEffect } from 'react'
-import { OutlineCard } from 'components/Card'
-import { RowBetween } from 'components/Row'
-import { ButtonGray } from 'components/Button'
-import { TYPE } from 'theme'
-import { Input as NumericalInput } from '../NumericalInput'
-import styled, { keyframes, css } from 'styled-components'
-
-const pulse = (color: string) => keyframes`
- 0% {
- box-shadow: 0 0 0 0 ${color};
- }
-
- 70% {
- box-shadow: 0 0 0 2px ${color};
- }
-
- 100% {
- box-shadow: 0 0 0 0 ${color};
- }
-`
-
-const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boolean }>`
- border-color: ${({ active, theme }) => active && theme.blue1};
- padding: 8px 12px;
-
- ${({ pulsing, theme }) =>
- pulsing &&
- css`
- animation: ${pulse(theme.blue1)} 0.8s linear;
- `}
-`
-
-const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
- background-color: ${({ theme }) => theme.bg0};
- text-align: ${({ usePercent }) => (usePercent ? 'right' : 'center')};
- margin-right: 2px;
-`
-
-const ContentWrapper = styled(RowBetween)`
- padding: 0 8px;
- width: 70%;
-`
-
-interface StepCounterProps {
- value: string
- onUserInput: (value: string) => void
- onIncrement?: () => void
- onDecrement?: () => void
- usePercent?: boolean
- prependSymbol?: string | undefined
-}
-
-const StepCounter = ({ value, onUserInput, usePercent = false, prependSymbol }: StepCounterProps) => {
- // for focus state, styled components doesnt let you select input parent container
- const [active, setActive] = useState(false)
-
- // let user type value and only update parent value on blur
- const [localValue, setLocalValue] = useState('')
- const [useLocalValue, setUseLocalValue] = useState(false)
-
- // animation if parent value updates local value
- const [pulsing, setPulsing] = useState<boolean>(false)
-
- const handleOnFocus = () => {
- setUseLocalValue(true)
- setActive(true)
- }
-
- const handleOnBlur = useCallback(() => {
- setUseLocalValue(false)
- setActive(false)
- onUserInput(localValue) // trigger update on parent value
- }, [localValue, onUserInput])
-
- useEffect(() => {
- if (localValue !== value && !useLocalValue) {
- setTimeout(() => {
- setLocalValue(value) // reset local value to match parent
- setPulsing(true) // trigger animation
- setTimeout(function () {
- setPulsing(false)
- }, 1800)
- }, 400)
- }
- }, [localValue, useLocalValue, value])
-
- const handleDeccrement = useCallback(() => {
- localValue && setLocalValue((parseFloat(localValue) * 0.997).toString())
- }, [localValue])
-
- const handleIncrement = useCallback(() => {
- localValue && setLocalValue((parseFloat(localValue) * 1.003).toString())
- }, [localValue])
-
- return (
- <FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur}>
- <RowBetween>
- <ButtonGray padding="2px 0px" borderRadius="8px" onClick={handleDeccrement} width="50px">
- <TYPE.label>-</TYPE.label>
- </ButtonGray>
- <ContentWrapper>
- <StyledInput
- className="rate-input-0"
- value={localValue}
- fontSize="18px"
- onUserInput={(val) => {
- setLocalValue(val)
- }}
- prependSymbol={prependSymbol}
- usePercent={usePercent}
- />
- {usePercent && <TYPE.main>%</TYPE.main>}
- </ContentWrapper>
- <ButtonGray padding="2px 0px" borderRadius="8px" onClick={handleIncrement} width="50px">
- <TYPE.label>+</TYPE.label>
- </ButtonGray>
- </RowBetween>
- </FocusedOutlineCard>
- )
-}
-
-export default StepCounter
diff --git a/src/components/LineChart/LineChart.stories.tsx b/src/components/LineChart/LineChart.stories.tsx
deleted file mode 100644
index effce1d..0000000
--- a/src/components/LineChart/LineChart.stories.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { Story } from '@storybook/react/types-6-0'
-import React from 'react'
-// import Row, { RowFixed } from 'components/Row'
-import styled from 'styled-components'
-import Component, { LineChartProps } from './'
-import { dummyData } from './data'
-// import { AutoColumn } from 'components/Column'
-// import { TYPE } from 'theme'
-// import DoubleCurrencyLogo from 'components/DoubleLogo'
-// import { MKR } from 'constants'
-// import { ETHER } from '@uniswap/sdk'
-// import LineChart from '.'
-
-const Wrapper = styled.div`
- margin: 1em 2em;
- max-width: 500px;
- & > * {
- font-size: 1em;
- }
-`
-
-export default {
- title: 'Charts',
- argTypes: {
- disabled: { control: { type: 'boolean' } },
- onClick: { action: 'clicked' },
- },
- decorators: [
- (Component: Story) => (
- <Wrapper>
- <Component />
- </Wrapper>
- ),
- ],
-}
-
-const Template: Story<LineChartProps> = (args) => <Component {...args}>{args.children}</Component>
-
-export const Basic = Template.bind({})
-Basic.args = { data: dummyData }
-
-// const Full = () => {
-// const [value, setValue] = useState<number | undefined>(dummyData[dummyData.length - 1].value)
-
-// const dummyUSDPrice = 410 // used for conversion
-
-// const TopLeftContent = () => (
-// <AutoColumn gap="md">
-// <RowFixed align="center">
-// <DoubleCurrencyLogo currency0={MKR} currency1={ETHER} size={20} />{' '}
-// <TYPE.main fontSize="20px" color="white" ml="10px">
-// ETH / MKR
-// </TYPE.main>
-// </RowFixed>
-// <Row>
-// <TYPE.main fontSize="20px" color="white">
-// {value} MKR
-// </TYPE.main>
-// <TYPE.main color="#565A69" fontSize="20px" ml="10px">
-// ($
-// {value
-// ? (value * dummyUSDPrice).toLocaleString('USD', {
-// currency: 'USD',
-// minimumFractionDigits: 2
-// })
-// : null}{' '}
-// )
-// </TYPE.main>
-// </Row>
-// </AutoColumn>
-// )
-
-// return (
-// <Wrapper>
-// <LineChart data={dummyData} setValue={setValue} topLeft={<TopLeftContent />} />
-// </Wrapper>
-// )
-// }
-
-// export const FullVersion = Template.bind(() => <LineChart data={dummyData} />)
-// Full.args = { data: dummyData }
-// Full.decorators = [
-// (Story: any) => {
-// return (
-// <Wrapper>
-// <LineChart data={dummyData} />
-// </Wrapper>
-// )
-// }
-// ]
diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx
index 22e16a2..be511b2 100644
--- a/src/components/Menu/index.tsx
+++ b/src/components/Menu/index.tsx
@@ -2,13 +2,11 @@ import React, { useRef } from 'react'
import { BookOpen, Code, Info, MessageCircle, PieChart } from 'react-feather'
import styled from 'styled-components'
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
-import { useActiveWeb3React } from '../../hooks'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { ApplicationModal } from '../../state/application/actions'
import { useModalOpen, useToggleModal } from '../../state/application/hooks'
import { ExternalLink } from '../../theme'
-import { ButtonPrimary } from '../Button'
const StyledMenuIcon = styled(MenuIcon)`
path {
@@ -88,13 +86,10 @@ const MenuItem = styled(ExternalLink)`
const CODE_LINK = 'https://github.com/Uniswap/uniswap-interface'
export default function Menu() {
- const { account } = useActiveWeb3React()
-
const node = useRef<HTMLDivElement>()
const open = useModalOpen(ApplicationModal.MENU)
const toggle = useToggleModal(ApplicationModal.MENU)
useOnClickOutside(node, open ? toggle : undefined)
- const openClaimModal = useToggleModal(ApplicationModal.ADDRESS_CLAIM)
return (
// https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451
@@ -125,11 +120,6 @@ export default function Menu() {
<PieChart size={14} />
Analytics
</MenuItem>
- {account && (
- <ButtonPrimary onClick={openClaimModal} padding="8px 16px" width="100%" borderRadius="12px" mt="0.5rem">
- Claim UNI
- </ButtonPrimary>
- )}
</MenuFlyout>
)}
</StyledMenu>
diff --git a/src/components/ModalViews/index.tsx b/src/components/ModalViews/index.tsx
deleted file mode 100644
index a1b384c..0000000
--- a/src/components/ModalViews/index.tsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import React, { useContext } from 'react'
-import { useActiveWeb3React } from '../../hooks'
-
-import { AutoColumn, ColumnCenter } from '../Column'
-import styled, { ThemeContext } from 'styled-components'
-import { RowBetween } from '../Row'
-import { TYPE, CloseIcon, CustomLightSpinner } from '../../theme'
-import { ArrowUpCircle } from 'react-feather'
-
-import Circle from '../../assets/images/blue-loader.svg'
-import { getEtherscanLink } from '../../utils'
-import { ExternalLink } from '../../theme/components'
-
-const ConfirmOrLoadingWrapper = styled.div`
- width: 100%;
- padding: 24px;
-`
-
-const ConfirmedIcon = styled(ColumnCenter)`
- padding: 60px 0;
-`
-
-export function LoadingView({ children, onDismiss }: { children: any; onDismiss: () => void }) {
- return (
- <ConfirmOrLoadingWrapper>
- <RowBetween>
- <div />
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- <ConfirmedIcon>
- <CustomLightSpinner src={Circle} alt="loader" size={'90px'} />
- </ConfirmedIcon>
- <AutoColumn gap="100px" justify={'center'}>
- {children}
- <TYPE.subHeader>Confirm this transaction in your wallet</TYPE.subHeader>
- </AutoColumn>
- </ConfirmOrLoadingWrapper>
- )
-}
-
-export function SubmittedView({
- children,
- onDismiss,
- hash,
-}: {
- children: any
- onDismiss: () => void
- hash: string | undefined
-}) {
- const theme = useContext(ThemeContext)
- const { chainId } = useActiveWeb3React()
-
- return (
- <ConfirmOrLoadingWrapper>
- <RowBetween>
- <div />
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- <ConfirmedIcon>
- <ArrowUpCircle strokeWidth={0.5} size={90} color={theme.primary1} />
- </ConfirmedIcon>
- <AutoColumn gap="100px" justify={'center'}>
- {children}
- {chainId && hash && (
- <ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ marginLeft: '4px' }}>
- <TYPE.subHeader>View transaction on Etherscan</TYPE.subHeader>
- </ExternalLink>
- )}
- </AutoColumn>
- </ConfirmOrLoadingWrapper>
- )
-}
diff --git a/src/components/NavigationTabs/index.tsx b/src/components/NavigationTabs/index.tsx
deleted file mode 100644
index 0eadd62..0000000
--- a/src/components/NavigationTabs/index.tsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-import { darken } from 'polished'
-import { useTranslation } from 'react-i18next'
-import { NavLink, Link as HistoryLink } from 'react-router-dom'
-
-import { ArrowLeft } from 'react-feather'
-import { RowBetween } from '../Row'
-// import QuestionHelper from '../QuestionHelper'
-import Settings from '../Settings'
-import { useDispatch } from 'react-redux'
-import { AppDispatch } from 'state'
-import { resetMintState } from 'state/mint/actions'
-
-const Tabs = styled.div`
- ${({ theme }) => theme.flexRowNoWrap}
- align-items: center;
- border-radius: 3rem;
- justify-content: space-evenly;
-`
-
-const activeClassName = 'ACTIVE'
-
-const StyledNavLink = styled(NavLink).attrs({
- activeClassName,
-})`
- ${({ theme }) => theme.flexRowNoWrap}
- align-items: center;
- justify-content: center;
- height: 3rem;
- border-radius: 3rem;
- outline: none;
- cursor: pointer;
- text-decoration: none;
- color: ${({ theme }) => theme.text3};
- font-size: 20px;
-
- &.${activeClassName} {
- border-radius: 12px;
- font-weight: 500;
- color: ${({ theme }) => theme.text1};
- }
-
- :hover,
- :focus {
- color: ${({ theme }) => darken(0.1, theme.text1)};
- }
-`
-
-const ActiveText = styled.div`
- font-weight: 500;
- font-size: 20px;
-`
-
-const StyledArrowLeft = styled(ArrowLeft)`
- color: ${({ theme }) => theme.text1};
-`
-
-export function SwapPoolTabs({ active }: { active: 'swap' | 'pool' }) {
- const { t } = useTranslation()
- return (
- <Tabs style={{ marginBottom: '20px', display: 'none' }}>
- <StyledNavLink id={`swap-nav-link`} to={'/swap'} isActive={() => active === 'swap'}>
- {t('swap')}
- </StyledNavLink>
- <StyledNavLink id={`pool-nav-link`} to={'/pool'} isActive={() => active === 'pool'}>
- {t('pool')}
- </StyledNavLink>
- </Tabs>
- )
-}
-
-export function FindPoolTabs() {
- return (
- <Tabs>
- <RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
- <HistoryLink to="/pool">
- <StyledArrowLeft />
- </HistoryLink>
- <ActiveText>Import Pool</ActiveText>
- <Settings />
- </RowBetween>
- </Tabs>
- )
-}
-
-export function AddRemoveTabs({ adding, creating }: { adding: boolean; creating: boolean }) {
- // reset states on back
- const dispatch = useDispatch<AppDispatch>()
-
- return (
- <Tabs>
- <RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
- <HistoryLink
- to="/pool"
- onClick={() => {
- adding && dispatch(resetMintState())
- }}
- >
- <StyledArrowLeft />
- </HistoryLink>
- <ActiveText>{creating ? 'Create a pair' : adding ? 'Add Liquidity' : 'Remove Liquidity'}</ActiveText>
- <Settings />
- </RowBetween>
- </Tabs>
- )
-}
diff --git a/src/components/Popups/ClaimPopup.tsx b/src/components/Popups/ClaimPopup.tsx
deleted file mode 100644
index 7998707..0000000
--- a/src/components/Popups/ClaimPopup.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-import { TokenAmount } from '@uniswap/sdk'
-import React, { useEffect } from 'react'
-import { X } from 'react-feather'
-import styled, { keyframes } from 'styled-components'
-import tokenLogo from '../../assets/images/token-logo.png'
-import { ButtonPrimary } from '../../components/Button'
-import { useActiveWeb3React } from '../../hooks'
-import { ApplicationModal } from '../../state/application/actions'
-import {
- useModalOpen,
- useShowClaimPopup,
- useToggleSelfClaimModal,
- useToggleShowClaimPopup,
-} from '../../state/application/hooks'
-
-import { useUserHasAvailableClaim, useUserUnclaimedAmount } from '../../state/claim/hooks'
-import { TYPE } from '../../theme'
-import { AutoColumn } from '../Column'
-import { CardBGImage, CardNoise } from '../earn/styled'
-
-const StyledClaimPopup = styled(AutoColumn)`
- background: radial-gradient(76.02% 75.41% at 1.84% 0%, #ff007a 0%, #021d43 100%);
- border-radius: 20px;
- padding: 1.5rem;
- overflow: hidden;
- position: relative;
- max-width: 360px;
- box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
-`
-
-const StyledClose = styled(X)`
- position: absolute;
- right: 10px;
- top: 10px;
-
- :hover {
- cursor: pointer;
- }
-`
-
-const rotate = keyframes`
- 0% {
- transform: perspective(1000px) rotateY(0deg);
- }
-
- 100% {
- transform: perspective(1000px) rotateY(360deg);
- }
-`
-
-const UniToken = styled.img`
- animation: ${rotate} 5s cubic-bezier(0.83, 0, 0.17, 1) infinite;
-`
-
-export default function ClaimPopup() {
- const { account } = useActiveWeb3React()
-
- // dont store these in persisted state yet
- const showClaimPopup: boolean = useShowClaimPopup()
- const toggleShowClaimPopup = useToggleShowClaimPopup()
-
- // toggle for showing this modal
- const showClaimModal = useModalOpen(ApplicationModal.SELF_CLAIM)
- const toggleSelfClaimModal = useToggleSelfClaimModal()
-
- // const userHasAvailableclaim = useUserHasAvailableClaim()
- const userHasAvailableclaim: boolean = useUserHasAvailableClaim(account)
- const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
-
- // listen for available claim and show popup if needed
- useEffect(() => {
- if (userHasAvailableclaim) {
- toggleShowClaimPopup()
- }
- // the toggleShowClaimPopup function changes every time the popup changes, so this will cause an infinite loop.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [userHasAvailableclaim])
-
- return (
- <>
- {showClaimPopup && !showClaimModal && (
- <StyledClaimPopup gap="md">
- <CardBGImage />
- <CardNoise />
- <StyledClose stroke="white" onClick={toggleShowClaimPopup} />
- <AutoColumn style={{ padding: '2rem 0', zIndex: 10 }} justify="center">
- <UniToken width="48px" src={tokenLogo} />{' '}
- <TYPE.white style={{ marginTop: '1rem' }} fontSize={36} fontWeight={600}>
- {unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
- </TYPE.white>
- <TYPE.white style={{ paddingTop: '1.25rem', textAlign: 'center' }} fontWeight={600} color="white">
- <span role="img" aria-label="party">
- 🎉
- </span>{' '}
- UNI has arrived{' '}
- <span role="img" aria-label="party">
- 🎉
- </span>
- </TYPE.white>
- <TYPE.subHeader style={{ paddingTop: '0.5rem', textAlign: 'center' }} color="white">
- {`Thanks for being part of the Uniswap community <3`}
- </TYPE.subHeader>
- </AutoColumn>
- <AutoColumn style={{ zIndex: 10 }} justify="center">
- <ButtonPrimary padding="8px" borderRadius="8px" width={'fit-content'} onClick={toggleSelfClaimModal}>
- Claim your UNI tokens
- </ButtonPrimary>
- </AutoColumn>
- </StyledClaimPopup>
- )}
- </>
- )
-}
diff --git a/src/components/Popups/index.tsx b/src/components/Popups/index.tsx
index 935fdc2..5cfa166 100644
--- a/src/components/Popups/index.tsx
+++ b/src/components/Popups/index.tsx
@@ -3,7 +3,6 @@ import styled from 'styled-components'
import { useActivePopups } from '../../state/application/hooks'
import { AutoColumn } from '../Column'
import PopupItem from './PopupItem'
-import ClaimPopup from './ClaimPopup'
import { useURLWarningVisible } from '../../state/user/hooks'
const MobilePopupWrapper = styled.div<{ height: string | number }>`
@@ -53,7 +52,6 @@ export default function Popups() {
return (
<>
<FixedPopupColumn gap="20px" extraPadding={urlWarningActive}>
- <ClaimPopup />
{activePopups.map((item) => (
<PopupItem key={item.key} content={item.content} popKey={item.key} removeAfterMs={item.removeAfterMs} />
))}
diff --git a/src/components/PositionCard/V1.tsx b/src/components/PositionCard/V1.tsx
deleted file mode 100644
index 6e276f5..0000000
--- a/src/components/PositionCard/V1.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { Token, TokenAmount, WETH } from '@uniswap/sdk'
-import React, { useContext } from 'react'
-import { Link, RouteComponentProps, withRouter } from 'react-router-dom'
-import { Text } from 'rebass'
-import { ThemeContext } from 'styled-components'
-import { useActiveWeb3React } from '../../hooks'
-import { ButtonSecondary } from '../Button'
-import { AutoColumn } from '../Column'
-import DoubleCurrencyLogo from '../DoubleLogo'
-import { RowBetween, RowFixed } from '../Row'
-import { FixedHeightRow, HoverCard } from './index'
-
-interface PositionCardProps extends RouteComponentProps<Record<string, any>> {
- token: Token
- V1LiquidityBalance: TokenAmount
-}
-
-function V1PositionCard({ token, V1LiquidityBalance }: PositionCardProps) {
- const theme = useContext(ThemeContext)
-
- const { chainId } = useActiveWeb3React()
-
- return (
- <HoverCard>
- <AutoColumn gap="12px">
- <FixedHeightRow>
- <RowFixed>
- <DoubleCurrencyLogo currency0={token} margin={true} size={20} />
- <Text fontWeight={500} fontSize={20} style={{ marginLeft: '' }}>
- {`${chainId && token.equals(WETH[chainId]) ? 'WETH' : token.symbol}/ETH`}
- </Text>
- <Text
- fontSize={12}
- fontWeight={500}
- ml="0.5rem"
- px="0.75rem"
- py="0.25rem"
- style={{ borderRadius: '1rem' }}
- backgroundColor={theme.yellow1}
- color={'black'}
- >
- V1
- </Text>
- </RowFixed>
- </FixedHeightRow>
-
- <AutoColumn gap="8px">
- <RowBetween marginTop="10px">
- <ButtonSecondary width="68%" as={Link} to={`/migrate/v1/${V1LiquidityBalance.token.address}`}>
- Migrate
- </ButtonSecondary>
-
- <ButtonSecondary
- style={{ backgroundColor: 'transparent' }}
- width="28%"
- as={Link}
- to={`/remove/v1/${V1LiquidityBalance.token.address}`}
- >
- Remove
- </ButtonSecondary>
- </RowBetween>
- </AutoColumn>
- </AutoColumn>
- </HoverCard>
- )
-}
-
-export default withRouter(V1PositionCard)
diff --git a/src/components/PositionCard/index.tsx b/src/components/PositionCard/index.tsx
deleted file mode 100644
index 5166dc2..0000000
--- a/src/components/PositionCard/index.tsx
+++ /dev/null
@@ -1,341 +0,0 @@
-import { JSBI, Pair, Percent, TokenAmount } from '@uniswap/sdk'
-import { darken } from 'polished'
-import React, { useState } from 'react'
-import { ChevronDown, ChevronUp } from 'react-feather'
-import { Link } from 'react-router-dom'
-import { Text } from 'rebass'
-import styled from 'styled-components'
-import { useTotalSupply } from '../../data/TotalSupply'
-
-import { useActiveWeb3React } from '../../hooks'
-import { useTokenBalance } from '../../state/wallet/hooks'
-import { ExternalLink, TYPE } from '../../theme'
-import { currencyId } from '../../utils/currencyId'
-import { unwrappedToken } from '../../utils/wrappedCurrency'
-import { ButtonPrimary, ButtonSecondary, ButtonEmpty } from '../Button'
-import { transparentize } from 'polished'
-import { CardNoise } from '../earn/styled'
-
-import { useColor } from '../../hooks/useColor'
-
-import Card, { GreyCard, LightCard } from '../Card'
-import { AutoColumn } from '../Column'
-import CurrencyLogo from '../CurrencyLogo'
-import DoubleCurrencyLogo from '../DoubleLogo'
-import { RowBetween, RowFixed, AutoRow } from '../Row'
-import { Dots } from '../swap/styleds'
-import { BIG_INT_ZERO } from '../../constants'
-
-export const FixedHeightRow = styled(RowBetween)`
- height: 24px;
-`
-
-export const HoverCard = styled(Card)`
- border: 1px solid transparent;
- :hover {
- border: 1px solid ${({ theme }) => darken(0.06, theme.bg2)};
- }
-`
-const StyledPositionCard = styled(LightCard)<{ bgColor: any }>`
- border: none;
- background: ${({ theme, bgColor }) =>
- `radial-gradient(91.85% 100% at 1.84% 0%, ${transparentize(0.8, bgColor)} 0%, ${theme.bg3} 100%) `};
- position: relative;
- overflow: hidden;
-`
-
-interface PositionCardProps {
- pair: Pair
- showUnwrapped?: boolean
- border?: string
- stakedBalance?: TokenAmount // optional balance to indicate that liquidity is deposited in mining pool
-}
-
-export function MinimalPositionCard({ pair, showUnwrapped = false, border }: PositionCardProps) {
- const { account } = useActiveWeb3React()
-
- const currency0 = showUnwrapped ? pair.token0 : unwrappedToken(pair.token0)
- const currency1 = showUnwrapped ? pair.token1 : unwrappedToken(pair.token1)
-
- const [showMore, setShowMore] = useState(false)
-
- const userPoolBalance = useTokenBalance(account ?? undefined, pair.liquidityToken)
- const totalPoolTokens = useTotalSupply(pair.liquidityToken)
-
- const poolTokenPercentage =
- !!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
- ? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
- : undefined
-
- const [token0Deposited, token1Deposited] =
- !!pair &&
- !!totalPoolTokens &&
- !!userPoolBalance &&
- // this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
- JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
- ? [
- pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
- pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
- ]
- : [undefined, undefined]
-
- return (
- <>
- {userPoolBalance && JSBI.greaterThan(userPoolBalance.raw, JSBI.BigInt(0)) ? (
- <GreyCard border={border}>
- <AutoColumn gap="12px">
- <FixedHeightRow>
- <RowFixed>
- <Text fontWeight={500} fontSize={16}>
- Your position
- </Text>
- </RowFixed>
- </FixedHeightRow>
- <FixedHeightRow onClick={() => setShowMore(!showMore)}>
- <RowFixed>
- <DoubleCurrencyLogo currency0={currency0} currency1={currency1} margin={true} size={20} />
- <Text fontWeight={500} fontSize={20}>
- {currency0.symbol}/{currency1.symbol}
- </Text>
- </RowFixed>
- <RowFixed>
- <Text fontWeight={500} fontSize={20}>
- {userPoolBalance ? userPoolBalance.toSignificant(4) : '-'}
- </Text>
- </RowFixed>
- </FixedHeightRow>
- <AutoColumn gap="4px">
- <FixedHeightRow>
- <Text fontSize={16} fontWeight={500}>
- Your pool share:
- </Text>
- <Text fontSize={16} fontWeight={500}>
- {poolTokenPercentage ? poolTokenPercentage.toFixed(6) + '%' : '-'}
- </Text>
- </FixedHeightRow>
- <FixedHeightRow>
- <Text fontSize={16} fontWeight={500}>
- {currency0.symbol}:
- </Text>
- {token0Deposited ? (
- <RowFixed>
- <Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
- {token0Deposited?.toSignificant(6)}
- </Text>
- </RowFixed>
- ) : (
- '-'
- )}
- </FixedHeightRow>
- <FixedHeightRow>
- <Text fontSize={16} fontWeight={500}>
- {currency1.symbol}:
- </Text>
- {token1Deposited ? (
- <RowFixed>
- <Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
- {token1Deposited?.toSignificant(6)}
- </Text>
- </RowFixed>
- ) : (
- '-'
- )}
- </FixedHeightRow>
- </AutoColumn>
- </AutoColumn>
- </GreyCard>
- ) : (
- <LightCard>
- <TYPE.subHeader style={{ textAlign: 'center' }}>
- <span role="img" aria-label="wizard-icon">
- ⭐️
- </span>{' '}
- By adding liquidity you&apos;ll earn 0.3% of all trades on this pair proportional to your share of the pool.
- Fees are added to the pool, accrue in real time and can be claimed by withdrawing your liquidity.
- </TYPE.subHeader>
- </LightCard>
- )}
- </>
- )
-}
-
-export default function FullPositionCard({ pair, border, stakedBalance }: PositionCardProps) {
- const { account } = useActiveWeb3React()
-
- const currency0 = unwrappedToken(pair.token0)
- const currency1 = unwrappedToken(pair.token1)
-
- const [showMore, setShowMore] = useState(false)
-
- const userDefaultPoolBalance = useTokenBalance(account ?? undefined, pair.liquidityToken)
- const totalPoolTokens = useTotalSupply(pair.liquidityToken)
-
- // if staked balance balance provided, add to standard liquidity amount
- const userPoolBalance = stakedBalance ? userDefaultPoolBalance?.add(stakedBalance) : userDefaultPoolBalance
-
- const poolTokenPercentage =
- !!userPoolBalance && !!totalPoolTokens && JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
- ? new Percent(userPoolBalance.raw, totalPoolTokens.raw)
- : undefined
-
- const [token0Deposited, token1Deposited] =
- !!pair &&
- !!totalPoolTokens &&
- !!userPoolBalance &&
- // this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
- JSBI.greaterThanOrEqual(totalPoolTokens.raw, userPoolBalance.raw)
- ? [
- pair.getLiquidityValue(pair.token0, totalPoolTokens, userPoolBalance, false),
- pair.getLiquidityValue(pair.token1, totalPoolTokens, userPoolBalance, false),
- ]
- : [undefined, undefined]
-
- const backgroundColor = useColor(pair?.token0)
-
- return (
- <StyledPositionCard border={border} bgColor={backgroundColor}>
- <CardNoise />
- <AutoColumn gap="12px">
- <FixedHeightRow>
- <AutoRow gap="8px">
- <DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={20} />
- <Text fontWeight={500} fontSize={20}>
- {!currency0 || !currency1 ? <Dots>Loading</Dots> : `${currency0.symbol}/${currency1.symbol}`}
- </Text>
- </AutoRow>
- <RowFixed gap="8px">
- <ButtonEmpty
- padding="6px 8px"
- borderRadius="12px"
- width="fit-content"
- onClick={() => setShowMore(!showMore)}
- >
- {showMore ? (
- <>
- Manage
- <ChevronUp size="20" style={{ marginLeft: '10px' }} />
- </>
- ) : (
- <>
- Manage
- <ChevronDown size="20" style={{ marginLeft: '10px' }} />
- </>
- )}
- </ButtonEmpty>
- </RowFixed>
- </FixedHeightRow>
-
- {showMore && (
- <AutoColumn gap="8px">
- <FixedHeightRow>
- <Text fontSize={16} fontWeight={500}>
- Your total pool tokens:
- </Text>
- <Text fontSize={16} fontWeight={500}>
- {userPoolBalance ? userPoolBalance.toSignificant(4) : '-'}
- </Text>
- </FixedHeightRow>
- {stakedBalance && (
- <FixedHeightRow>
- <Text fontSize={16} fontWeight={500}>
- Pool tokens in rewards pool:
- </Text>
- <Text fontSize={16} fontWeight={500}>
- {stakedBalance.toSignificant(4)}
- </Text>
- </FixedHeightRow>
- )}
- <FixedHeightRow>
- <RowFixed>
- <Text fontSize={16} fontWeight={500}>
- Pooled {currency0.symbol}:
- </Text>
- </RowFixed>
- {token0Deposited ? (
- <RowFixed>
- <Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
- {token0Deposited?.toSignificant(6)}
- </Text>
- <CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency0} />
- </RowFixed>
- ) : (
- '-'
- )}
- </FixedHeightRow>
-
- <FixedHeightRow>
- <RowFixed>
- <Text fontSize={16} fontWeight={500}>
- Pooled {currency1.symbol}:
- </Text>
- </RowFixed>
- {token1Deposited ? (
- <RowFixed>
- <Text fontSize={16} fontWeight={500} marginLeft={'6px'}>
- {token1Deposited?.toSignificant(6)}
- </Text>
- <CurrencyLogo size="20px" style={{ marginLeft: '8px' }} currency={currency1} />
- </RowFixed>
- ) : (
- '-'
- )}
- </FixedHeightRow>
-
- <FixedHeightRow>
- <Text fontSize={16} fontWeight={500}>
- Your pool share:
- </Text>
- <Text fontSize={16} fontWeight={500}>
- {poolTokenPercentage
- ? (poolTokenPercentage.toFixed(2) === '0.00' ? '<0.01' : poolTokenPercentage.toFixed(2)) + '%'
- : '-'}
- </Text>
- </FixedHeightRow>
-
- <ButtonSecondary padding="8px" borderRadius="8px">
- <ExternalLink
- style={{ width: '100%', textAlign: 'center' }}
- href={`https://uniswap.info/account/${account}`}
- >
- View accrued fees and analytics<span style={{ fontSize: '11px' }}>↗</span>
- </ExternalLink>
- </ButtonSecondary>
- {userDefaultPoolBalance && JSBI.greaterThan(userDefaultPoolBalance.raw, BIG_INT_ZERO) && (
- <RowBetween marginTop="10px">
- <ButtonPrimary
- padding="8px"
- borderRadius="8px"
- as={Link}
- to={`/add/${currencyId(currency0)}/${currencyId(currency1)}`}
- width="48%"
- >
- Add
- </ButtonPrimary>
- <ButtonPrimary
- padding="8px"
- borderRadius="8px"
- as={Link}
- width="48%"
- to={`/remove/${currencyId(currency0)}/${currencyId(currency1)}`}
- >
- Remove
- </ButtonPrimary>
- </RowBetween>
- )}
- {stakedBalance && JSBI.greaterThan(stakedBalance.raw, BIG_INT_ZERO) && (
- <ButtonPrimary
- padding="8px"
- borderRadius="8px"
- as={Link}
- to={`/uni/${currencyId(currency0)}/${currencyId(currency1)}`}
- width="100%"
- >
- Manage Liquidity in Rewards Pool
- </ButtonPrimary>
- )}
- </AutoColumn>
- )}
- </AutoColumn>
- </StyledPositionCard>
- )
-}
diff --git a/src/components/ProgressSteps/index.tsx b/src/components/ProgressSteps/index.tsx
deleted file mode 100644
index cbe573d..0000000
--- a/src/components/ProgressSteps/index.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-import { RowBetween } from '../Row'
-import { AutoColumn } from '../Column'
-import { transparentize } from 'polished'
-
-const Wrapper = styled(AutoColumn)``
-
-const Grouping = styled(RowBetween)`
- width: 50%;
-`
-
-const Circle = styled.div<{ confirmed?: boolean; disabled?: boolean }>`
- min-width: 20px;
- min-height: 20px;
- background-color: ${({ theme, confirmed, disabled }) =>
- disabled ? theme.bg4 : confirmed ? theme.green1 : theme.primary1};
- border-radius: 50%;
- color: ${({ theme }) => theme.white};
- display: flex;
- align-items: center;
- justify-content: center;
- line-height: 8px;
- font-size: 12px;
-`
-
-const CircleRow = styled.div`
- width: calc(100% - 20px);
- display: flex;
- align-items: center;
-`
-
-const Connector = styled.div<{ prevConfirmed?: boolean; disabled?: boolean }>`
- width: 100%;
- height: 2px;
- background-color: ;
- background: linear-gradient(
- 90deg,
- ${({ theme, prevConfirmed, disabled }) =>
- disabled ? theme.bg4 : transparentize(0.5, prevConfirmed ? theme.green1 : theme.primary1)}
- 0%,
- ${({ theme, prevConfirmed, disabled }) => (disabled ? theme.bg4 : prevConfirmed ? theme.primary1 : theme.bg4)} 80%
- );
- opacity: 0.6;
-`
-
-interface ProgressCirclesProps {
- steps: boolean[]
- disabled?: boolean
-}
-
-/**
- * Based on array of steps, create a step counter of circles.
- * A circle can be enabled, disabled, or confirmed. States are derived
- * from previous step.
- *
- * An extra circle is added to represent the ability to swap, add, or remove.
- * This step will never be marked as complete (because no 'txn done' state in body ui).
- *
- * @param steps array of booleans where true means step is complete
- */
-export default function ProgressCircles({ steps, disabled = false, ...rest }: ProgressCirclesProps) {
- return (
- <Wrapper justify={'center'} {...rest}>
- <Grouping>
- {steps.map((step, i) => {
- return (
- <CircleRow key={i}>
- <Circle confirmed={step} disabled={disabled || (!steps[i - 1] && i !== 0)}>
- {step ? '✓' : i + 1}
- </Circle>
- <Connector prevConfirmed={step} disabled={disabled} />
- </CircleRow>
- )
- })}
- <Circle disabled={disabled || !steps[steps.length - 1]}>{steps.length + 1}</Circle>
- </Grouping>
- </Wrapper>
- )
-}
diff --git a/src/components/SearchModal/CommonBases.tsx b/src/components/SearchModal/CommonBases.tsx
deleted file mode 100644
index 30c7e9b..0000000
--- a/src/components/SearchModal/CommonBases.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React from 'react'
-import { Text } from 'rebass'
-import { ChainId, Currency, currencyEquals, ETHER, Token } from '@uniswap/sdk'
-import styled from 'styled-components'
-
-import { SUGGESTED_BASES } from '../../constants'
-import { AutoColumn } from '../Column'
-import QuestionHelper from '../QuestionHelper'
-import { AutoRow } from '../Row'
-import CurrencyLogo from '../CurrencyLogo'
-
-const BaseWrapper = styled.div<{ disable?: boolean }>`
- border: 1px solid ${({ theme, disable }) => (disable ? 'transparent' : theme.bg3)};
- border-radius: 10px;
- display: flex;
- padding: 6px;
-
- align-items: center;
- :hover {
- cursor: ${({ disable }) => !disable && 'pointer'};
- background-color: ${({ theme, disable }) => !disable && theme.bg2};
- }
-
- background-color: ${({ theme, disable }) => disable && theme.bg3};
- opacity: ${({ disable }) => disable && '0.4'};
-`
-
-export default function CommonBases({
- chainId,
- onSelect,
- selectedCurrency,
-}: {
- chainId?: ChainId
- selectedCurrency?: Currency | null
- onSelect: (currency: Currency) => void
-}) {
- return (
- <AutoColumn gap="md">
- <AutoRow>
- <Text fontWeight={500} fontSize={14}>
- Common bases
- </Text>
- <QuestionHelper text="These tokens are commonly paired with other tokens." />
- </AutoRow>
- <AutoRow gap="4px">
- <BaseWrapper
- onClick={() => {
- if (!selectedCurrency || !currencyEquals(selectedCurrency, ETHER)) {
- onSelect(ETHER)
- }
- }}
- disable={selectedCurrency === ETHER}
- >
- <CurrencyLogo currency={ETHER} style={{ marginRight: 8 }} />
- <Text fontWeight={500} fontSize={16}>
- ETH
- </Text>
- </BaseWrapper>
- {(chainId ? SUGGESTED_BASES[chainId] : []).map((token: Token) => {
- const selected = selectedCurrency instanceof Token && selectedCurrency.address === token.address
- return (
- <BaseWrapper onClick={() => !selected && onSelect(token)} disable={selected} key={token.address}>
- <CurrencyLogo currency={token} style={{ marginRight: 8 }} />
- <Text fontWeight={500} fontSize={16}>
- {token.symbol}
- </Text>
- </BaseWrapper>
- )
- })}
- </AutoRow>
- </AutoColumn>
- )
-}
diff --git a/src/components/SearchModal/CurrencyList.tsx b/src/components/SearchModal/CurrencyList.tsx
deleted file mode 100644
index 4dd1ae1..0000000
--- a/src/components/SearchModal/CurrencyList.tsx
+++ /dev/null
@@ -1,263 +0,0 @@
-import { Currency, CurrencyAmount, currencyEquals, ETHER, Token } from '@uniswap/sdk'
-import React, { CSSProperties, MutableRefObject, useCallback, useMemo } from 'react'
-import { FixedSizeList } from 'react-window'
-import { Text } from 'rebass'
-import styled from 'styled-components'
-import { useActiveWeb3React } from '../../hooks'
-import { WrappedTokenInfo, useCombinedActiveList } from '../../state/lists/hooks'
-import { useCurrencyBalance } from '../../state/wallet/hooks'
-import { TYPE } from '../../theme'
-import { useIsUserAddedToken, useAllInactiveTokens } from '../../hooks/Tokens'
-import Column from '../Column'
-import { RowFixed, RowBetween } from '../Row'
-import CurrencyLogo from '../CurrencyLogo'
-import { MouseoverTooltip } from '../Tooltip'
-import { MenuItem } from './styleds'
-import Loader from '../Loader'
-import { isTokenOnList } from '../../utils'
-import ImportRow from './ImportRow'
-import { wrappedCurrency } from 'utils/wrappedCurrency'
-import { LightGreyCard } from 'components/Card'
-import TokenListLogo from '../../assets/svg/tokenlist.svg'
-import QuestionHelper from 'components/QuestionHelper'
-import useTheme from 'hooks/useTheme'
-
-function currencyKey(currency: Currency): string {
- return currency instanceof Token ? currency.address : currency === ETHER ? 'ETHER' : ''
-}
-
-const StyledBalanceText = styled(Text)`
- white-space: nowrap;
- overflow: hidden;
- max-width: 5rem;
- text-overflow: ellipsis;
-`
-
-const Tag = styled.div`
- background-color: ${({ theme }) => theme.bg3};
- color: ${({ theme }) => theme.text2};
- font-size: 14px;
- border-radius: 4px;
- padding: 0.25rem 0.3rem 0.25rem 0.3rem;
- max-width: 6rem;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- justify-self: flex-end;
- margin-right: 4px;
-`
-
-const FixedContentRow = styled.div`
- padding: 4px 20px;
- height: 56px;
- display: grid;
- grid-gap: 16px;
- align-items: center;
-`
-
-function Balance({ balance }: { balance: CurrencyAmount }) {
- return <StyledBalanceText title={balance.toExact()}>{balance.toSignificant(4)}</StyledBalanceText>
-}
-
-const TagContainer = styled.div`
- display: flex;
- justify-content: flex-end;
-`
-
-const TokenListLogoWrapper = styled.img`
- height: 20px;
-`
-
-function TokenTags({ currency }: { currency: Currency }) {
- if (!(currency instanceof WrappedTokenInfo)) {
- return <span />
- }
-
- const tags = currency.tags
- if (!tags || tags.length === 0) return <span />
-
- const tag = tags[0]
-
- return (
- <TagContainer>
- <MouseoverTooltip text={tag.description}>
- <Tag key={tag.id}>{tag.name}</Tag>
- </MouseoverTooltip>
- {tags.length > 1 ? (
- <MouseoverTooltip
- text={tags
- .slice(1)
- .map(({ name, description }) => `${name}: ${description}`)
- .join('; \n')}
- >
- <Tag>...</Tag>
- </MouseoverTooltip>
- ) : null}
- </TagContainer>
- )
-}
-
-function CurrencyRow({
- currency,
- onSelect,
- isSelected,
- otherSelected,
- style,
-}: {
- currency: Currency
- onSelect: () => void
- isSelected: boolean
- otherSelected: boolean
- style: CSSProperties
-}) {
- const { account } = useActiveWeb3React()
- const key = currencyKey(currency)
- const selectedTokenList = useCombinedActiveList()
- const isOnSelectedList = isTokenOnList(selectedTokenList, currency)
- const customAdded = useIsUserAddedToken(currency)
- const balance = useCurrencyBalance(account ?? undefined, currency)
-
- // only show add or remove buttons if not on selected list
- return (
- <MenuItem
- style={style}
- className={`token-item-${key}`}
- onClick={() => (isSelected ? null : onSelect())}
- disabled={isSelected}
- selected={otherSelected}
- >
- <CurrencyLogo currency={currency} size={'24px'} />
- <Column>
- <Text title={currency.name} fontWeight={500}>
- {currency.symbol}
- </Text>
- <TYPE.darkGray ml="0px" fontSize={'12px'} fontWeight={300}>
- {currency.name} {!isOnSelectedList && customAdded && '• Added by user'}
- </TYPE.darkGray>
- </Column>
- <TokenTags currency={currency} />
- <RowFixed style={{ justifySelf: 'flex-end' }}>
- {balance ? <Balance balance={balance} /> : account ? <Loader /> : null}
- </RowFixed>
- </MenuItem>
- )
-}
-
-export default function CurrencyList({
- height,
- currencies,
- selectedCurrency,
- onCurrencySelect,
- otherCurrency,
- fixedListRef,
- showETH,
- showImportView,
- setImportToken,
- breakIndex,
-}: {
- height: number
- currencies: Currency[]
- selectedCurrency?: Currency | null
- onCurrencySelect: (currency: Currency) => void
- otherCurrency?: Currency | null
- fixedListRef?: MutableRefObject<FixedSizeList | undefined>
- showETH: boolean
- showImportView: () => void
- setImportToken: (token: Token) => void
- breakIndex: number | undefined
-}) {
- const itemData: (Currency | undefined)[] = useMemo(() => {
- let formatted: (Currency | undefined)[] = showETH ? [Currency.ETHER, ...currencies] : currencies
- if (breakIndex !== undefined) {
- formatted = [...formatted.slice(0, breakIndex), undefined, ...formatted.slice(breakIndex, formatted.length)]
- }
- return formatted
- }, [breakIndex, currencies, showETH])
-
- const { chainId } = useActiveWeb3React()
- const theme = useTheme()
-
- const inactiveTokens: {
- [address: string]: Token
- } = useAllInactiveTokens()
-
- const Row = useCallback(
- ({ data, index, style }) => {
- const currency: Currency = data[index]
- const isSelected = Boolean(selectedCurrency && currencyEquals(selectedCurrency, currency))
- const otherSelected = Boolean(otherCurrency && currencyEquals(otherCurrency, currency))
- const handleSelect = () => onCurrencySelect(currency)
-
- const token = wrappedCurrency(currency, chainId)
-
- const showImport = inactiveTokens && token && Object.keys(inactiveTokens).includes(token.address)
-
- if (index === breakIndex || !data) {
- return (
- <FixedContentRow style={style}>
- <LightGreyCard padding="8px 12px" borderRadius="8px">
- <RowBetween>
- <RowFixed>
- <TokenListLogoWrapper src={TokenListLogo} />
- <TYPE.main ml="6px" fontSize="12px" color={theme.text1}>
- Expanded results from inactive Token Lists
- </TYPE.main>
- </RowFixed>
- <QuestionHelper text="Tokens from inactive lists. Import specific tokens below or click 'Manage' to activate more lists." />
- </RowBetween>
- </LightGreyCard>
- </FixedContentRow>
- )
- }
-
- if (showImport && token) {
- return (
- <ImportRow
- style={style}
- token={token}
- showImportView={showImportView}
- setImportToken={setImportToken}
- dim={true}
- />
- )
- } else {
- return (
- <CurrencyRow
- style={style}
- currency={currency}
- isSelected={isSelected}
- onSelect={handleSelect}
- otherSelected={otherSelected}
- />
- )
- }
- },
- [
- chainId,
- inactiveTokens,
- onCurrencySelect,
- otherCurrency,
- selectedCurrency,
- setImportToken,
- showImportView,
- breakIndex,
- theme.text1,
- ]
- )
-
- const itemKey = useCallback((index: number, data: any) => currencyKey(data[index]), [])
-
- return (
- <FixedSizeList
- height={height}
- ref={fixedListRef as any}
- width="100%"
- itemData={itemData}
- itemCount={itemData.length}
- itemSize={56}
- itemKey={itemKey}
- >
- {Row}
- </FixedSizeList>
- )
-}
diff --git a/src/components/SearchModal/CurrencySearch.tsx b/src/components/SearchModal/CurrencySearch.tsx
deleted file mode 100644
index a55763b..0000000
--- a/src/components/SearchModal/CurrencySearch.tsx
+++ /dev/null
@@ -1,234 +0,0 @@
-import { Currency, ETHER, Token } from '@uniswap/sdk'
-import React, { KeyboardEvent, RefObject, useCallback, useEffect, useMemo, useRef, useState } from 'react'
-import ReactGA from 'react-ga'
-import { useTranslation } from 'react-i18next'
-import { FixedSizeList } from 'react-window'
-import { Text } from 'rebass'
-import { useActiveWeb3React } from '../../hooks'
-import { useAllTokens, useToken, useIsUserAddedToken, useFoundOnInactiveList } from '../../hooks/Tokens'
-import { CloseIcon, TYPE, ButtonText, IconWrapper } from '../../theme'
-import { isAddress } from '../../utils'
-import Column from '../Column'
-import Row, { RowBetween, RowFixed } from '../Row'
-import CommonBases from './CommonBases'
-import CurrencyList from './CurrencyList'
-import { filterTokens, useSortedTokensByQuery } from './filtering'
-import { useTokenComparator } from './sorting'
-import { PaddedColumn, SearchInput, Separator } from './styleds'
-import AutoSizer from 'react-virtualized-auto-sizer'
-import styled from 'styled-components'
-import useToggle from 'hooks/useToggle'
-import { useOnClickOutside } from 'hooks/useOnClickOutside'
-import useTheme from 'hooks/useTheme'
-import ImportRow from './ImportRow'
-import { Edit } from 'react-feather'
-import useDebounce from 'hooks/useDebounce'
-
-const ContentWrapper = styled(Column)`
- width: 100%;
- flex: 1 1;
- position: relative;
-`
-
-const Footer = styled.div`
- width: 100%;
- border-radius: 20px;
- padding: 20px;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- background-color: ${({ theme }) => theme.bg1};
- border-top: 1px solid ${({ theme }) => theme.bg2};
-`
-
-interface CurrencySearchProps {
- isOpen: boolean
- onDismiss: () => void
- selectedCurrency?: Currency | null
- onCurrencySelect: (currency: Currency) => void
- otherSelectedCurrency?: Currency | null
- showCommonBases?: boolean
- showManageView: () => void
- showImportView: () => void
- setImportToken: (token: Token) => void
-}
-
-export function CurrencySearch({
- selectedCurrency,
- onCurrencySelect,
- otherSelectedCurrency,
- showCommonBases,
- onDismiss,
- isOpen,
- showManageView,
- showImportView,
- setImportToken,
-}: CurrencySearchProps) {
- const { t } = useTranslation()
- const { chainId } = useActiveWeb3React()
- const theme = useTheme()
-
- // refs for fixed size lists
- const fixedList = useRef<FixedSizeList>()
-
- const [searchQuery, setSearchQuery] = useState<string>('')
- const debouncedQuery = useDebounce(searchQuery, 200)
-
- const [invertSearchOrder] = useState<boolean>(false)
-
- const allTokens = useAllTokens()
-
- // if they input an address, use it
- const isAddressSearch = isAddress(debouncedQuery)
- const searchToken = useToken(debouncedQuery)
- const searchTokenIsAdded = useIsUserAddedToken(searchToken)
-
- useEffect(() => {
- if (isAddressSearch) {
- ReactGA.event({
- category: 'Currency Select',
- action: 'Search by address',
- label: isAddressSearch,
- })
- }
- }, [isAddressSearch])
-
- const showETH: boolean = useMemo(() => {
- const s = debouncedQuery.toLowerCase().trim()
- return s === '' || s === 'e' || s === 'et' || s === 'eth'
- }, [debouncedQuery])
-
- const tokenComparator = useTokenComparator(invertSearchOrder)
-
- const filteredTokens: Token[] = useMemo(() => {
- return filterTokens(Object.values(allTokens), debouncedQuery)
- }, [allTokens, debouncedQuery])
-
- const sortedTokens: Token[] = useMemo(() => {
- return filteredTokens.sort(tokenComparator)
- }, [filteredTokens, tokenComparator])
-
- const filteredSortedTokens = useSortedTokensByQuery(sortedTokens, debouncedQuery)
-
- const handleCurrencySelect = useCallback(
- (currency: Currency) => {
- onCurrencySelect(currency)
- onDismiss()
- },
- [onDismiss, onCurrencySelect]
- )
-
- // clear the input on open
- useEffect(() => {
- if (isOpen) setSearchQuery('')
- }, [isOpen])
-
- // manage focus on modal show
- const inputRef = useRef<HTMLInputElement>()
- const handleInput = useCallback((event) => {
- const input = event.target.value
- const checksummedInput = isAddress(input)
- setSearchQuery(checksummedInput || input)
- fixedList.current?.scrollTo(0)
- }, [])
-
- const handleEnter = useCallback(
- (e: KeyboardEvent<HTMLInputElement>) => {
- if (e.key === 'Enter') {
- const s = debouncedQuery.toLowerCase().trim()
- if (s === 'eth') {
- handleCurrencySelect(ETHER)
- } else if (filteredSortedTokens.length > 0) {
- if (
- filteredSortedTokens[0].symbol?.toLowerCase() === debouncedQuery.trim().toLowerCase() ||
- filteredSortedTokens.length === 1
- ) {
- handleCurrencySelect(filteredSortedTokens[0])
- }
- }
- }
- },
- [filteredSortedTokens, handleCurrencySelect, debouncedQuery]
- )
-
- // menu ui
- const [open, toggle] = useToggle(false)
- const node = useRef<HTMLDivElement>()
- useOnClickOutside(node, open ? toggle : undefined)
-
- // if no results on main list, show option to expand into inactive
- const inactiveTokens = useFoundOnInactiveList(debouncedQuery)
- const filteredInactiveTokens: Token[] = useSortedTokensByQuery(inactiveTokens, debouncedQuery)
-
- return (
- <ContentWrapper>
- <PaddedColumn gap="16px">
- <RowBetween>
- <Text fontWeight={500} fontSize={16}>
- Select a token
- </Text>
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- <Row>
- <SearchInput
- type="text"
- id="token-search-input"
- placeholder={t('tokenSearchPlaceholder')}
- autoComplete="off"
- value={searchQuery}
- ref={inputRef as RefObject<HTMLInputElement>}
- onChange={handleInput}
- onKeyDown={handleEnter}
- />
- </Row>
- {showCommonBases && (
- <CommonBases chainId={chainId} onSelect={handleCurrencySelect} selectedCurrency={selectedCurrency} />
- )}
- </PaddedColumn>
- <Separator />
- {searchToken && !searchTokenIsAdded ? (
- <Column style={{ padding: '20px 0', height: '100%' }}>
- <ImportRow token={searchToken} showImportView={showImportView} setImportToken={setImportToken} />
- </Column>
- ) : filteredSortedTokens?.length > 0 || filteredInactiveTokens?.length > 0 ? (
- <div style={{ flex: '1' }}>
- <AutoSizer disableWidth>
- {({ height }) => (
- <CurrencyList
- height={height}
- showETH={showETH}
- currencies={
- filteredInactiveTokens ? filteredSortedTokens.concat(filteredInactiveTokens) : filteredSortedTokens
- }
- breakIndex={inactiveTokens && filteredSortedTokens ? filteredSortedTokens.length : undefined}
- onCurrencySelect={handleCurrencySelect}
- otherCurrency={otherSelectedCurrency}
- selectedCurrency={selectedCurrency}
- fixedListRef={fixedList}
- showImportView={showImportView}
- setImportToken={setImportToken}
- />
- )}
- </AutoSizer>
- </div>
- ) : (
- <Column style={{ padding: '20px', height: '100%' }}>
- <TYPE.main color={theme.text3} textAlign="center" mb="20px">
- No results found.
- </TYPE.main>
- </Column>
- )}
- <Footer>
- <Row justify="center">
- <ButtonText onClick={showManageView} color={theme.blue1} className="list-token-manage-button">
- <RowFixed>
- <IconWrapper size="16px" marginRight="6px">
- <Edit />
- </IconWrapper>
- <TYPE.main color={theme.blue1}>Manage</TYPE.main>
- </RowFixed>
- </ButtonText>
- </Row>
- </Footer>
- </ContentWrapper>
- )
-}
diff --git a/src/components/SearchModal/CurrencySearchModal.tsx b/src/components/SearchModal/CurrencySearchModal.tsx
deleted file mode 100644
index f27bc8e..0000000
--- a/src/components/SearchModal/CurrencySearchModal.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { Currency, Token } from '@uniswap/sdk'
-import React, { useCallback, useEffect, useState } from 'react'
-import useLast from '../../hooks/useLast'
-import Modal from '../Modal'
-import { CurrencySearch } from './CurrencySearch'
-import { ImportToken } from './ImportToken'
-import usePrevious from 'hooks/usePrevious'
-import Manage from './Manage'
-import { TokenList } from '@uniswap/token-lists'
-import { ImportList } from './ImportList'
-
-interface CurrencySearchModalProps {
- isOpen: boolean
- onDismiss: () => void
- selectedCurrency?: Currency | null
- onCurrencySelect: (currency: Currency) => void
- otherSelectedCurrency?: Currency | null
- showCommonBases?: boolean
-}
-
-export enum CurrencyModalView {
- search,
- manage,
- importToken,
- importList,
-}
-
-export default function CurrencySearchModal({
- isOpen,
- onDismiss,
- onCurrencySelect,
- selectedCurrency,
- otherSelectedCurrency,
- showCommonBases = false,
-}: CurrencySearchModalProps) {
- const [modalView, setModalView] = useState<CurrencyModalView>(CurrencyModalView.manage)
- const lastOpen = useLast(isOpen)
-
- useEffect(() => {
- if (isOpen && !lastOpen) {
- setModalView(CurrencyModalView.search)
- }
- }, [isOpen, lastOpen])
-
- const handleCurrencySelect = useCallback(
- (currency: Currency) => {
- onCurrencySelect(currency)
- onDismiss()
- },
- [onDismiss, onCurrencySelect]
- )
-
- // for token import view
- const prevView = usePrevious(modalView)
-
- // used for import token flow
- const [importToken, setImportToken] = useState<Token | undefined>()
-
- // used for import list
- const [importList, setImportList] = useState<TokenList | undefined>()
- const [listURL, setListUrl] = useState<string | undefined>()
-
- // change min height if not searching
- const minHeight = modalView === CurrencyModalView.importToken || modalView === CurrencyModalView.importList ? 40 : 80
-
- return (
- <Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={80} minHeight={minHeight}>
- {modalView === CurrencyModalView.search ? (
- <CurrencySearch
- isOpen={isOpen}
- onDismiss={onDismiss}
- onCurrencySelect={handleCurrencySelect}
- selectedCurrency={selectedCurrency}
- otherSelectedCurrency={otherSelectedCurrency}
- showCommonBases={showCommonBases}
- showImportView={() => setModalView(CurrencyModalView.importToken)}
- setImportToken={setImportToken}
- showManageView={() => setModalView(CurrencyModalView.manage)}
- />
- ) : modalView === CurrencyModalView.importToken && importToken ? (
- <ImportToken
- tokens={[importToken]}
- onDismiss={onDismiss}
- onBack={() =>
- setModalView(prevView && prevView !== CurrencyModalView.importToken ? prevView : CurrencyModalView.search)
- }
- handleCurrencySelect={handleCurrencySelect}
- />
- ) : modalView === CurrencyModalView.importList && importList && listURL ? (
- <ImportList list={importList} listURL={listURL} onDismiss={onDismiss} setModalView={setModalView} />
- ) : modalView === CurrencyModalView.manage ? (
- <Manage
- onDismiss={onDismiss}
- setModalView={setModalView}
- setImportToken={setImportToken}
- setImportList={setImportList}
- setListUrl={setListUrl}
- />
- ) : (
- ''
- )}
- </Modal>
- )
-}
diff --git a/src/components/SearchModal/ImportList.tsx b/src/components/SearchModal/ImportList.tsx
deleted file mode 100644
index 2d15195..0000000
--- a/src/components/SearchModal/ImportList.tsx
+++ /dev/null
@@ -1,163 +0,0 @@
-import React, { useState, useCallback } from 'react'
-import styled from 'styled-components'
-import ReactGA from 'react-ga'
-import { TYPE, CloseIcon } from 'theme'
-import Card from 'components/Card'
-import { AutoColumn } from 'components/Column'
-import { RowBetween, RowFixed, AutoRow } from 'components/Row'
-import { ArrowLeft, AlertTriangle } from 'react-feather'
-import useTheme from 'hooks/useTheme'
-import { transparentize } from 'polished'
-import { ButtonPrimary } from 'components/Button'
-import { SectionBreak } from 'components/swap/styleds'
-import { ExternalLink } from '../../theme/components'
-import ListLogo from 'components/ListLogo'
-import { PaddedColumn, Checkbox, TextDot } from './styleds'
-import { TokenList } from '@uniswap/token-lists'
-import { useDispatch } from 'react-redux'
-import { AppDispatch } from 'state'
-import { useFetchListCallback } from 'hooks/useFetchListCallback'
-import { removeList, enableList } from 'state/lists/actions'
-import { CurrencyModalView } from './CurrencySearchModal'
-import { useAllLists } from 'state/lists/hooks'
-
-const Wrapper = styled.div`
- position: relative;
- width: 100%;
- overflow: auto;
-`
-
-interface ImportProps {
- listURL: string
- list: TokenList
- onDismiss: () => void
- setModalView: (view: CurrencyModalView) => void
-}
-
-export function ImportList({ listURL, list, setModalView, onDismiss }: ImportProps) {
- const theme = useTheme()
- const dispatch = useDispatch<AppDispatch>()
-
- // user must accept
- const [confirmed, setConfirmed] = useState(false)
-
- const lists = useAllLists()
- const fetchList = useFetchListCallback()
-
- // monitor is list is loading
- const adding = Boolean(lists[listURL]?.loadingRequestId)
- const [addError, setAddError] = useState<string | null>(null)
-
- const handleAddList = useCallback(() => {
- if (adding) return
- setAddError(null)
- fetchList(listURL)
- .then(() => {
- ReactGA.event({
- category: 'Lists',
- action: 'Add List',
- label: listURL,
- })
-
- // turn list on
- dispatch(enableList(listURL))
- // go back to lists
- setModalView(CurrencyModalView.manage)
- })
- .catch((error) => {
- ReactGA.event({
- category: 'Lists',
- action: 'Add List Failed',
- label: listURL,
- })
- setAddError(error.message)
- dispatch(removeList(listURL))
- })
- }, [adding, dispatch, fetchList, listURL, setModalView])
-
- return (
- <Wrapper>
- <PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
- <RowBetween>
- <ArrowLeft style={{ cursor: 'pointer' }} onClick={() => setModalView(CurrencyModalView.manage)} />
- <TYPE.mediumHeader>Import List</TYPE.mediumHeader>
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- </PaddedColumn>
- <SectionBreak />
- <PaddedColumn gap="md">
- <AutoColumn gap="md">
- <Card backgroundColor={theme.bg2} padding="12px 20px">
- <RowBetween>
- <RowFixed>
- {list.logoURI && <ListLogo logoURI={list.logoURI} size="40px" />}
- <AutoColumn gap="sm" style={{ marginLeft: '20px' }}>
- <RowFixed>
- <TYPE.body fontWeight={600} mr="6px">
- {list.name}
- </TYPE.body>
- <TextDot />
- <TYPE.main fontSize={'16px'} ml="6px">
- {list.tokens.length} tokens
- </TYPE.main>
- </RowFixed>
- <ExternalLink href={`https://tokenlists.org/token-list?url=${listURL}`}>
- <TYPE.main fontSize={'12px'} color={theme.blue1}>
- {listURL}
- </TYPE.main>
- </ExternalLink>
- </AutoColumn>
- </RowFixed>
- </RowBetween>
- </Card>
- <Card style={{ backgroundColor: transparentize(0.8, theme.red1) }}>
- <AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
- <AlertTriangle stroke={theme.red1} size={32} />
- <TYPE.body fontWeight={500} fontSize={20} color={theme.red1}>
- Import at your own risk{' '}
- </TYPE.body>
- </AutoColumn>
-
- <AutoColumn style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
- <TYPE.body fontWeight={500} color={theme.red1}>
- By adding this list you are implicitly trusting that the data is correct. Anyone can create a list,
- including creating fake versions of existing lists and lists that claim to represent projects that do
- not have one.
- </TYPE.body>
- <TYPE.body fontWeight={600} color={theme.red1}>
- If you purchase a token from this list, you may not be able to sell it back.
- </TYPE.body>
- </AutoColumn>
- <AutoRow justify="center" style={{ cursor: 'pointer' }} onClick={() => setConfirmed(!confirmed)}>
- <Checkbox
- name="confirmed"
- type="checkbox"
- checked={confirmed}
- onChange={() => setConfirmed(!confirmed)}
- />
- <TYPE.body ml="10px" fontSize="16px" color={theme.red1} fontWeight={500}>
- I understand
- </TYPE.body>
- </AutoRow>
- </Card>
-
- <ButtonPrimary
- disabled={!confirmed}
- altDisabledStyle={true}
- borderRadius="20px"
- padding="10px 1rem"
- onClick={handleAddList}
- >
- Import
- </ButtonPrimary>
- {addError ? (
- <TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
- {addError}
- </TYPE.error>
- ) : null}
- </AutoColumn>
- {/* </Card> */}
- </PaddedColumn>
- </Wrapper>
- )
-}
diff --git a/src/components/SearchModal/ImportRow.tsx b/src/components/SearchModal/ImportRow.tsx
deleted file mode 100644
index 097ee15..0000000
--- a/src/components/SearchModal/ImportRow.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import React, { CSSProperties } from 'react'
-import { Token } from '@uniswap/sdk'
-import { AutoRow, RowFixed } from 'components/Row'
-import { AutoColumn } from 'components/Column'
-import CurrencyLogo from 'components/CurrencyLogo'
-import { TYPE } from 'theme'
-import ListLogo from 'components/ListLogo'
-import { useActiveWeb3React } from 'hooks'
-import { useCombinedInactiveList } from 'state/lists/hooks'
-import useTheme from 'hooks/useTheme'
-import { ButtonPrimary } from 'components/Button'
-import styled from 'styled-components'
-import { useIsUserAddedToken, useIsTokenActive } from 'hooks/Tokens'
-import { CheckCircle } from 'react-feather'
-
-const TokenSection = styled.div<{ dim?: boolean }>`
- padding: 4px 20px;
- height: 56px;
- display: grid;
- grid-template-columns: auto minmax(auto, 1fr) auto;
- grid-gap: 16px;
- align-items: center;
-
- opacity: ${({ dim }) => (dim ? '0.4' : '1')};
-`
-
-const CheckIcon = styled(CheckCircle)`
- height: 16px;
- width: 16px;
- margin-right: 6px;
- stroke: ${({ theme }) => theme.green1};
-`
-
-const NameOverflow = styled.div`
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
- text-overflow: ellipsis;
- max-width: 140px;
- font-size: 12px;
-`
-
-export default function ImportRow({
- token,
- style,
- dim,
- showImportView,
- setImportToken,
-}: {
- token: Token
- style?: CSSProperties
- dim?: boolean
- showImportView: () => void
- setImportToken: (token: Token) => void
-}) {
- // gloabls
- const { chainId } = useActiveWeb3React()
- const theme = useTheme()
-
- // check if token comes from list
- const inactiveTokenList = useCombinedInactiveList()
- const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
-
- // check if already active on list or local storage tokens
- const isAdded = useIsUserAddedToken(token)
- const isActive = useIsTokenActive(token)
-
- return (
- <TokenSection style={style}>
- <CurrencyLogo currency={token} size={'24px'} style={{ opacity: dim ? '0.6' : '1' }} />
- <AutoColumn gap="4px" style={{ opacity: dim ? '0.6' : '1' }}>
- <AutoRow>
- <TYPE.body fontWeight={500}>{token.symbol}</TYPE.body>
- <TYPE.darkGray ml="8px" fontWeight={300}>
- <NameOverflow title={token.name}>{token.name}</NameOverflow>
- </TYPE.darkGray>
- </AutoRow>
- {list && list.logoURI && (
- <RowFixed>
- <TYPE.small mr="4px" color={theme.text3}>
- via {list.name}
- </TYPE.small>
- <ListLogo logoURI={list.logoURI} size="12px" />
- </RowFixed>
- )}
- </AutoColumn>
- {!isActive && !isAdded ? (
- <ButtonPrimary
- width="fit-content"
- padding="6px 12px"
- fontWeight={500}
- fontSize="14px"
- onClick={() => {
- setImportToken && setImportToken(token)
- showImportView()
- }}
- >
- Import
- </ButtonPrimary>
- ) : (
- <RowFixed style={{ minWidth: 'fit-content' }}>
- <CheckIcon />
- <TYPE.main color={theme.green1}>Active</TYPE.main>
- </RowFixed>
- )}
- </TokenSection>
- )
-}
diff --git a/src/components/SearchModal/ImportToken.tsx b/src/components/SearchModal/ImportToken.tsx
deleted file mode 100644
index 4e79f15..0000000
--- a/src/components/SearchModal/ImportToken.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import React, { useState } from 'react'
-import { Token, Currency } from '@uniswap/sdk'
-import styled from 'styled-components'
-import { TYPE, CloseIcon } from 'theme'
-import Card from 'components/Card'
-import { AutoColumn } from 'components/Column'
-import { RowBetween, RowFixed, AutoRow } from 'components/Row'
-import CurrencyLogo from 'components/CurrencyLogo'
-import { ArrowLeft, AlertTriangle } from 'react-feather'
-import { transparentize } from 'polished'
-import useTheme from 'hooks/useTheme'
-import { ButtonPrimary } from 'components/Button'
-import { SectionBreak } from 'components/swap/styleds'
-import { useAddUserToken } from 'state/user/hooks'
-import { getEtherscanLink } from 'utils'
-import { useActiveWeb3React } from 'hooks'
-import { ExternalLink } from '../../theme/components'
-import { useCombinedInactiveList } from 'state/lists/hooks'
-import ListLogo from 'components/ListLogo'
-import { PaddedColumn, Checkbox } from './styleds'
-
-const Wrapper = styled.div`
- position: relative;
- width: 100%;
- overflow: auto;
-`
-
-const WarningWrapper = styled(Card)<{ highWarning: boolean }>`
- background-color: ${({ theme, highWarning }) =>
- highWarning ? transparentize(0.8, theme.red1) : transparentize(0.8, theme.yellow2)};
- width: fit-content;
-`
-
-const AddressText = styled(TYPE.blue)`
- font-size: 12px;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- font-size: 10px;
-`}
-`
-
-interface ImportProps {
- tokens: Token[]
- onBack?: () => void
- onDismiss?: () => void
- handleCurrencySelect?: (currency: Currency) => void
-}
-
-export function ImportToken({ tokens, onBack, onDismiss, handleCurrencySelect }: ImportProps) {
- const theme = useTheme()
-
- const { chainId } = useActiveWeb3React()
-
- const [confirmed, setConfirmed] = useState(false)
-
- const addToken = useAddUserToken()
-
- // use for showing import source on inactive tokens
- const inactiveTokenList = useCombinedInactiveList()
-
- // higher warning severity if either is not on a list
- const fromLists =
- (chainId && inactiveTokenList?.[chainId]?.[tokens[0]?.address]?.list) ||
- (chainId && inactiveTokenList?.[chainId]?.[tokens[1]?.address]?.list)
-
- return (
- <Wrapper>
- <PaddedColumn gap="14px" style={{ width: '100%', flex: '1 1' }}>
- <RowBetween>
- {onBack ? <ArrowLeft style={{ cursor: 'pointer' }} onClick={onBack} /> : <div></div>}
- <TYPE.mediumHeader>Import {tokens.length > 1 ? 'Tokens' : 'Token'}</TYPE.mediumHeader>
- {onDismiss ? <CloseIcon onClick={onDismiss} /> : <div></div>}
- </RowBetween>
- </PaddedColumn>
- <SectionBreak />
- <PaddedColumn gap="md">
- {tokens.map((token) => {
- const list = chainId && inactiveTokenList?.[chainId]?.[token.address]?.list
- return (
- <Card backgroundColor={theme.bg2} key={'import' + token.address} className=".token-warning-container">
- <AutoColumn gap="10px">
- <AutoRow align="center">
- <CurrencyLogo currency={token} size={'24px'} />
- <TYPE.body ml="8px" mr="8px" fontWeight={500}>
- {token.symbol}
- </TYPE.body>
- <TYPE.darkGray fontWeight={300}>{token.name}</TYPE.darkGray>
- </AutoRow>
- {chainId && (
- <ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
- <AddressText>{token.address}</AddressText>
- </ExternalLink>
- )}
- {list !== undefined ? (
- <RowFixed>
- {list.logoURI && <ListLogo logoURI={list.logoURI} size="12px" />}
- <TYPE.small ml="6px" color={theme.text3}>
- via {list.name}
- </TYPE.small>
- </RowFixed>
- ) : (
- <WarningWrapper borderRadius="4px" padding="4px" highWarning={true}>
- <RowFixed>
- <AlertTriangle stroke={theme.red1} size="10px" />
- <TYPE.body color={theme.red1} ml="4px" fontSize="10px" fontWeight={500}>
- Unknown Source
- </TYPE.body>
- </RowFixed>
- </WarningWrapper>
- )}
- </AutoColumn>
- </Card>
- )
- })}
-
- <Card
- style={{ backgroundColor: fromLists ? transparentize(0.8, theme.yellow2) : transparentize(0.8, theme.red1) }}
- >
- <AutoColumn justify="center" style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
- <AlertTriangle stroke={fromLists ? theme.yellow2 : theme.red1} size={32} />
- <TYPE.body fontWeight={600} fontSize={20} color={fromLists ? theme.yellow2 : theme.red1}>
- Trade at your own risk!
- </TYPE.body>
- </AutoColumn>
-
- <AutoColumn style={{ textAlign: 'center', gap: '16px', marginBottom: '12px' }}>
- <TYPE.body fontWeight={400} color={fromLists ? theme.yellow2 : theme.red1}>
- Anyone can create a token, including creating fake versions of existing tokens that claim to represent
- projects.
- </TYPE.body>
- <TYPE.body fontWeight={600} color={fromLists ? theme.yellow2 : theme.red1}>
- If you purchase this token, you may not be able to sell it back.
- </TYPE.body>
- </AutoColumn>
- <AutoRow justify="center" style={{ cursor: 'pointer' }} onClick={() => setConfirmed(!confirmed)}>
- <Checkbox
- className=".understand-checkbox"
- name="confirmed"
- type="checkbox"
- checked={confirmed}
- onChange={() => setConfirmed(!confirmed)}
- />
- <TYPE.body ml="10px" fontSize="16px" color={fromLists ? theme.yellow2 : theme.red1} fontWeight={500}>
- I understand
- </TYPE.body>
- </AutoRow>
- </Card>
- <ButtonPrimary
- disabled={!confirmed}
- altDisabledStyle={true}
- borderRadius="20px"
- padding="10px 1rem"
- onClick={() => {
- tokens.map((token) => addToken(token))
- handleCurrencySelect && handleCurrencySelect(tokens[0])
- }}
- className=".token-dismiss-button"
- >
- Import
- </ButtonPrimary>
- </PaddedColumn>
- </Wrapper>
- )
-}
diff --git a/src/components/SearchModal/Manage.tsx b/src/components/SearchModal/Manage.tsx
deleted file mode 100644
index 4f6e664..0000000
--- a/src/components/SearchModal/Manage.tsx
+++ /dev/null
@@ -1,89 +0,0 @@
-import React, { useState } from 'react'
-import { PaddedColumn, Separator } from './styleds'
-import { RowBetween } from 'components/Row'
-import { ArrowLeft } from 'react-feather'
-import { Text } from 'rebass'
-import { CloseIcon } from 'theme'
-import styled from 'styled-components'
-import { Token } from '@uniswap/sdk'
-import { ManageLists } from './ManageLists'
-import ManageTokens from './ManageTokens'
-import { TokenList } from '@uniswap/token-lists'
-import { CurrencyModalView } from './CurrencySearchModal'
-
-const Wrapper = styled.div`
- width: 100%;
- position: relative;
- padding-bottom: 80px;
-`
-
-const ToggleWrapper = styled(RowBetween)`
- background-color: ${({ theme }) => theme.bg3};
- border-radius: 12px;
- padding: 6px;
-`
-
-const ToggleOption = styled.div<{ active?: boolean }>`
- width: 48%;
- padding: 10px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 12px;
- font-weight: 600;
- background-color: ${({ theme, active }) => (active ? theme.bg1 : theme.bg3)};
- color: ${({ theme, active }) => (active ? theme.text1 : theme.text2)};
- user-select: none;
-
- :hover {
- cursor: pointer;
- opacity: 0.7;
- }
-`
-
-export default function Manage({
- onDismiss,
- setModalView,
- setImportList,
- setImportToken,
- setListUrl,
-}: {
- onDismiss: () => void
- setModalView: (view: CurrencyModalView) => void
- setImportToken: (token: Token) => void
- setImportList: (list: TokenList) => void
- setListUrl: (url: string) => void
-}) {
- // toggle between tokens and lists
- const [showLists, setShowLists] = useState(true)
-
- return (
- <Wrapper>
- <PaddedColumn>
- <RowBetween>
- <ArrowLeft style={{ cursor: 'pointer' }} onClick={() => setModalView(CurrencyModalView.search)} />
- <Text fontWeight={500} fontSize={20}>
- Manage
- </Text>
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- </PaddedColumn>
- <Separator />
- <PaddedColumn style={{ paddingBottom: 0 }}>
- <ToggleWrapper>
- <ToggleOption onClick={() => setShowLists(!showLists)} active={showLists}>
- Lists
- </ToggleOption>
- <ToggleOption onClick={() => setShowLists(!showLists)} active={!showLists}>
- Tokens
- </ToggleOption>
- </ToggleWrapper>
- </PaddedColumn>
- {showLists ? (
- <ManageLists setModalView={setModalView} setImportList={setImportList} setListUrl={setListUrl} />
- ) : (
- <ManageTokens setModalView={setModalView} setImportToken={setImportToken} />
- )}
- </Wrapper>
- )
-}
diff --git a/src/components/SearchModal/ManageLists.tsx b/src/components/SearchModal/ManageLists.tsx
deleted file mode 100644
index d011ca9..0000000
--- a/src/components/SearchModal/ManageLists.tsx
+++ /dev/null
@@ -1,377 +0,0 @@
-import React, { memo, useCallback, useMemo, useRef, useState, useEffect } from 'react'
-import { Settings, CheckCircle } from 'react-feather'
-import ReactGA from 'react-ga'
-import { usePopper } from 'react-popper'
-import { useDispatch, useSelector } from 'react-redux'
-import styled from 'styled-components'
-import { useFetchListCallback } from '../../hooks/useFetchListCallback'
-import { useOnClickOutside } from '../../hooks/useOnClickOutside'
-import { TokenList } from '@uniswap/token-lists'
-
-import useToggle from '../../hooks/useToggle'
-import { AppDispatch, AppState } from '../../state'
-import { acceptListUpdate, removeList, disableList, enableList } from '../../state/lists/actions'
-import { useIsListActive, useAllLists, useActiveListUrls } from '../../state/lists/hooks'
-import { ExternalLink, LinkStyledButton, TYPE, IconWrapper } from '../../theme'
-import listVersionLabel from '../../utils/listVersionLabel'
-import { parseENSAddress } from '../../utils/parseENSAddress'
-import uriToHttp from '../../utils/uriToHttp'
-import { ButtonEmpty, ButtonPrimary } from '../Button'
-
-import Column, { AutoColumn } from '../Column'
-import ListLogo from '../ListLogo'
-import Row, { RowFixed, RowBetween } from '../Row'
-import { PaddedColumn, SearchInput, Separator, SeparatorDark } from './styleds'
-import { useListColor } from 'hooks/useColor'
-import useTheme from '../../hooks/useTheme'
-import ListToggle from '../Toggle/ListToggle'
-import Card from 'components/Card'
-import { CurrencyModalView } from './CurrencySearchModal'
-import { UNSUPPORTED_LIST_URLS } from 'constants/lists'
-
-const Wrapper = styled(Column)`
- width: 100%;
- height: 100%;
-`
-
-const UnpaddedLinkStyledButton = styled(LinkStyledButton)`
- padding: 0;
- font-size: 1rem;
- opacity: ${({ disabled }) => (disabled ? '0.4' : '1')};
-`
-
-const PopoverContainer = styled.div<{ show: boolean }>`
- z-index: 100;
- visibility: ${(props) => (props.show ? 'visible' : 'hidden')};
- opacity: ${(props) => (props.show ? 1 : 0)};
- transition: visibility 150ms linear, opacity 150ms linear;
- background: ${({ theme }) => theme.bg2};
- border: 1px solid ${({ theme }) => theme.bg3};
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
- 0px 24px 32px rgba(0, 0, 0, 0.01);
- color: ${({ theme }) => theme.text2};
- border-radius: 0.5rem;
- padding: 1rem;
- display: grid;
- grid-template-rows: 1fr;
- grid-gap: 8px;
- font-size: 1rem;
- text-align: left;
-`
-
-const StyledMenu = styled.div`
- display: flex;
- justify-content: center;
- align-items: center;
- position: relative;
- border: none;
-`
-
-const StyledTitleText = styled.div<{ active: boolean }>`
- font-size: 16px;
- overflow: hidden;
- text-overflow: ellipsis;
- font-weight: 600;
- color: ${({ theme, active }) => (active ? theme.white : theme.text2)};
-`
-
-const StyledListUrlText = styled(TYPE.main)<{ active: boolean }>`
- font-size: 12px;
- color: ${({ theme, active }) => (active ? theme.white : theme.text2)};
-`
-
-const RowWrapper = styled(Row)<{ bgColor: string; active: boolean }>`
- background-color: ${({ bgColor, active, theme }) => (active ? bgColor ?? 'transparent' : theme.bg2)};
- transition: 200ms;
- align-items: center;
- padding: 1rem;
- border-radius: 20px;
-`
-
-function listUrlRowHTMLId(listUrl: string) {
- return `list-row-${listUrl.replace(/\./g, '-')}`
-}
-
-const ListRow = memo(function ListRow({ listUrl }: { listUrl: string }) {
- const listsByUrl = useSelector<AppState, AppState['lists']['byUrl']>((state) => state.lists.byUrl)
- const dispatch = useDispatch<AppDispatch>()
- const { current: list, pendingUpdate: pending } = listsByUrl[listUrl]
-
- const theme = useTheme()
- const listColor = useListColor(list?.logoURI)
- const isActive = useIsListActive(listUrl)
-
- const [open, toggle] = useToggle(false)
- const node = useRef<HTMLDivElement>()
- const [referenceElement, setReferenceElement] = useState<HTMLDivElement>()
- const [popperElement, setPopperElement] = useState<HTMLDivElement>()
-
- const { styles, attributes } = usePopper(referenceElement, popperElement, {
- placement: 'auto',
- strategy: 'fixed',
- modifiers: [{ name: 'offset', options: { offset: [8, 8] } }],
- })
-
- useOnClickOutside(node, open ? toggle : undefined)
-
- const handleAcceptListUpdate = useCallback(() => {
- if (!pending) return
- ReactGA.event({
- category: 'Lists',
- action: 'Update List from List Select',
- label: listUrl,
- })
- dispatch(acceptListUpdate(listUrl))
- }, [dispatch, listUrl, pending])
-
- const handleRemoveList = useCallback(() => {
- ReactGA.event({
- category: 'Lists',
- action: 'Start Remove List',
- label: listUrl,
- })
- if (window.prompt(`Please confirm you would like to remove this list by typing REMOVE`) === `REMOVE`) {
- ReactGA.event({
- category: 'Lists',
- action: 'Confirm Remove List',
- label: listUrl,
- })
- dispatch(removeList(listUrl))
- }
- }, [dispatch, listUrl])
-
- const handleEnableList = useCallback(() => {
- ReactGA.event({
- category: 'Lists',
- action: 'Enable List',
- label: listUrl,
- })
- dispatch(enableList(listUrl))
- }, [dispatch, listUrl])
-
- const handleDisableList = useCallback(() => {
- ReactGA.event({
- category: 'Lists',
- action: 'Disable List',
- label: listUrl,
- })
- dispatch(disableList(listUrl))
- }, [dispatch, listUrl])
-
- if (!list) return null
-
- return (
- <RowWrapper active={isActive} bgColor={listColor} key={listUrl} id={listUrlRowHTMLId(listUrl)}>
- {list.logoURI ? (
- <ListLogo size="40px" style={{ marginRight: '1rem' }} logoURI={list.logoURI} alt={`${list.name} list logo`} />
- ) : (
- <div style={{ width: '24px', height: '24px', marginRight: '1rem' }} />
- )}
- <Column style={{ flex: '1' }}>
- <Row>
- <StyledTitleText active={isActive}>{list.name}</StyledTitleText>
- </Row>
- <RowFixed mt="4px">
- <StyledListUrlText active={isActive} mr="6px">
- {list.tokens.length} tokens
- </StyledListUrlText>
- <StyledMenu ref={node as any}>
- <ButtonEmpty onClick={toggle} ref={setReferenceElement} padding="0">
- <Settings stroke={isActive ? theme.bg1 : theme.text1} size={12} />
- </ButtonEmpty>
- {open && (
- <PopoverContainer show={true} ref={setPopperElement as any} style={styles.popper} {...attributes.popper}>
- <div>{list && listVersionLabel(list.version)}</div>
- <SeparatorDark />
- <ExternalLink href={`https://tokenlists.org/token-list?url=${listUrl}`}>View list</ExternalLink>
- <UnpaddedLinkStyledButton onClick={handleRemoveList} disabled={Object.keys(listsByUrl).length === 1}>
- Remove list
- </UnpaddedLinkStyledButton>
- {pending && (
- <UnpaddedLinkStyledButton onClick={handleAcceptListUpdate}>Update list</UnpaddedLinkStyledButton>
- )}
- </PopoverContainer>
- )}
- </StyledMenu>
- </RowFixed>
- </Column>
- <ListToggle
- isActive={isActive}
- bgColor={listColor}
- toggle={() => {
- isActive ? handleDisableList() : handleEnableList()
- }}
- />
- </RowWrapper>
- )
-})
-
-const ListContainer = styled.div`
- padding: 1rem;
- height: 100%;
- overflow: auto;
- padding-bottom: 80px;
-`
-
-export function ManageLists({
- setModalView,
- setImportList,
- setListUrl,
-}: {
- setModalView: (view: CurrencyModalView) => void
- setImportList: (list: TokenList) => void
- setListUrl: (url: string) => void
-}) {
- const theme = useTheme()
-
- const [listUrlInput, setListUrlInput] = useState<string>('')
-
- const lists = useAllLists()
-
- // sort by active but only if not visible
- const activeListUrls = useActiveListUrls()
- const [activeCopy, setActiveCopy] = useState<string[] | undefined>()
- useEffect(() => {
- if (!activeCopy && activeListUrls) {
- setActiveCopy(activeListUrls)
- }
- }, [activeCopy, activeListUrls])
-
- const handleInput = useCallback((e) => {
- setListUrlInput(e.target.value)
- }, [])
-
- const fetchList = useFetchListCallback()
-
- const validUrl: boolean = useMemo(() => {
- return uriToHttp(listUrlInput).length > 0 || Boolean(parseENSAddress(listUrlInput))
- }, [listUrlInput])
-
- const sortedLists = useMemo(() => {
- const listUrls = Object.keys(lists)
- return listUrls
- .filter((listUrl) => {
- // only show loaded lists, hide unsupported lists
- return Boolean(lists[listUrl].current) && !Boolean(UNSUPPORTED_LIST_URLS.includes(listUrl))
- })
- .sort((u1, u2) => {
- const { current: l1 } = lists[u1]
- const { current: l2 } = lists[u2]
-
- // first filter on active lists
- if (activeCopy?.includes(u1) && !activeCopy?.includes(u2)) {
- return -1
- }
- if (!activeCopy?.includes(u1) && activeCopy?.includes(u2)) {
- return 1
- }
-
- if (l1 && l2) {
- return l1.name.toLowerCase() < l2.name.toLowerCase()
- ? -1
- : l1.name.toLowerCase() === l2.name.toLowerCase()
- ? 0
- : 1
- }
- if (l1) return -1
- if (l2) return 1
- return 0
- })
- }, [lists, activeCopy])
-
- // temporary fetched list for import flow
- const [tempList, setTempList] = useState<TokenList>()
- const [addError, setAddError] = useState<string | undefined>()
-
- useEffect(() => {
- async function fetchTempList() {
- fetchList(listUrlInput, false)
- .then((list) => setTempList(list))
- .catch(() => setAddError('Error importing list'))
- }
- // if valid url, fetch details for card
- if (validUrl) {
- fetchTempList()
- } else {
- setTempList(undefined)
- listUrlInput !== '' && setAddError('Enter valid list location')
- }
-
- // reset error
- if (listUrlInput === '') {
- setAddError(undefined)
- }
- }, [fetchList, listUrlInput, validUrl])
-
- // check if list is already imported
- const isImported = Object.keys(lists).includes(listUrlInput)
-
- // set list values and have parent modal switch to import list view
- const handleImport = useCallback(() => {
- if (!tempList) return
- setImportList(tempList)
- setModalView(CurrencyModalView.importList)
- setListUrl(listUrlInput)
- }, [listUrlInput, setImportList, setListUrl, setModalView, tempList])
-
- return (
- <Wrapper>
- <PaddedColumn gap="14px">
- <Row>
- <SearchInput
- type="text"
- id="list-add-input"
- placeholder="https:// or ipfs:// or ENS name"
- value={listUrlInput}
- onChange={handleInput}
- />
- </Row>
- {addError ? (
- <TYPE.error title={addError} style={{ textOverflow: 'ellipsis', overflow: 'hidden' }} error>
- {addError}
- </TYPE.error>
- ) : null}
- </PaddedColumn>
- {tempList && (
- <PaddedColumn style={{ paddingTop: 0 }}>
- <Card backgroundColor={theme.bg2} padding="12px 20px">
- <RowBetween>
- <RowFixed>
- {tempList.logoURI && <ListLogo logoURI={tempList.logoURI} size="40px" />}
- <AutoColumn gap="4px" style={{ marginLeft: '20px' }}>
- <TYPE.body fontWeight={600}>{tempList.name}</TYPE.body>
- <TYPE.main fontSize={'12px'}>{tempList.tokens.length} tokens</TYPE.main>
- </AutoColumn>
- </RowFixed>
- {isImported ? (
- <RowFixed>
- <IconWrapper stroke={theme.text2} size="16px" marginRight={'10px'}>
- <CheckCircle />
- </IconWrapper>
- <TYPE.body color={theme.text2}>Loaded</TYPE.body>
- </RowFixed>
- ) : (
- <ButtonPrimary
- style={{ fontSize: '14px' }}
- padding="6px 8px"
- width="fit-content"
- onClick={handleImport}
- >
- Import
- </ButtonPrimary>
- )}
- </RowBetween>
- </Card>
- </PaddedColumn>
- )}
- <Separator />
- <ListContainer>
- <AutoColumn gap="md">
- {sortedLists.map((listUrl) => (
- <ListRow key={listUrl} listUrl={listUrl} />
- ))}
- </AutoColumn>
- </ListContainer>
- </Wrapper>
- )
-}
diff --git a/src/components/SearchModal/ManageTokens.tsx b/src/components/SearchModal/ManageTokens.tsx
deleted file mode 100644
index 816bef5..0000000
--- a/src/components/SearchModal/ManageTokens.tsx
+++ /dev/null
@@ -1,143 +0,0 @@
-import React, { useRef, RefObject, useCallback, useState, useMemo } from 'react'
-import Column from 'components/Column'
-import { PaddedColumn, Separator, SearchInput } from './styleds'
-import Row, { RowBetween, RowFixed } from 'components/Row'
-import { TYPE, ExternalLinkIcon, TrashIcon, ButtonText, ExternalLink } from 'theme'
-import { useToken } from 'hooks/Tokens'
-import styled from 'styled-components'
-import { useUserAddedTokens, useRemoveUserAddedToken } from 'state/user/hooks'
-import { Token } from '@uniswap/sdk'
-import CurrencyLogo from 'components/CurrencyLogo'
-import { getEtherscanLink, isAddress } from 'utils'
-import { useActiveWeb3React } from 'hooks'
-import Card from 'components/Card'
-import ImportRow from './ImportRow'
-import useTheme from '../../hooks/useTheme'
-
-import { CurrencyModalView } from './CurrencySearchModal'
-
-const Wrapper = styled.div`
- width: 100%;
- height: calc(100% - 60px);
- position: relative;
- padding-bottom: 60px;
-`
-
-const Footer = styled.div`
- position: absolute;
- bottom: 0;
- width: 100%;
- border-radius: 20px;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
- border-top: 1px solid ${({ theme }) => theme.bg3};
- padding: 20px;
- text-align: center;
-`
-
-export default function ManageTokens({
- setModalView,
- setImportToken,
-}: {
- setModalView: (view: CurrencyModalView) => void
- setImportToken: (token: Token) => void
-}) {
- const { chainId } = useActiveWeb3React()
-
- const [searchQuery, setSearchQuery] = useState<string>('')
- const theme = useTheme()
-
- // manage focus on modal show
- const inputRef = useRef<HTMLInputElement>()
- const handleInput = useCallback((event) => {
- const input = event.target.value
- const checksummedInput = isAddress(input)
- setSearchQuery(checksummedInput || input)
- }, [])
-
- // if they input an address, use it
- const isAddressSearch = isAddress(searchQuery)
- const searchToken = useToken(searchQuery)
-
- // all tokens for local lisr
- const userAddedTokens: Token[] = useUserAddedTokens()
- const removeToken = useRemoveUserAddedToken()
-
- const handleRemoveAll = useCallback(() => {
- if (chainId && userAddedTokens) {
- userAddedTokens.map((token) => {
- return removeToken(chainId, token.address)
- })
- }
- }, [removeToken, userAddedTokens, chainId])
-
- const tokenList = useMemo(() => {
- return (
- chainId &&
- userAddedTokens.map((token) => (
- <RowBetween key={token.address} width="100%">
- <RowFixed>
- <CurrencyLogo currency={token} size={'20px'} />
- <ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
- <TYPE.main ml={'10px'} fontWeight={600}>
- {token.symbol}
- </TYPE.main>
- </ExternalLink>
- </RowFixed>
- <RowFixed>
- <TrashIcon onClick={() => removeToken(chainId, token.address)} />
- <ExternalLinkIcon href={getEtherscanLink(chainId, token.address, 'address')} />
- </RowFixed>
- </RowBetween>
- ))
- )
- }, [userAddedTokens, chainId, removeToken])
-
- return (
- <Wrapper>
- <Column style={{ width: '100%', flex: '1 1' }}>
- <PaddedColumn gap="14px">
- <Row>
- <SearchInput
- type="text"
- id="token-search-input"
- placeholder={'0x0000'}
- value={searchQuery}
- autoComplete="off"
- ref={inputRef as RefObject<HTMLInputElement>}
- onChange={handleInput}
- />
- </Row>
- {searchQuery !== '' && !isAddressSearch && <TYPE.error error={true}>Enter valid token address</TYPE.error>}
- {searchToken && (
- <Card backgroundColor={theme.bg2} padding="10px 0">
- <ImportRow
- token={searchToken}
- showImportView={() => setModalView(CurrencyModalView.importToken)}
- setImportToken={setImportToken}
- style={{ height: 'fit-content' }}
- />
- </Card>
- )}
- </PaddedColumn>
- <Separator />
- <PaddedColumn gap="lg">
- <RowBetween>
- <TYPE.main fontWeight={600}>
- {userAddedTokens?.length} Custom {userAddedTokens.length === 1 ? 'Token' : 'Tokens'}
- </TYPE.main>
- {userAddedTokens.length > 0 && (
- <ButtonText onClick={handleRemoveAll}>
- <TYPE.blue>Clear all</TYPE.blue>
- </ButtonText>
- )}
- </RowBetween>
- {tokenList}
- </PaddedColumn>
- </Column>
- <Footer>
- <TYPE.darkGray>Tip: Custom tokens are stored locally in your browser</TYPE.darkGray>
- </Footer>
- </Wrapper>
- )
-}
diff --git a/src/components/SearchModal/SortButton.tsx b/src/components/SearchModal/SortButton.tsx
deleted file mode 100644
index 9d2742e..0000000
--- a/src/components/SearchModal/SortButton.tsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react'
-import { Text } from 'rebass'
-import styled from 'styled-components'
-import { RowFixed } from '../Row'
-
-export const FilterWrapper = styled(RowFixed)`
- padding: 8px;
- background-color: ${({ theme }) => theme.bg2};
- color: ${({ theme }) => theme.text1};
- border-radius: 8px;
- user-select: none;
- & > * {
- user-select: none;
- }
- :hover {
- cursor: pointer;
- }
-`
-
-export default function SortButton({
- toggleSortOrder,
- ascending,
-}: {
- toggleSortOrder: () => void
- ascending: boolean
-}) {
- return (
- <FilterWrapper onClick={toggleSortOrder}>
- <Text fontSize={14} fontWeight={500}>
- {ascending ? '↑' : '↓'}
- </Text>
- </FilterWrapper>
- )
-}
diff --git a/src/components/SearchModal/filtering.ts b/src/components/SearchModal/filtering.ts
deleted file mode 100644
index 8e2cadf..0000000
--- a/src/components/SearchModal/filtering.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { useMemo } from 'react'
-import { isAddress } from '../../utils'
-import { Token } from '@uniswap/sdk'
-
-export function filterTokens(tokens: Token[], search: string): Token[] {
- if (search.length === 0) return tokens
-
- const searchingAddress = isAddress(search)
-
- if (searchingAddress) {
- return tokens.filter((token) => token.address === searchingAddress)
- }
-
- const lowerSearchParts = search
- .toLowerCase()
- .split(/\s+/)
- .filter((s) => s.length > 0)
-
- if (lowerSearchParts.length === 0) {
- return tokens
- }
-
- const matchesSearch = (s: string): boolean => {
- const sParts = s
- .toLowerCase()
- .split(/\s+/)
- .filter((s) => s.length > 0)
-
- return lowerSearchParts.every((p) => p.length === 0 || sParts.some((sp) => sp.startsWith(p) || sp.endsWith(p)))
- }
-
- return tokens.filter((token) => {
- const { symbol, name } = token
- return (symbol && matchesSearch(symbol)) || (name && matchesSearch(name))
- })
-}
-
-export function useSortedTokensByQuery(tokens: Token[] | undefined, searchQuery: string): Token[] {
- return useMemo(() => {
- if (!tokens) {
- return []
- }
-
- const symbolMatch = searchQuery
- .toLowerCase()
- .split(/\s+/)
- .filter((s) => s.length > 0)
-
- if (symbolMatch.length > 1) {
- return tokens
- }
-
- const exactMatches: Token[] = []
- const symbolSubtrings: Token[] = []
- const rest: Token[] = []
-
- // sort tokens by exact match -> subtring on symbol match -> rest
- tokens.map((token) => {
- if (token.symbol?.toLowerCase() === symbolMatch[0]) {
- return exactMatches.push(token)
- } else if (token.symbol?.toLowerCase().startsWith(searchQuery.toLowerCase().trim())) {
- return symbolSubtrings.push(token)
- } else {
- return rest.push(token)
- }
- })
-
- return [...exactMatches, ...symbolSubtrings, ...rest]
- }, [tokens, searchQuery])
-}
diff --git a/src/components/SearchModal/sorting.ts b/src/components/SearchModal/sorting.ts
deleted file mode 100644
index 4713cb5..0000000
--- a/src/components/SearchModal/sorting.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Token, TokenAmount } from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { useAllTokenBalances } from '../../state/wallet/hooks'
-
-// compare two token amounts with highest one coming first
-function balanceComparator(balanceA?: TokenAmount, balanceB?: TokenAmount) {
- if (balanceA && balanceB) {
- return balanceA.greaterThan(balanceB) ? -1 : balanceA.equalTo(balanceB) ? 0 : 1
- } else if (balanceA && balanceA.greaterThan('0')) {
- return -1
- } else if (balanceB && balanceB.greaterThan('0')) {
- return 1
- }
- return 0
-}
-
-function getTokenComparator(balances: {
- [tokenAddress: string]: TokenAmount | undefined
-}): (tokenA: Token, tokenB: Token) => number {
- return function sortTokens(tokenA: Token, tokenB: Token): number {
- // -1 = a is first
- // 1 = b is first
-
- // sort by balances
- const balanceA = balances[tokenA.address]
- const balanceB = balances[tokenB.address]
-
- const balanceComp = balanceComparator(balanceA, balanceB)
- if (balanceComp !== 0) return balanceComp
-
- if (tokenA.symbol && tokenB.symbol) {
- // sort by symbol
- return tokenA.symbol.toLowerCase() < tokenB.symbol.toLowerCase() ? -1 : 1
- } else {
- return tokenA.symbol ? -1 : tokenB.symbol ? -1 : 0
- }
- }
-}
-
-export function useTokenComparator(inverted: boolean): (tokenA: Token, tokenB: Token) => number {
- const balances = useAllTokenBalances()
- const comparator = useMemo(() => getTokenComparator(balances ?? {}), [balances])
- return useMemo(() => {
- if (inverted) {
- return (tokenA: Token, tokenB: Token) => comparator(tokenA, tokenB) * -1
- } else {
- return comparator
- }
- }, [inverted, comparator])
-}
diff --git a/src/components/SearchModal/styleds.tsx b/src/components/SearchModal/styleds.tsx
deleted file mode 100644
index 52fe477..0000000
--- a/src/components/SearchModal/styleds.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import styled from 'styled-components'
-import { AutoColumn } from '../Column'
-import { RowBetween, RowFixed } from '../Row'
-
-export const ModalInfo = styled.div`
- ${({ theme }) => theme.flexRowNoWrap}
- align-items: center;
- padding: 1rem 1rem;
- margin: 0.25rem 0.5rem;
- justify-content: center;
- flex: 1;
- user-select: none;
-`
-export const StyledMenu = styled.div`
- display: flex;
- justify-content: center;
- align-items: center;
- position: relative;
- border: none;
-`
-
-export const PopoverContainer = styled.div<{ show: boolean }>`
- z-index: 100;
- visibility: ${(props) => (props.show ? 'visible' : 'hidden')};
- opacity: ${(props) => (props.show ? 1 : 0)};
- transition: visibility 150ms linear, opacity 150ms linear;
- background: ${({ theme }) => theme.bg2};
- border: 1px solid ${({ theme }) => theme.bg3};
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
- 0px 24px 32px rgba(0, 0, 0, 0.01);
- color: ${({ theme }) => theme.text2};
- border-radius: 0.5rem;
- padding: 1rem;
- display: grid;
- grid-template-rows: 1fr;
- grid-gap: 8px;
- font-size: 1rem;
- text-align: left;
- top: 80px;
-`
-
-export const TextDot = styled.div`
- height: 3px;
- width: 3px;
- background-color: ${({ theme }) => theme.text2};
- border-radius: 50%;
-`
-
-export const FadedSpan = styled(RowFixed)`
- color: ${({ theme }) => theme.primary1};
- font-size: 14px;
-`
-export const Checkbox = styled.input`
- border: 1px solid ${({ theme }) => theme.red3};
- height: 20px;
- margin: 0;
-`
-
-export const PaddedColumn = styled(AutoColumn)`
- padding: 20px;
-`
-
-export const MenuItem = styled(RowBetween)`
- padding: 4px 20px;
- height: 56px;
- display: grid;
- grid-template-columns: auto minmax(auto, 1fr) auto minmax(0, 72px);
- grid-gap: 16px;
- cursor: ${({ disabled }) => !disabled && 'pointer'};
- pointer-events: ${({ disabled }) => disabled && 'none'};
- :hover {
- background-color: ${({ theme, disabled }) => !disabled && theme.bg2};
- }
- opacity: ${({ disabled, selected }) => (disabled || selected ? 0.5 : 1)};
-`
-
-export const SearchInput = styled.input`
- position: relative;
- display: flex;
- padding: 16px;
- align-items: center;
- width: 100%;
- white-space: nowrap;
- background: none;
- border: none;
- outline: none;
- border-radius: 20px;
- color: ${({ theme }) => theme.text1};
- border-style: solid;
- border: 1px solid ${({ theme }) => theme.bg3};
- -webkit-appearance: none;
-
- font-size: 18px;
-
- ::placeholder {
- color: ${({ theme }) => theme.text3};
- }
- transition: border 100ms;
- :focus {
- border: 1px solid ${({ theme }) => theme.primary1};
- outline: none;
- }
-`
-export const Separator = styled.div`
- width: 100%;
- height: 1px;
- background-color: ${({ theme }) => theme.bg2};
-`
-
-export const SeparatorDark = styled.div`
- width: 100%;
- height: 1px;
- background-color: ${({ theme }) => theme.bg3};
-`
diff --git a/src/components/Settings/index.tsx b/src/components/Settings/index.tsx
deleted file mode 100644
index 60978e7..0000000
--- a/src/components/Settings/index.tsx
+++ /dev/null
@@ -1,247 +0,0 @@
-import React, { useContext, useRef, useState } from 'react'
-import { Settings, X } from 'react-feather'
-import { Text } from 'rebass'
-import styled, { ThemeContext } from 'styled-components'
-import { useOnClickOutside } from '../../hooks/useOnClickOutside'
-import { ApplicationModal } from '../../state/application/actions'
-import { useModalOpen, useToggleSettingsMenu } from '../../state/application/hooks'
-import {
- useExpertModeManager,
- useUserTransactionTTL,
- useUserSlippageTolerance,
- useUserSingleHopOnly,
-} from '../../state/user/hooks'
-import { TYPE } from '../../theme'
-import { ButtonError } from '../Button'
-import { AutoColumn } from '../Column'
-import Modal from '../Modal'
-import QuestionHelper from '../QuestionHelper'
-import { RowBetween, RowFixed } from '../Row'
-import Toggle from '../Toggle'
-import TransactionSettings from '../TransactionSettings'
-
-const StyledMenuIcon = styled(Settings)`
- height: 20px;
- width: 20px;
-
- > * {
- stroke: ${({ theme }) => theme.text2};
- }
-
- :hover {
- opacity: 0.7;
- }
-`
-
-const StyledCloseIcon = styled(X)`
- height: 20px;
- width: 20px;
- :hover {
- cursor: pointer;
- }
-
- > * {
- stroke: ${({ theme }) => theme.text1};
- }
-`
-
-const StyledMenuButton = styled.button`
- position: relative;
- width: 100%;
- height: 100%;
- border: none;
- background-color: transparent;
- margin: 0;
- padding: 0;
- height: 35px;
-
- padding: 0.15rem 0.5rem;
- border-radius: 0.5rem;
-
- :hover,
- :focus {
- cursor: pointer;
- outline: none;
- }
-
- svg {
- margin-top: 2px;
- }
-`
-const EmojiWrapper = styled.div`
- position: absolute;
- bottom: -6px;
- right: 0px;
- font-size: 14px;
-`
-
-const StyledMenu = styled.div`
- margin-left: 0.5rem;
- display: flex;
- justify-content: center;
- align-items: center;
- position: relative;
- border: none;
- text-align: left;
-`
-
-const MenuFlyout = styled.span`
- min-width: 20.125rem;
- background-color: ${({ theme }) => theme.bg2};
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
- 0px 24px 32px rgba(0, 0, 0, 0.01);
- border-radius: 12px;
- display: flex;
- flex-direction: column;
- font-size: 1rem;
- position: absolute;
- top: 3rem;
- right: 0rem;
- z-index: 100;
-
- ${({ theme }) => theme.mediaWidth.upToMedium`
- min-width: 18.125rem;
- `};
-`
-
-const Break = styled.div`
- width: 100%;
- height: 1px;
- background-color: ${({ theme }) => theme.bg3};
-`
-
-const ModalContentWrapper = styled.div`
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 2rem 0;
- background-color: ${({ theme }) => theme.bg2};
- border-radius: 20px;
-`
-
-export default function SettingsTab() {
- const node = useRef<HTMLDivElement>()
- const open = useModalOpen(ApplicationModal.SETTINGS)
- const toggle = useToggleSettingsMenu()
-
- const theme = useContext(ThemeContext)
- const [userSlippageTolerance, setUserslippageTolerance] = useUserSlippageTolerance()
-
- const [ttl, setTtl] = useUserTransactionTTL()
-
- const [expertMode, toggleExpertMode] = useExpertModeManager()
-
- const [singleHopOnly, setSingleHopOnly] = useUserSingleHopOnly()
-
- // show confirmation view before turning on
- const [showConfirmation, setShowConfirmation] = useState(false)
-
- useOnClickOutside(node, open ? toggle : undefined)
-
- return (
- // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451
- <StyledMenu ref={node as any}>
- <Modal isOpen={showConfirmation} onDismiss={() => setShowConfirmation(false)} maxHeight={100}>
- <ModalContentWrapper>
- <AutoColumn gap="lg">
- <RowBetween style={{ padding: '0 2rem' }}>
- <div />
- <Text fontWeight={500} fontSize={20}>
- Are you sure?
- </Text>
- <StyledCloseIcon onClick={() => setShowConfirmation(false)} />
- </RowBetween>
- <Break />
- <AutoColumn gap="lg" style={{ padding: '0 2rem' }}>
- <Text fontWeight={500} fontSize={20}>
- Expert mode turns off the confirm transaction prompt and allows high slippage trades that often result
- in bad rates and lost funds.
- </Text>
- <Text fontWeight={600} fontSize={20}>
- ONLY USE THIS MODE IF YOU KNOW WHAT YOU ARE DOING.
- </Text>
- <ButtonError
- error={true}
- padding={'12px'}
- onClick={() => {
- if (window.prompt(`Please type the word "confirm" to enable expert mode.`) === 'confirm') {
- toggleExpertMode()
- setShowConfirmation(false)
- }
- }}
- >
- <Text fontSize={20} fontWeight={500} id="confirm-expert-mode">
- Turn On Expert Mode
- </Text>
- </ButtonError>
- </AutoColumn>
- </AutoColumn>
- </ModalContentWrapper>
- </Modal>
- <StyledMenuButton onClick={toggle} id="open-settings-dialog-button">
- <StyledMenuIcon />
- {expertMode ? (
- <EmojiWrapper>
- <span role="img" aria-label="wizard-icon">
- 🧙
- </span>
- </EmojiWrapper>
- ) : null}
- </StyledMenuButton>
- {open && (
- <MenuFlyout>
- <AutoColumn gap="md" style={{ padding: '1rem' }}>
- <Text fontWeight={600} fontSize={14}>
- Transaction Settings
- </Text>
- <TransactionSettings
- rawSlippage={userSlippageTolerance}
- setRawSlippage={setUserslippageTolerance}
- deadline={ttl}
- setDeadline={setTtl}
- />
- <Text fontWeight={600} fontSize={14}>
- Interface Settings
- </Text>
- <RowBetween>
- <RowFixed>
- <TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
- Toggle Expert Mode
- </TYPE.black>
- <QuestionHelper text="Bypasses confirmation modals and allows high slippage trades. Use at your own risk." />
- </RowFixed>
- <Toggle
- id="toggle-expert-mode-button"
- isActive={expertMode}
- toggle={
- expertMode
- ? () => {
- toggleExpertMode()
- setShowConfirmation(false)
- }
- : () => {
- toggle()
- setShowConfirmation(true)
- }
- }
- />
- </RowBetween>
- <RowBetween>
- <RowFixed>
- <TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
- Disable Multihops
- </TYPE.black>
- <QuestionHelper text="Restricts swaps to direct pairs only." />
- </RowFixed>
- <Toggle
- id="toggle-disable-multihop-button"
- isActive={singleHopOnly}
- toggle={() => (singleHopOnly ? setSingleHopOnly(false) : setSingleHopOnly(true))}
- />
- </RowBetween>
- </AutoColumn>
- </MenuFlyout>
- )}
- </StyledMenu>
- )
-}
diff --git a/src/components/Slider/index.tsx b/src/components/Slider/index.tsx
deleted file mode 100644
index 11f5b5c..0000000
--- a/src/components/Slider/index.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import React, { useCallback } from 'react'
-import styled from 'styled-components'
-
-const StyledRangeInput = styled.input<{ size: number }>`
- -webkit-appearance: none; /* Hides the slider so that custom slider can be made */
- width: 100%; /* Specific width is required for Firefox. */
- background: transparent; /* Otherwise white in Chrome */
- cursor: pointer;
-
- &:focus {
- outline: none;
- }
-
- &::-moz-focus-outer {
- border: 0;
- }
-
- &::-webkit-slider-thumb {
- -webkit-appearance: none;
- height: ${({ size }) => size}px;
- width: ${({ size }) => size}px;
- background-color: #565a69;
- border-radius: 100%;
- border: none;
- transform: translateY(-50%);
- color: ${({ theme }) => theme.bg1};
-
- &:hover,
- &:focus {
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.1), 0px 4px 8px rgba(0, 0, 0, 0.08), 0px 16px 24px rgba(0, 0, 0, 0.06),
- 0px 24px 32px rgba(0, 0, 0, 0.04);
- }
- }
-
- &::-moz-range-thumb {
- height: ${({ size }) => size}px;
- width: ${({ size }) => size}px;
- background-color: #565a69;
- border-radius: 100%;
- border: none;
- color: ${({ theme }) => theme.bg1};
-
- &:hover,
- &:focus {
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.1), 0px 4px 8px rgba(0, 0, 0, 0.08), 0px 16px 24px rgba(0, 0, 0, 0.06),
- 0px 24px 32px rgba(0, 0, 0, 0.04);
- }
- }
-
- &::-ms-thumb {
- height: ${({ size }) => size}px;
- width: ${({ size }) => size}px;
- background-color: #565a69;
- border-radius: 100%;
- color: ${({ theme }) => theme.bg1};
-
- &:hover,
- &:focus {
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.1), 0px 4px 8px rgba(0, 0, 0, 0.08), 0px 16px 24px rgba(0, 0, 0, 0.06),
- 0px 24px 32px rgba(0, 0, 0, 0.04);
- }
- }
-
- &::-webkit-slider-runnable-track {
- background: linear-gradient(90deg, ${({ theme }) => theme.bg5}, ${({ theme }) => theme.bg3});
- height: 2px;
- }
-
- &::-moz-range-track {
- background: linear-gradient(90deg, ${({ theme }) => theme.bg5}, ${({ theme }) => theme.bg3});
- height: 2px;
- }
-
- &::-ms-track {
- width: 100%;
- border-color: transparent;
- color: transparent;
-
- background: ${({ theme }) => theme.bg5};
- height: 2px;
- }
- &::-ms-fill-lower {
- background: ${({ theme }) => theme.bg5};
- }
- &::-ms-fill-upper {
- background: ${({ theme }) => theme.bg3};
- }
-`
-
-interface InputSliderProps {
- value: number
- onChange: (value: number) => void
- step?: number
- min?: number
- max?: number
- size?: number
-}
-
-export default function Slider({ value, onChange, min = 0, step = 1, max = 100, size = 28 }: InputSliderProps) {
- const changeCallback = useCallback(
- (e) => {
- onChange(parseInt(e.target.value))
- },
- [onChange]
- )
-
- return (
- <StyledRangeInput
- size={size}
- type="range"
- value={value}
- style={{ width: '90%', marginLeft: 15, marginRight: 15, padding: '15px 0' }}
- onChange={changeCallback}
- aria-labelledby="input slider"
- step={step}
- min={min}
- max={max}
- />
- )
-}
diff --git a/src/components/TokenWarningModal/index.tsx b/src/components/TokenWarningModal/index.tsx
deleted file mode 100644
index d2277a3..0000000
--- a/src/components/TokenWarningModal/index.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Token } from '@uniswap/sdk'
-import React, { useCallback } from 'react'
-import Modal from '../Modal'
-import { ImportToken } from 'components/SearchModal/ImportToken'
-
-export default function TokenWarningModal({
- isOpen,
- tokens,
- onConfirm,
-}: {
- isOpen: boolean
- tokens: Token[]
- onConfirm: () => void
-}) {
- const handleDismiss = useCallback(() => null, [])
-
- return (
- <Modal isOpen={isOpen} onDismiss={handleDismiss} maxHeight={90}>
- <ImportToken tokens={tokens} handleCurrencySelect={onConfirm} />
- </Modal>
- )
-}
diff --git a/src/components/TransactionConfirmationModal/index.tsx b/src/components/TransactionConfirmationModal/index.tsx
deleted file mode 100644
index a75379c..0000000
--- a/src/components/TransactionConfirmationModal/index.tsx
+++ /dev/null
@@ -1,225 +0,0 @@
-import { ChainId, Currency } from '@uniswap/sdk'
-import React, { useContext } from 'react'
-import styled, { ThemeContext } from 'styled-components'
-import Modal from '../Modal'
-import { ExternalLink } from '../../theme'
-import { Text } from 'rebass'
-import { CloseIcon, CustomLightSpinner } from '../../theme/components'
-import { RowBetween, RowFixed } from '../Row'
-import { AlertTriangle, ArrowUpCircle, CheckCircle } from 'react-feather'
-import { ButtonPrimary, ButtonLight } from '../Button'
-import { AutoColumn, ColumnCenter } from '../Column'
-import Circle from '../../assets/images/blue-loader.svg'
-import MetaMaskLogo from '../../assets/images/metamask.png'
-import { getEtherscanLink } from '../../utils'
-import { useActiveWeb3React } from '../../hooks'
-import useAddTokenToMetamask from 'hooks/useAddTokenToMetamask'
-
-const Wrapper = styled.div`
- width: 100%;
-`
-const Section = styled(AutoColumn)`
- padding: 24px;
-`
-
-const BottomSection = styled(Section)`
- // background-color: ${({ theme }) => theme.bg2};
- border-bottom-left-radius: 20px;
- border-bottom-right-radius: 20px;
-`
-
-const ConfirmedIcon = styled(ColumnCenter)`
- padding: 60px 0;
-`
-
-const StyledLogo = styled.img`
- height: 16px;
- width: 16px;
- margin-left: 6px;
-`
-
-function ConfirmationPendingContent({ onDismiss, pendingText }: { onDismiss: () => void; pendingText: string }) {
- return (
- <Wrapper>
- <Section>
- <RowBetween>
- <div />
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- <ConfirmedIcon>
- <CustomLightSpinner src={Circle} alt="loader" size={'90px'} />
- </ConfirmedIcon>
- <AutoColumn gap="12px" justify={'center'}>
- <Text fontWeight={500} fontSize={20}>
- Waiting For Confirmation
- </Text>
- <AutoColumn gap="12px" justify={'center'}>
- <Text fontWeight={600} fontSize={14} color="" textAlign="center">
- {pendingText}
- </Text>
- </AutoColumn>
- <Text fontSize={12} color="#565A69" textAlign="center">
- Confirm this transaction in your wallet
- </Text>
- </AutoColumn>
- </Section>
- </Wrapper>
- )
-}
-
-function TransactionSubmittedContent({
- onDismiss,
- chainId,
- hash,
- currencyToAdd,
-}: {
- onDismiss: () => void
- hash: string | undefined
- chainId: ChainId
- currencyToAdd?: Currency | undefined
-}) {
- const theme = useContext(ThemeContext)
-
- const { library } = useActiveWeb3React()
-
- const { addToken, success } = useAddTokenToMetamask(currencyToAdd)
-
- return (
- <Wrapper>
- <Section>
- <RowBetween>
- <div />
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- <ConfirmedIcon>
- <ArrowUpCircle strokeWidth={0.5} size={90} color={theme.primary1} />
- </ConfirmedIcon>
- <AutoColumn gap="12px" justify={'center'}>
- <Text fontWeight={500} fontSize={20}>
- Transaction Submitted
- </Text>
- {chainId && hash && (
- <ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')}>
- <Text fontWeight={500} fontSize={14} color={theme.primary1}>
- View on Etherscan
- </Text>
- </ExternalLink>
- )}
- {currencyToAdd && library?.provider?.isMetaMask && (
- <ButtonLight mt="12px" padding="6px 12px" width="fit-content" onClick={addToken}>
- {!success ? (
- <RowFixed>
- Add {currencyToAdd.symbol} to Metamask <StyledLogo src={MetaMaskLogo} />
- </RowFixed>
- ) : (
- <RowFixed>
- Added {currencyToAdd.symbol}{' '}
- <CheckCircle size={'16px'} stroke={theme.green1} style={{ marginLeft: '6px' }} />
- </RowFixed>
- )}
- </ButtonLight>
- )}
- <ButtonPrimary onClick={onDismiss} style={{ margin: '20px 0 0 0' }}>
- <Text fontWeight={500} fontSize={20}>
- Close
- </Text>
- </ButtonPrimary>
- </AutoColumn>
- </Section>
- </Wrapper>
- )
-}
-
-export function ConfirmationModalContent({
- title,
- bottomContent,
- onDismiss,
- topContent,
-}: {
- title: string
- onDismiss: () => void
- topContent: () => React.ReactNode
- bottomContent?: () => React.ReactNode | undefined
-}) {
- return (
- <Wrapper>
- <Section>
- <RowBetween>
- <Text fontWeight={500} fontSize={20}>
- {title}
- </Text>
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- {topContent()}
- </Section>
- {bottomContent && <BottomSection gap="12px">{bottomContent()}</BottomSection>}
- </Wrapper>
- )
-}
-
-export function TransactionErrorContent({ message, onDismiss }: { message: string; onDismiss: () => void }) {
- const theme = useContext(ThemeContext)
- return (
- <Wrapper>
- <Section>
- <RowBetween>
- <Text fontWeight={500} fontSize={20}>
- Error
- </Text>
- <CloseIcon onClick={onDismiss} />
- </RowBetween>
- <AutoColumn style={{ marginTop: 20, padding: '2rem 0' }} gap="24px" justify="center">
- <AlertTriangle color={theme.red1} style={{ strokeWidth: 1.5 }} size={64} />
- <Text fontWeight={500} fontSize={16} color={theme.red1} style={{ textAlign: 'center', width: '85%' }}>
- {message}
- </Text>
- </AutoColumn>
- </Section>
- <BottomSection gap="12px">
- <ButtonPrimary onClick={onDismiss}>Dismiss</ButtonPrimary>
- </BottomSection>
- </Wrapper>
- )
-}
-
-interface ConfirmationModalProps {
- isOpen: boolean
- onDismiss: () => void
- hash: string | undefined
- content: () => React.ReactNode
- attemptingTxn: boolean
- pendingText: string
- currencyToAdd?: Currency | undefined
-}
-
-export default function TransactionConfirmationModal({
- isOpen,
- onDismiss,
- attemptingTxn,
- hash,
- pendingText,
- content,
- currencyToAdd,
-}: ConfirmationModalProps) {
- const { chainId } = useActiveWeb3React()
-
- if (!chainId) return null
-
- // confirmation screen
- return (
- <Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={90}>
- {attemptingTxn ? (
- <ConfirmationPendingContent onDismiss={onDismiss} pendingText={pendingText} />
- ) : hash ? (
- <TransactionSubmittedContent
- chainId={chainId}
- hash={hash}
- onDismiss={onDismiss}
- currencyToAdd={currencyToAdd}
- />
- ) : (
- content()
- )}
- </Modal>
- )
-}
diff --git a/src/components/TransactionSettings/index.tsx b/src/components/TransactionSettings/index.tsx
deleted file mode 100644
index 918ce4f..0000000
--- a/src/components/TransactionSettings/index.tsx
+++ /dev/null
@@ -1,252 +0,0 @@
-import React, { useState, useRef, useContext } from 'react'
-import styled, { ThemeContext } from 'styled-components'
-
-import QuestionHelper from '../QuestionHelper'
-import { TYPE } from '../../theme'
-import { AutoColumn } from '../Column'
-import { RowBetween, RowFixed } from '../Row'
-
-import { darken } from 'polished'
-
-enum SlippageError {
- InvalidInput = 'InvalidInput',
- RiskyLow = 'RiskyLow',
- RiskyHigh = 'RiskyHigh',
-}
-
-enum DeadlineError {
- InvalidInput = 'InvalidInput',
-}
-
-const FancyButton = styled.button`
- color: ${({ theme }) => theme.text1};
- align-items: center;
- height: 2rem;
- border-radius: 36px;
- font-size: 1rem;
- width: auto;
- min-width: 3.5rem;
- border: 1px solid ${({ theme }) => theme.bg3};
- outline: none;
- background: ${({ theme }) => theme.bg1};
- :hover {
- border: 1px solid ${({ theme }) => theme.bg4};
- }
- :focus {
- border: 1px solid ${({ theme }) => theme.primary1};
- }
-`
-
-const Option = styled(FancyButton)<{ active: boolean }>`
- margin-right: 8px;
- :hover {
- cursor: pointer;
- }
- background-color: ${({ active, theme }) => active && theme.primary1};
- color: ${({ active, theme }) => (active ? theme.white : theme.text1)};
-`
-
-const Input = styled.input`
- background: ${({ theme }) => theme.bg1};
- font-size: 16px;
- width: auto;
- outline: none;
- &::-webkit-outer-spin-button,
- &::-webkit-inner-spin-button {
- -webkit-appearance: none;
- }
- color: ${({ theme, color }) => (color === 'red' ? theme.red1 : theme.text1)};
- text-align: right;
-`
-
-const OptionCustom = styled(FancyButton)<{ active?: boolean; warning?: boolean }>`
- height: 2rem;
- position: relative;
- padding: 0 0.75rem;
- flex: 1;
- border: ${({ theme, active, warning }) => active && `1px solid ${warning ? theme.red1 : theme.primary1}`};
- :hover {
- border: ${({ theme, active, warning }) =>
- active && `1px solid ${warning ? darken(0.1, theme.red1) : darken(0.1, theme.primary1)}`};
- }
-
- input {
- width: 100%;
- height: 100%;
- border: 0px;
- border-radius: 2rem;
- }
-`
-
-const SlippageEmojiContainer = styled.span`
- color: #f3841e;
- ${({ theme }) => theme.mediaWidth.upToSmall`
- display: none;
- `}
-`
-
-export interface SlippageTabsProps {
- rawSlippage: number
- setRawSlippage: (rawSlippage: number) => void
- deadline: number
- setDeadline: (deadline: number) => void
-}
-
-export default function SlippageTabs({ rawSlippage, setRawSlippage, deadline, setDeadline }: SlippageTabsProps) {
- const theme = useContext(ThemeContext)
-
- const inputRef = useRef<HTMLInputElement>()
-
- const [slippageInput, setSlippageInput] = useState('')
- const [deadlineInput, setDeadlineInput] = useState('')
-
- const slippageInputIsValid =
- slippageInput === '' || (rawSlippage / 100).toFixed(2) === Number.parseFloat(slippageInput).toFixed(2)
- const deadlineInputIsValid = deadlineInput === '' || (deadline / 60).toString() === deadlineInput
-
- let slippageError: SlippageError | undefined
- if (slippageInput !== '' && !slippageInputIsValid) {
- slippageError = SlippageError.InvalidInput
- } else if (slippageInputIsValid && rawSlippage < 50) {
- slippageError = SlippageError.RiskyLow
- } else if (slippageInputIsValid && rawSlippage > 500) {
- slippageError = SlippageError.RiskyHigh
- } else {
- slippageError = undefined
- }
-
- let deadlineError: DeadlineError | undefined
- if (deadlineInput !== '' && !deadlineInputIsValid) {
- deadlineError = DeadlineError.InvalidInput
- } else {
- deadlineError = undefined
- }
-
- function parseCustomSlippage(value: string) {
- setSlippageInput(value)
-
- try {
- const valueAsIntFromRoundedFloat = Number.parseInt((Number.parseFloat(value) * 100).toString())
- if (!Number.isNaN(valueAsIntFromRoundedFloat) && valueAsIntFromRoundedFloat < 5000) {
- setRawSlippage(valueAsIntFromRoundedFloat)
- }
- } catch {}
- }
-
- function parseCustomDeadline(value: string) {
- setDeadlineInput(value)
-
- try {
- const valueAsInt: number = Number.parseInt(value) * 60
- if (!Number.isNaN(valueAsInt) && valueAsInt > 0) {
- setDeadline(valueAsInt)
- }
- } catch {}
- }
-
- return (
- <AutoColumn gap="md">
- <AutoColumn gap="sm">
- <RowFixed>
- <TYPE.black fontWeight={400} fontSize={14} color={theme.text2}>
- Slippage tolerance
- </TYPE.black>
- <QuestionHelper text="Your transaction will revert if the price changes unfavorably by more than this percentage." />
- </RowFixed>
- <RowBetween>
- <Option
- onClick={() => {
- setSlippageInput('')
- setRawSlippage(10)
- }}
- active={rawSlippage === 10}
- >
- 0.1%
- </Option>
- <Option
- onClick={() => {
- setSlippageInput('')
- setRawSlippage(50)
- }}
- active={rawSlippage === 50}
- >
- 0.5%
- </Option>
- <Option
- onClick={() => {
- setSlippageInput('')
- setRawSlippage(100)
- }}
- active={rawSlippage === 100}
- >
- 1%
- </Option>
- <OptionCustom active={![10, 50, 100].includes(rawSlippage)} warning={!slippageInputIsValid} tabIndex={-1}>
- <RowBetween>
- {!!slippageInput &&
- (slippageError === SlippageError.RiskyLow || slippageError === SlippageError.RiskyHigh) ? (
- <SlippageEmojiContainer>
- <span role="img" aria-label="warning">
- ⚠️
- </span>
- </SlippageEmojiContainer>
- ) : null}
- {/* https://github.com/DefinitelyTyped/DefinitelyTyped/issues/30451 */}
- <Input
- ref={inputRef as any}
- placeholder={(rawSlippage / 100).toFixed(2)}
- value={slippageInput}
- onBlur={() => {
- parseCustomSlippage((rawSlippage / 100).toFixed(2))
- }}
- onChange={(e) => parseCustomSlippage(e.target.value)}
- color={!slippageInputIsValid ? 'red' : ''}
- />
- %
- </RowBetween>
- </OptionCustom>
- </RowBetween>
- {!!slippageError && (
- <RowBetween
- style={{
- fontSize: '14px',
- paddingTop: '7px',
- color: slippageError === SlippageError.InvalidInput ? 'red' : '#F3841E',
- }}
- >
- {slippageError === SlippageError.InvalidInput
- ? 'Enter a valid slippage percentage'
- : slippageError === SlippageError.RiskyLow
- ? 'Your transaction may fail'
- : 'Your transaction may be frontrun'}
- </RowBetween>
- )}
- </AutoColumn>
-
- <AutoColumn gap="sm">
- <RowFixed>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- Transaction deadline
- </TYPE.black>
- <QuestionHelper text="Your transaction will revert if it is pending for more than this long." />
- </RowFixed>
- <RowFixed>
- <OptionCustom style={{ width: '80px' }} tabIndex={-1}>
- <Input
- color={!!deadlineError ? 'red' : undefined}
- onBlur={() => {
- parseCustomDeadline((deadline / 60).toString())
- }}
- placeholder={(deadline / 60).toString()}
- value={deadlineInput}
- onChange={(e) => parseCustomDeadline(e.target.value)}
- />
- </OptionCustom>
- <TYPE.body style={{ paddingLeft: '8px' }} fontSize={14}>
- minutes
- </TYPE.body>
- </RowFixed>
- </AutoColumn>
- </AutoColumn>
- )
-}
diff --git a/src/components/WalletModal/index.tsx b/src/components/WalletModal/index.tsx
index b916780..a9669d6 100644
--- a/src/components/WalletModal/index.tsx
+++ b/src/components/WalletModal/index.tsx
@@ -116,15 +116,7 @@ const WALLET_VIEWS = {
PENDING: 'pending',
}
-export default function WalletModal({
- pendingTransactions,
- confirmedTransactions,
- ENSName,
-}: {
- pendingTransactions: string[] // hashes of pending
- confirmedTransactions: string[] // hashes of confirmed
- ENSName?: string
-}) {
+export default function WalletModal({ ENSName }: { ENSName?: string }) {
// important that these are destructed from the account-specific web3-react context
const { active, account, connector, activate, error } = useWeb3React()
@@ -310,8 +302,6 @@ export default function WalletModal({
return (
<AccountDetails
toggleWalletModal={toggleWalletModal}
- pendingTransactions={pendingTransactions}
- confirmedTransactions={confirmedTransactions}
ENSName={ENSName}
openOptions={() => setWalletView(WALLET_VIEWS.OPTIONS)}
/>
diff --git a/src/components/Web3Status/index.tsx b/src/components/Web3Status/index.tsx
index b3bac3c..ec82d1c 100644
--- a/src/components/Web3Status/index.tsx
+++ b/src/components/Web3Status/index.tsx
@@ -1,7 +1,7 @@
import { AbstractConnector } from '@web3-react/abstract-connector'
import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core'
import { darken, lighten } from 'polished'
-import React, { useMemo } from 'react'
+import React from 'react'
import { Activity } from 'react-feather'
import { useTranslation } from 'react-i18next'
import styled, { css } from 'styled-components'
@@ -14,15 +14,11 @@ import { NetworkContextName } from '../../constants'
import useENSName from '../../hooks/useENSName'
import { useHasSocks } from '../../hooks/useSocksBalance'
import { useWalletModalToggle } from '../../state/application/hooks'
-import { isTransactionRecent, useAllTransactions } from '../../state/transactions/hooks'
-import { TransactionDetails } from '../../state/transactions/reducer'
import { shortenAddress } from '../../utils'
import { ButtonSecondary } from '../Button'
import Identicon from '../Identicon'
-import Loader from '../Loader'
-import { RowBetween } from '../Row'
import WalletModal from '../WalletModal'
const IconWrapper = styled.div<{ size?: number }>`
@@ -118,11 +114,6 @@ const NetworkIcon = styled(Activity)`
height: 16px;
`
-// we want the latest one to come first, so return negative if a is after b
-function newTransactionsFirst(a: TransactionDetails, b: TransactionDetails) {
- return b.addedTime - a.addedTime
-}
-
const SOCK = (
<span role="img" aria-label="has socks emoji" style={{ marginTop: -4, marginBottom: -4 }}>
🧦
@@ -167,33 +158,15 @@ function Web3StatusInner() {
const { ENSName } = useENSName(account ?? undefined)
- const allTransactions = useAllTransactions()
-
- const sortedRecentTransactions = useMemo(() => {
- const txs = Object.values(allTransactions)
- return txs.filter(isTransactionRecent).sort(newTransactionsFirst)
- }, [allTransactions])
-
- const pending = sortedRecentTransactions.filter((tx) => !tx.receipt).map((tx) => tx.hash)
-
- const hasPendingTransactions = !!pending.length
const hasSocks = useHasSocks()
const toggleWalletModal = useWalletModalToggle()
if (account) {
return (
- <Web3StatusConnected id="web3-status-connected" onClick={toggleWalletModal} pending={hasPendingTransactions}>
- {hasPendingTransactions ? (
- <RowBetween>
- <Text>{pending?.length} Pending</Text> <Loader stroke="white" />
- </RowBetween>
- ) : (
- <>
- {hasSocks ? SOCK : null}
- <Text>{ENSName || shortenAddress(account)}</Text>
- </>
- )}
- {!hasPendingTransactions && connector && <StatusIcon connector={connector} />}
+ <Web3StatusConnected id="web3-status-connected" onClick={toggleWalletModal}>
+ {hasSocks ? SOCK : null}
+ <Text>{ENSName || shortenAddress(account)}</Text>
+ {connector && <StatusIcon connector={connector} />}
</Web3StatusConnected>
)
} else if (error) {
@@ -218,16 +191,6 @@ export default function Web3Status() {
const { ENSName } = useENSName(account ?? undefined)
- const allTransactions = useAllTransactions()
-
- const sortedRecentTransactions = useMemo(() => {
- const txs = Object.values(allTransactions)
- return txs.filter(isTransactionRecent).sort(newTransactionsFirst)
- }, [allTransactions])
-
- const pending = sortedRecentTransactions.filter((tx) => !tx.receipt).map((tx) => tx.hash)
- const confirmed = sortedRecentTransactions.filter((tx) => tx.receipt).map((tx) => tx.hash)
-
if (!contextNetwork.active && !active) {
return null
}
@@ -235,7 +198,7 @@ export default function Web3Status() {
return (
<>
<Web3StatusInner />
- <WalletModal ENSName={ENSName ?? undefined} pendingTransactions={pending} confirmedTransactions={confirmed} />
+ <WalletModal ENSName={ENSName ?? undefined} />
</>
)
}
diff --git a/src/components/claim/AddressClaimModal.tsx b/src/components/claim/AddressClaimModal.tsx
deleted file mode 100644
index a9d88ff..0000000
--- a/src/components/claim/AddressClaimModal.tsx
+++ /dev/null
@@ -1,193 +0,0 @@
-import React, { useState } from 'react'
-import Modal from '../Modal'
-import { AutoColumn, ColumnCenter } from '../Column'
-import styled from 'styled-components'
-import { DataCard, CardSection, Break } from '../earn/styled'
-import { RowBetween } from '../Row'
-import { TYPE, ExternalLink, CloseIcon, CustomLightSpinner, UniTokenAnimated } from '../../theme'
-import { ButtonPrimary } from '../Button'
-import { useClaimCallback, useUserUnclaimedAmount, useUserHasAvailableClaim } from '../../state/claim/hooks'
-import tokenLogo from '../../assets/images/token-logo.png'
-import Circle from '../../assets/images/blue-loader.svg'
-import { Text } from 'rebass'
-import AddressInputPanel from '../AddressInputPanel'
-import useENS from '../../hooks/useENS'
-import { useActiveWeb3React } from '../../hooks'
-import { isAddress } from 'ethers/lib/utils'
-import Confetti from '../Confetti'
-import { CardNoise, CardBGImage, CardBGImageSmaller } from '../earn/styled'
-import { useIsTransactionPending } from '../../state/transactions/hooks'
-import { TokenAmount } from '@uniswap/sdk'
-import { getEtherscanLink, shortenAddress } from '../../utils'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
-`
-
-const ModalUpper = styled(DataCard)`
- box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
- background: radial-gradient(76.02% 75.41% at 1.84% 0%, #ff007a 0%, #021d43 100%);
-`
-
-const ConfirmOrLoadingWrapper = styled.div<{ activeBG: boolean }>`
- width: 100%;
- padding: 24px;
- position: relative;
- background: ${({ activeBG }) =>
- activeBG &&
- 'radial-gradient(76.02% 75.41% at 1.84% 0%, rgba(255, 0, 122, 0.2) 0%, rgba(33, 114, 229, 0.2) 100%), #FFFFFF;'};
-`
-
-const ConfirmedIcon = styled(ColumnCenter)`
- padding: 60px 0;
-`
-
-export default function AddressClaimModal({ isOpen, onDismiss }: { isOpen: boolean; onDismiss: () => void }) {
- const { chainId } = useActiveWeb3React()
-
- // state for smart contract input
- const [typed, setTyped] = useState('')
- function handleRecipientType(val: string) {
- setTyped(val)
- }
-
- // monitor for third party recipient of claim
- const { address: parsedAddress } = useENS(typed)
-
- // used for UI loading states
- const [attempting, setAttempting] = useState<boolean>(false)
-
- // monitor the status of the claim from contracts and txns
- const { claimCallback } = useClaimCallback(parsedAddress)
- const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(parsedAddress)
-
- // check if the user has something available
- const hasAvailableClaim = useUserHasAvailableClaim(parsedAddress)
-
- const [hash, setHash] = useState<string | undefined>()
-
- // monitor the status of the claim from contracts and txns
- const claimPending = useIsTransactionPending(hash ?? '')
- const claimConfirmed = hash && !claimPending
-
- // use the hash to monitor this txn
-
- function onClaim() {
- setAttempting(true)
- claimCallback()
- .then((hash) => {
- setHash(hash)
- })
- // reset modal and log error
- .catch((error) => {
- setAttempting(false)
- console.log(error)
- })
- }
-
- function wrappedOnDismiss() {
- setAttempting(false)
- setHash(undefined)
- setTyped('')
- onDismiss()
- }
-
- return (
- <Modal isOpen={isOpen} onDismiss={wrappedOnDismiss} maxHeight={90}>
- <Confetti start={Boolean(isOpen && claimConfirmed && attempting)} />
- {!attempting && (
- <ContentWrapper gap="lg">
- <ModalUpper>
- <CardBGImage />
- <CardNoise />
- <CardSection gap="md">
- <RowBetween>
- <TYPE.white fontWeight={500}>Claim UNI Token</TYPE.white>
- <CloseIcon onClick={wrappedOnDismiss} style={{ zIndex: 99 }} stroke="white" />
- </RowBetween>
- <TYPE.white fontWeight={700} fontSize={36}>
- {unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
- </TYPE.white>
- </CardSection>
- <Break />
- </ModalUpper>
- <AutoColumn gap="md" style={{ padding: '1rem', paddingTop: '0' }} justify="center">
- <TYPE.subHeader fontWeight={500}>
- Enter an address to trigger a UNI claim. If the address has any claimable UNI it will be sent to them on
- submission.
- </TYPE.subHeader>
- <AddressInputPanel value={typed} onChange={handleRecipientType} />
- {parsedAddress && !hasAvailableClaim && (
- <TYPE.error error={true}>Address has no available claim</TYPE.error>
- )}
- <ButtonPrimary
- disabled={!isAddress(parsedAddress ?? '') || !hasAvailableClaim}
- padding="16px 16px"
- width="100%"
- borderRadius="12px"
- mt="1rem"
- onClick={onClaim}
- >
- Claim UNI
- </ButtonPrimary>
- </AutoColumn>
- </ContentWrapper>
- )}
- {(attempting || claimConfirmed) && (
- <ConfirmOrLoadingWrapper activeBG={true}>
- <CardNoise />
- <CardBGImageSmaller desaturate />
- <RowBetween>
- <div />
- <CloseIcon onClick={wrappedOnDismiss} style={{ zIndex: 99 }} stroke="black" />
- </RowBetween>
- <ConfirmedIcon>
- {!claimConfirmed ? (
- <CustomLightSpinner src={Circle} alt="loader" size={'90px'} />
- ) : (
- <UniTokenAnimated width="72px" src={tokenLogo} />
- )}
- </ConfirmedIcon>
- <AutoColumn gap="100px" justify={'center'}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader fontWeight={600} color="black">
- {claimConfirmed ? 'Claimed' : 'Claiming'}
- </TYPE.largeHeader>
- {!claimConfirmed && (
- <Text fontSize={36} color={'#ff007a'} fontWeight={800}>
- {unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
- </Text>
- )}
- {parsedAddress && (
- <TYPE.largeHeader fontWeight={600} color="black">
- for {shortenAddress(parsedAddress)}
- </TYPE.largeHeader>
- )}
- </AutoColumn>
- {claimConfirmed && (
- <>
- <TYPE.subHeader fontWeight={500} color="black">
- <span role="img" aria-label="party-hat">
- 🎉{' '}
- </span>
- Welcome to team Unicorn :){' '}
- <span role="img" aria-label="party-hat">
- 🎉
- </span>
- </TYPE.subHeader>
- </>
- )}
- {attempting && !hash && (
- <TYPE.subHeader color="black">Confirm this transaction in your wallet</TYPE.subHeader>
- )}
- {attempting && hash && !claimConfirmed && chainId && hash && (
- <ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ zIndex: 99 }}>
- View transaction on Etherscan
- </ExternalLink>
- )}
- </AutoColumn>
- </ConfirmOrLoadingWrapper>
- )}
- </Modal>
- )
-}
diff --git a/src/components/claim/ClaimModal.tsx b/src/components/claim/ClaimModal.tsx
deleted file mode 100644
index 84529d7..0000000
--- a/src/components/claim/ClaimModal.tsx
+++ /dev/null
@@ -1,207 +0,0 @@
-import { JSBI, TokenAmount } from '@uniswap/sdk'
-import { isAddress } from 'ethers/lib/utils'
-import React, { useEffect, useState } from 'react'
-import { Text } from 'rebass'
-import styled from 'styled-components'
-import Circle from '../../assets/images/blue-loader.svg'
-import tokenLogo from '../../assets/images/token-logo.png'
-import { useActiveWeb3React } from '../../hooks'
-import { ApplicationModal } from '../../state/application/actions'
-import { useModalOpen, useToggleSelfClaimModal } from '../../state/application/hooks'
-import { useClaimCallback, useUserClaimData, useUserUnclaimedAmount } from '../../state/claim/hooks'
-import { useUserHasSubmittedClaim } from '../../state/transactions/hooks'
-import { CloseIcon, CustomLightSpinner, ExternalLink, TYPE, UniTokenAnimated } from '../../theme'
-import { getEtherscanLink } from '../../utils'
-import { ButtonPrimary } from '../Button'
-import { AutoColumn, ColumnCenter } from '../Column'
-import Confetti from '../Confetti'
-import { Break, CardBGImage, CardBGImageSmaller, CardNoise, CardSection, DataCard } from '../earn/styled'
-
-import Modal from '../Modal'
-import { RowBetween } from '../Row'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
-`
-
-const ModalUpper = styled(DataCard)`
- box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
- background: radial-gradient(76.02% 75.41% at 1.84% 0%, #ff007a 0%, #021d43 100%);
-`
-
-const ConfirmOrLoadingWrapper = styled.div<{ activeBG: boolean }>`
- width: 100%;
- padding: 24px;
- position: relative;
- background: ${({ activeBG }) =>
- activeBG &&
- 'radial-gradient(76.02% 75.41% at 1.84% 0%, rgba(255, 0, 122, 0.2) 0%, rgba(33, 114, 229, 0.2) 100%), #FFFFFF;'};
-`
-
-const ConfirmedIcon = styled(ColumnCenter)`
- padding: 60px 0;
-`
-
-const SOCKS_AMOUNT = 1000
-const USER_AMOUNT = 400
-
-export default function ClaimModal() {
- const isOpen = useModalOpen(ApplicationModal.SELF_CLAIM)
- const toggleClaimModal = useToggleSelfClaimModal()
-
- const { account, chainId } = useActiveWeb3React()
-
- // used for UI loading states
- const [attempting, setAttempting] = useState<boolean>(false)
-
- // get user claim data
- const userClaimData = useUserClaimData(account)
-
- // monitor the status of the claim from contracts and txns
- const { claimCallback } = useClaimCallback(account)
- const unclaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
- const { claimSubmitted, claimTxn } = useUserHasSubmittedClaim(account ?? undefined)
- const claimConfirmed = Boolean(claimTxn?.receipt)
-
- function onClaim() {
- setAttempting(true)
- claimCallback()
- // reset modal and log error
- .catch((error) => {
- setAttempting(false)
- console.log(error)
- })
- }
-
- // once confirmed txn is found, if modal is closed open, mark as not attempting regradless
- useEffect(() => {
- if (claimConfirmed && claimSubmitted && attempting) {
- setAttempting(false)
- if (!isOpen) {
- toggleClaimModal()
- }
- }
- }, [attempting, claimConfirmed, claimSubmitted, isOpen, toggleClaimModal])
-
- const nonLPAmount = JSBI.multiply(
- JSBI.BigInt((userClaimData?.flags?.isSOCKS ? SOCKS_AMOUNT : 0) + (userClaimData?.flags?.isUser ? USER_AMOUNT : 0)),
- JSBI.exponentiate(JSBI.BigInt(10), JSBI.BigInt(18))
- )
-
- return (
- <Modal isOpen={isOpen} onDismiss={toggleClaimModal} maxHeight={90}>
- <Confetti start={Boolean(isOpen && claimConfirmed)} />
- {!attempting && !claimConfirmed && (
- <ContentWrapper gap="lg">
- <ModalUpper>
- <CardBGImage />
- <CardNoise />
- <CardSection gap="md">
- <RowBetween>
- <TYPE.white fontWeight={500}>Claim UNI</TYPE.white>
- <CloseIcon onClick={toggleClaimModal} style={{ zIndex: 99 }} color="white" />
- </RowBetween>
- <TYPE.white fontWeight={700} fontSize={36}>
- {unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
- </TYPE.white>
- </CardSection>
- <Break />
- <CardSection gap="sm">
- {userClaimData?.flags?.isSOCKS && (
- <RowBetween>
- <TYPE.subHeader color="white">SOCKS</TYPE.subHeader>
- <TYPE.subHeader color="white">{SOCKS_AMOUNT} UNI</TYPE.subHeader>
- </RowBetween>
- )}
- {userClaimData?.flags?.isLP &&
- unclaimedAmount &&
- JSBI.greaterThanOrEqual(unclaimedAmount.raw, nonLPAmount) && (
- <RowBetween>
- <TYPE.subHeader color="white">Liquidity</TYPE.subHeader>
- <TYPE.subHeader color="white">
- {unclaimedAmount
- .subtract(new TokenAmount(unclaimedAmount.token, nonLPAmount))
- .toFixed(0, { groupSeparator: ',' })}{' '}
- UNI
- </TYPE.subHeader>
- </RowBetween>
- )}
- {userClaimData?.flags?.isUser && (
- <RowBetween>
- <TYPE.subHeader color="white">User</TYPE.subHeader>
- <TYPE.subHeader color="white">{USER_AMOUNT} UNI</TYPE.subHeader>
- </RowBetween>
- )}
- </CardSection>
- </ModalUpper>
- <AutoColumn gap="md" style={{ padding: '1rem', paddingTop: '0' }} justify="center">
- <TYPE.subHeader fontWeight={500}>
- As a member of the Uniswap community you may claim UNI to be used for voting and governance. <br /> <br />
- <ExternalLink href="https://uniswap.org/blog/uni">Read more about UNI</ExternalLink>
- </TYPE.subHeader>
- <ButtonPrimary
- disabled={!isAddress(account ?? '')}
- padding="16px 16px"
- width="100%"
- borderRadius="12px"
- mt="1rem"
- onClick={onClaim}
- >
- Claim UNI
- </ButtonPrimary>
- </AutoColumn>
- </ContentWrapper>
- )}
- {(attempting || claimConfirmed) && (
- <ConfirmOrLoadingWrapper activeBG={true}>
- <CardNoise />
- <CardBGImageSmaller desaturate />
- <RowBetween>
- <div />
- <CloseIcon onClick={toggleClaimModal} style={{ zIndex: 99 }} stroke="black" />
- </RowBetween>
- <ConfirmedIcon>
- {!claimConfirmed ? (
- <CustomLightSpinner src={Circle} alt="loader" size={'90px'} />
- ) : (
- <UniTokenAnimated width="72px" src={tokenLogo} />
- )}
- </ConfirmedIcon>
- <AutoColumn gap="100px" justify={'center'}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader fontWeight={600} color="black">
- {claimConfirmed ? 'Claimed!' : 'Claiming'}
- </TYPE.largeHeader>
- {!claimConfirmed && (
- <Text fontSize={36} color={'#ff007a'} fontWeight={800}>
- {unclaimedAmount?.toFixed(0, { groupSeparator: ',' } ?? '-')} UNI
- </Text>
- )}
- </AutoColumn>
- {claimConfirmed && (
- <>
- <TYPE.subHeader fontWeight={500} color="black">
- <span role="img" aria-label="party-hat">
- 🎉{' '}
- </span>
- Welcome to team Unicorn :){' '}
- <span role="img" aria-label="party-hat">
- 🎉
- </span>
- </TYPE.subHeader>
- </>
- )}
- {attempting && !claimSubmitted && (
- <TYPE.subHeader color="black">Confirm this transaction in your wallet</TYPE.subHeader>
- )}
- {attempting && claimSubmitted && !claimConfirmed && chainId && claimTxn?.hash && (
- <ExternalLink href={getEtherscanLink(chainId, claimTxn?.hash, 'transaction')} style={{ zIndex: 99 }}>
- View transaction on Etherscan
- </ExternalLink>
- )}
- </AutoColumn>
- </ConfirmOrLoadingWrapper>
- )}
- </Modal>
- )
-}
diff --git a/src/components/earn/ClaimRewardModal.tsx b/src/components/earn/ClaimRewardModal.tsx
deleted file mode 100644
index d030f66..0000000
--- a/src/components/earn/ClaimRewardModal.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import React, { useState } from 'react'
-import Modal from '../Modal'
-import { AutoColumn } from '../Column'
-import styled from 'styled-components'
-import { RowBetween } from '../Row'
-import { TYPE, CloseIcon } from '../../theme'
-import { ButtonError } from '../Button'
-import { StakingInfo } from '../../state/stake/hooks'
-import { useStakingContract } from '../../hooks/useContract'
-import { SubmittedView, LoadingView } from '../ModalViews'
-import { TransactionResponse } from '@ethersproject/providers'
-import { useTransactionAdder } from '../../state/transactions/hooks'
-import { useActiveWeb3React } from '../../hooks'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
- padding: 1rem;
-`
-
-interface StakingModalProps {
- isOpen: boolean
- onDismiss: () => void
- stakingInfo: StakingInfo
-}
-
-export default function ClaimRewardModal({ isOpen, onDismiss, stakingInfo }: StakingModalProps) {
- const { account } = useActiveWeb3React()
-
- // monitor call to help UI loading state
- const addTransaction = useTransactionAdder()
- const [hash, setHash] = useState<string | undefined>()
- const [attempting, setAttempting] = useState(false)
-
- function wrappedOnDismiss() {
- setHash(undefined)
- setAttempting(false)
- onDismiss()
- }
-
- const stakingContract = useStakingContract(stakingInfo.stakingRewardAddress)
-
- async function onClaimReward() {
- if (stakingContract && stakingInfo?.stakedAmount) {
- setAttempting(true)
- await stakingContract
- .getReward({ gasLimit: 350000 })
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: `Claim accumulated UNI rewards`,
- })
- setHash(response.hash)
- })
- .catch((error: any) => {
- setAttempting(false)
- console.log(error)
- })
- }
- }
-
- let error: string | undefined
- if (!account) {
- error = 'Connect Wallet'
- }
- if (!stakingInfo?.stakedAmount) {
- error = error ?? 'Enter an amount'
- }
-
- return (
- <Modal isOpen={isOpen} onDismiss={wrappedOnDismiss} maxHeight={90}>
- {!attempting && !hash && (
- <ContentWrapper gap="lg">
- <RowBetween>
- <TYPE.mediumHeader>Claim</TYPE.mediumHeader>
- <CloseIcon onClick={wrappedOnDismiss} />
- </RowBetween>
- {stakingInfo?.earnedAmount && (
- <AutoColumn justify="center" gap="md">
- <TYPE.body fontWeight={600} fontSize={36}>
- {stakingInfo?.earnedAmount?.toSignificant(6)}
- </TYPE.body>
- <TYPE.body>Unclaimed UNI</TYPE.body>
- </AutoColumn>
- )}
- <TYPE.subHeader style={{ textAlign: 'center' }}>
- When you claim without withdrawing your liquidity remains in the mining pool.
- </TYPE.subHeader>
- <ButtonError disabled={!!error} error={!!error && !!stakingInfo?.stakedAmount} onClick={onClaimReward}>
- {error ?? 'Claim'}
- </ButtonError>
- </ContentWrapper>
- )}
- {attempting && !hash && (
- <LoadingView onDismiss={wrappedOnDismiss}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.body fontSize={20}>Claiming {stakingInfo?.earnedAmount?.toSignificant(6)} UNI</TYPE.body>
- </AutoColumn>
- </LoadingView>
- )}
- {hash && (
- <SubmittedView onDismiss={wrappedOnDismiss} hash={hash}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
- <TYPE.body fontSize={20}>Claimed UNI!</TYPE.body>
- </AutoColumn>
- </SubmittedView>
- )}
- </Modal>
- )
-}
diff --git a/src/components/earn/PoolCard.tsx b/src/components/earn/PoolCard.tsx
deleted file mode 100644
index 35b68e5..0000000
--- a/src/components/earn/PoolCard.tsx
+++ /dev/null
@@ -1,175 +0,0 @@
-import React from 'react'
-import { AutoColumn } from '../Column'
-import { RowBetween } from '../Row'
-import styled from 'styled-components'
-import { TYPE, StyledInternalLink } from '../../theme'
-import DoubleCurrencyLogo from '../DoubleLogo'
-import { ETHER, JSBI, TokenAmount } from '@uniswap/sdk'
-import { ButtonPrimary } from '../Button'
-import { StakingInfo } from '../../state/stake/hooks'
-import { useColor } from '../../hooks/useColor'
-import { currencyId } from '../../utils/currencyId'
-import { Break, CardNoise, CardBGImage } from './styled'
-import { unwrappedToken } from '../../utils/wrappedCurrency'
-import { useTotalSupply } from '../../data/TotalSupply'
-import { usePair } from '../../data/Reserves'
-import useUSDCPrice from '../../utils/useUSDCPrice'
-import { BIG_INT_SECONDS_IN_WEEK } from '../../constants'
-
-const StatContainer = styled.div`
- display: flex;
- justify-content: space-between;
- flex-direction: column;
- gap: 12px;
- margin-bottom: 1rem;
- margin-right: 1rem;
- margin-left: 1rem;
- ${({ theme }) => theme.mediaWidth.upToSmall`
- display: none;
-`};
-`
-
-const Wrapper = styled(AutoColumn)<{ showBackground: boolean; bgColor: any }>`
- border-radius: 12px;
- width: 100%;
- overflow: hidden;
- position: relative;
- opacity: ${({ showBackground }) => (showBackground ? '1' : '1')};
- background: ${({ theme, bgColor, showBackground }) =>
- `radial-gradient(91.85% 100% at 1.84% 0%, ${bgColor} 0%, ${showBackground ? theme.black : theme.bg5} 100%) `};
- color: ${({ theme, showBackground }) => (showBackground ? theme.white : theme.text1)} !important;
-
- ${({ showBackground }) =>
- showBackground &&
- ` box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
- 0px 24px 32px rgba(0, 0, 0, 0.01);`}
-`
-
-const TopSection = styled.div`
- display: grid;
- grid-template-columns: 48px 1fr 120px;
- grid-gap: 0px;
- align-items: center;
- padding: 1rem;
- z-index: 1;
- ${({ theme }) => theme.mediaWidth.upToSmall`
- grid-template-columns: 48px 1fr 96px;
- `};
-`
-
-const BottomSection = styled.div<{ showBackground: boolean }>`
- padding: 12px 16px;
- opacity: ${({ showBackground }) => (showBackground ? '1' : '0.4')};
- border-radius: 0 0 12px 12px;
- display: flex;
- flex-direction: row;
- align-items: baseline;
- justify-content: space-between;
- z-index: 1;
-`
-
-export default function PoolCard({ stakingInfo }: { stakingInfo: StakingInfo }) {
- const token0 = stakingInfo.tokens[0]
- const token1 = stakingInfo.tokens[1]
-
- const currency0 = unwrappedToken(token0)
- const currency1 = unwrappedToken(token1)
-
- const isStaking = Boolean(stakingInfo.stakedAmount.greaterThan('0'))
-
- // get the color of the token
- const token = currency0 === ETHER ? token1 : token0
- const WETH = currency0 === ETHER ? token0 : token1
- const backgroundColor = useColor(token)
-
- const totalSupplyOfStakingToken = useTotalSupply(stakingInfo.stakedAmount.token)
- const [, stakingTokenPair] = usePair(...stakingInfo.tokens)
-
- // let returnOverMonth: Percent = new Percent('0')
- let valueOfTotalStakedAmountInWETH: TokenAmount | undefined
- if (totalSupplyOfStakingToken && stakingTokenPair) {
- // take the total amount of LP tokens staked, multiply by ETH value of all LP tokens, divide by all LP tokens
- valueOfTotalStakedAmountInWETH = new TokenAmount(
- WETH,
- JSBI.divide(
- JSBI.multiply(
- JSBI.multiply(stakingInfo.totalStakedAmount.raw, stakingTokenPair.reserveOf(WETH).raw),
- JSBI.BigInt(2) // this is b/c the value of LP shares are ~double the value of the WETH they entitle owner to
- ),
- totalSupplyOfStakingToken.raw
- )
- )
- }
-
- // get the USD value of staked WETH
- const USDPrice = useUSDCPrice(WETH)
- const valueOfTotalStakedAmountInUSDC =
- valueOfTotalStakedAmountInWETH && USDPrice?.quote(valueOfTotalStakedAmountInWETH)
-
- return (
- <Wrapper showBackground={isStaking} bgColor={backgroundColor}>
- <CardBGImage desaturate />
- <CardNoise />
-
- <TopSection>
- <DoubleCurrencyLogo currency0={currency0} currency1={currency1} size={24} />
- <TYPE.white fontWeight={600} fontSize={24} style={{ marginLeft: '8px' }}>
- {currency0.symbol}-{currency1.symbol}
- </TYPE.white>
-
- <StyledInternalLink to={`/uni/${currencyId(currency0)}/${currencyId(currency1)}`} style={{ width: '100%' }}>
- <ButtonPrimary padding="8px" borderRadius="8px">
- {isStaking ? 'Manage' : 'Deposit'}
- </ButtonPrimary>
- </StyledInternalLink>
- </TopSection>
-
- <StatContainer>
- <RowBetween>
- <TYPE.white> Total deposited</TYPE.white>
- <TYPE.white>
- {valueOfTotalStakedAmountInUSDC
- ? `$${valueOfTotalStakedAmountInUSDC.toFixed(0, { groupSeparator: ',' })}`
- : `${valueOfTotalStakedAmountInWETH?.toSignificant(4, { groupSeparator: ',' }) ?? '-'} ETH`}
- </TYPE.white>
- </RowBetween>
- <RowBetween>
- <TYPE.white> Pool rate </TYPE.white>
- <TYPE.white>
- {stakingInfo
- ? stakingInfo.active
- ? `${stakingInfo.totalRewardRate
- ?.multiply(BIG_INT_SECONDS_IN_WEEK)
- ?.toFixed(0, { groupSeparator: ',' })} UNI / week`
- : '0 UNI / week'
- : '-'}
- </TYPE.white>
- </RowBetween>
- </StatContainer>
-
- {isStaking && (
- <>
- <Break />
- <BottomSection showBackground={true}>
- <TYPE.black color={'white'} fontWeight={500}>
- <span>Your rate</span>
- </TYPE.black>
-
- <TYPE.black style={{ textAlign: 'right' }} color={'white'} fontWeight={500}>
- <span role="img" aria-label="wizard-icon" style={{ marginRight: '0.5rem' }}>
- ⚡
- </span>
- {stakingInfo
- ? stakingInfo.active
- ? `${stakingInfo.rewardRate
- ?.multiply(BIG_INT_SECONDS_IN_WEEK)
- ?.toSignificant(4, { groupSeparator: ',' })} UNI / week`
- : '0 UNI / week'
- : '-'}
- </TYPE.black>
- </BottomSection>
- </>
- )}
- </Wrapper>
- )
-}
diff --git a/src/components/earn/StakingModal.tsx b/src/components/earn/StakingModal.tsx
deleted file mode 100644
index 5343ee5..0000000
--- a/src/components/earn/StakingModal.tsx
+++ /dev/null
@@ -1,265 +0,0 @@
-import React, { useState, useCallback } from 'react'
-import useIsArgentWallet from '../../hooks/useIsArgentWallet'
-import useTransactionDeadline from '../../hooks/useTransactionDeadline'
-import Modal from '../Modal'
-import { AutoColumn } from '../Column'
-import styled from 'styled-components'
-import { RowBetween } from '../Row'
-import { TYPE, CloseIcon } from '../../theme'
-import { ButtonConfirmed, ButtonError } from '../Button'
-import ProgressCircles from '../ProgressSteps'
-import CurrencyInputPanel from '../CurrencyInputPanel'
-import { TokenAmount, Pair } from '@uniswap/sdk'
-import { useActiveWeb3React } from '../../hooks'
-import { maxAmountSpend } from '../../utils/maxAmountSpend'
-import { usePairContract, useStakingContract } from '../../hooks/useContract'
-import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallback'
-import { splitSignature } from 'ethers/lib/utils'
-import { StakingInfo, useDerivedStakeInfo } from '../../state/stake/hooks'
-import { wrappedCurrencyAmount } from '../../utils/wrappedCurrency'
-import { TransactionResponse } from '@ethersproject/providers'
-import { useTransactionAdder } from '../../state/transactions/hooks'
-import { LoadingView, SubmittedView } from '../ModalViews'
-
-const HypotheticalRewardRate = styled.div<{ dim: boolean }>`
- display: flex;
- justify-content: space-between;
- padding-right: 20px;
- padding-left: 20px;
-
- opacity: ${({ dim }) => (dim ? 0.5 : 1)};
-`
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
- padding: 1rem;
-`
-
-interface StakingModalProps {
- isOpen: boolean
- onDismiss: () => void
- stakingInfo: StakingInfo
- userLiquidityUnstaked: TokenAmount | undefined
-}
-
-export default function StakingModal({ isOpen, onDismiss, stakingInfo, userLiquidityUnstaked }: StakingModalProps) {
- const { account, chainId, library } = useActiveWeb3React()
-
- // track and parse user input
- const [typedValue, setTypedValue] = useState('')
- const { parsedAmount, error } = useDerivedStakeInfo(typedValue, stakingInfo.stakedAmount.token, userLiquidityUnstaked)
- const parsedAmountWrapped = wrappedCurrencyAmount(parsedAmount, chainId)
-
- let hypotheticalRewardRate: TokenAmount = new TokenAmount(stakingInfo.rewardRate.token, '0')
- if (parsedAmountWrapped?.greaterThan('0')) {
- hypotheticalRewardRate = stakingInfo.getHypotheticalRewardRate(
- stakingInfo.stakedAmount.add(parsedAmountWrapped),
- stakingInfo.totalStakedAmount.add(parsedAmountWrapped),
- stakingInfo.totalRewardRate
- )
- }
-
- // state for pending and submitted txn views
- const addTransaction = useTransactionAdder()
- const [attempting, setAttempting] = useState<boolean>(false)
- const [hash, setHash] = useState<string | undefined>()
- const wrappedOnDismiss = useCallback(() => {
- setHash(undefined)
- setAttempting(false)
- onDismiss()
- }, [onDismiss])
-
- // pair contract for this token to be staked
- const dummyPair = new Pair(new TokenAmount(stakingInfo.tokens[0], '0'), new TokenAmount(stakingInfo.tokens[1], '0'))
- const pairContract = usePairContract(dummyPair.liquidityToken.address)
-
- // approval data for stake
- const deadline = useTransactionDeadline()
- const [signatureData, setSignatureData] = useState<{ v: number; r: string; s: string; deadline: number } | null>(null)
- const [approval, approveCallback] = useApproveCallback(parsedAmount, stakingInfo.stakingRewardAddress)
-
- const isArgentWallet = useIsArgentWallet()
- const stakingContract = useStakingContract(stakingInfo.stakingRewardAddress)
- async function onStake() {
- setAttempting(true)
- if (stakingContract && parsedAmount && deadline) {
- if (approval === ApprovalState.APPROVED) {
- await stakingContract.stake(`0x${parsedAmount.raw.toString(16)}`, { gasLimit: 350000 })
- } else if (signatureData) {
- stakingContract
- .stakeWithPermit(
- `0x${parsedAmount.raw.toString(16)}`,
- signatureData.deadline,
- signatureData.v,
- signatureData.r,
- signatureData.s,
- { gasLimit: 350000 }
- )
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: `Deposit liquidity`,
- })
- setHash(response.hash)
- })
- .catch((error: any) => {
- setAttempting(false)
- console.log(error)
- })
- } else {
- setAttempting(false)
- throw new Error('Attempting to stake without approval or a signature. Please contact support.')
- }
- }
- }
-
- // wrapped onUserInput to clear signatures
- const onUserInput = useCallback((typedValue: string) => {
- setSignatureData(null)
- setTypedValue(typedValue)
- }, [])
-
- // used for max input button
- const maxAmountInput = maxAmountSpend(userLiquidityUnstaked)
- const atMaxAmount = Boolean(maxAmountInput && parsedAmount?.equalTo(maxAmountInput))
- const handleMax = useCallback(() => {
- maxAmountInput && onUserInput(maxAmountInput.toExact())
- }, [maxAmountInput, onUserInput])
-
- async function onAttemptToApprove() {
- if (!pairContract || !library || !deadline) throw new Error('missing dependencies')
- const liquidityAmount = parsedAmount
- if (!liquidityAmount) throw new Error('missing liquidity amount')
-
- if (isArgentWallet) {
- return approveCallback()
- }
-
- // try to gather a signature for permission
- const nonce = await pairContract.nonces(account)
-
- const EIP712Domain = [
- { name: 'name', type: 'string' },
- { name: 'version', type: 'string' },
- { name: 'chainId', type: 'uint256' },
- { name: 'verifyingContract', type: 'address' },
- ]
- const domain = {
- name: 'Uniswap V2',
- version: '1',
- chainId: chainId,
- verifyingContract: pairContract.address,
- }
- const Permit = [
- { name: 'owner', type: 'address' },
- { name: 'spender', type: 'address' },
- { name: 'value', type: 'uint256' },
- { name: 'nonce', type: 'uint256' },
- { name: 'deadline', type: 'uint256' },
- ]
- const message = {
- owner: account,
- spender: stakingInfo.stakingRewardAddress,
- value: liquidityAmount.raw.toString(),
- nonce: nonce.toHexString(),
- deadline: deadline.toNumber(),
- }
- const data = JSON.stringify({
- types: {
- EIP712Domain,
- Permit,
- },
- domain,
- primaryType: 'Permit',
- message,
- })
-
- library
- .send('eth_signTypedData_v4', [account, data])
- .then(splitSignature)
- .then((signature) => {
- setSignatureData({
- v: signature.v,
- r: signature.r,
- s: signature.s,
- deadline: deadline.toNumber(),
- })
- })
- .catch((error) => {
- // for all errors other than 4001 (EIP-1193 user rejected request), fall back to manual approve
- if (error?.code !== 4001) {
- approveCallback()
- }
- })
- }
-
- return (
- <Modal isOpen={isOpen} onDismiss={wrappedOnDismiss} maxHeight={90}>
- {!attempting && !hash && (
- <ContentWrapper gap="lg">
- <RowBetween>
- <TYPE.mediumHeader>Deposit</TYPE.mediumHeader>
- <CloseIcon onClick={wrappedOnDismiss} />
- </RowBetween>
- <CurrencyInputPanel
- value={typedValue}
- onUserInput={onUserInput}
- onMax={handleMax}
- showMaxButton={!atMaxAmount}
- currency={stakingInfo.stakedAmount.token}
- pair={dummyPair}
- label={''}
- disableCurrencySelect={true}
- customBalanceText={'Available to deposit: '}
- id="stake-liquidity-token"
- />
-
- <HypotheticalRewardRate dim={!hypotheticalRewardRate.greaterThan('0')}>
- <div>
- <TYPE.black fontWeight={600}>Weekly Rewards</TYPE.black>
- </div>
-
- <TYPE.black>
- {hypotheticalRewardRate.multiply((60 * 60 * 24 * 7).toString()).toSignificant(4, { groupSeparator: ',' })}{' '}
- UNI / week
- </TYPE.black>
- </HypotheticalRewardRate>
-
- <RowBetween>
- <ButtonConfirmed
- mr="0.5rem"
- onClick={onAttemptToApprove}
- confirmed={approval === ApprovalState.APPROVED || signatureData !== null}
- disabled={approval !== ApprovalState.NOT_APPROVED || signatureData !== null}
- >
- Approve
- </ButtonConfirmed>
- <ButtonError
- disabled={!!error || (signatureData === null && approval !== ApprovalState.APPROVED)}
- error={!!error && !!parsedAmount}
- onClick={onStake}
- >
- {error ?? 'Deposit'}
- </ButtonError>
- </RowBetween>
- <ProgressCircles steps={[approval === ApprovalState.APPROVED || signatureData !== null]} disabled={true} />
- </ContentWrapper>
- )}
- {attempting && !hash && (
- <LoadingView onDismiss={wrappedOnDismiss}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Depositing Liquidity</TYPE.largeHeader>
- <TYPE.body fontSize={20}>{parsedAmount?.toSignificant(4)} UNI-V2</TYPE.body>
- </AutoColumn>
- </LoadingView>
- )}
- {attempting && hash && (
- <SubmittedView onDismiss={wrappedOnDismiss} hash={hash}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
- <TYPE.body fontSize={20}>Deposited {parsedAmount?.toSignificant(4)} UNI-V2</TYPE.body>
- </AutoColumn>
- </SubmittedView>
- )}
- </Modal>
- )
-}
diff --git a/src/components/earn/UnstakingModal.tsx b/src/components/earn/UnstakingModal.tsx
deleted file mode 100644
index 8d01c32..0000000
--- a/src/components/earn/UnstakingModal.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import React, { useState } from 'react'
-import Modal from '../Modal'
-import { AutoColumn } from '../Column'
-import styled from 'styled-components'
-import { RowBetween } from '../Row'
-import { TYPE, CloseIcon } from '../../theme'
-import { ButtonError } from '../Button'
-import { StakingInfo } from '../../state/stake/hooks'
-import { useStakingContract } from '../../hooks/useContract'
-import { SubmittedView, LoadingView } from '../ModalViews'
-import { TransactionResponse } from '@ethersproject/providers'
-import { useTransactionAdder } from '../../state/transactions/hooks'
-import FormattedCurrencyAmount from '../FormattedCurrencyAmount'
-import { useActiveWeb3React } from '../../hooks'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
- padding: 1rem;
-`
-
-interface StakingModalProps {
- isOpen: boolean
- onDismiss: () => void
- stakingInfo: StakingInfo
-}
-
-export default function UnstakingModal({ isOpen, onDismiss, stakingInfo }: StakingModalProps) {
- const { account } = useActiveWeb3React()
-
- // monitor call to help UI loading state
- const addTransaction = useTransactionAdder()
- const [hash, setHash] = useState<string | undefined>()
- const [attempting, setAttempting] = useState(false)
-
- function wrappedOndismiss() {
- setHash(undefined)
- setAttempting(false)
- onDismiss()
- }
-
- const stakingContract = useStakingContract(stakingInfo.stakingRewardAddress)
-
- async function onWithdraw() {
- if (stakingContract && stakingInfo?.stakedAmount) {
- setAttempting(true)
- await stakingContract
- .exit({ gasLimit: 300000 })
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: `Withdraw deposited liquidity`,
- })
- setHash(response.hash)
- })
- .catch((error: any) => {
- setAttempting(false)
- console.log(error)
- })
- }
- }
-
- let error: string | undefined
- if (!account) {
- error = 'Connect Wallet'
- }
- if (!stakingInfo?.stakedAmount) {
- error = error ?? 'Enter an amount'
- }
-
- return (
- <Modal isOpen={isOpen} onDismiss={wrappedOndismiss} maxHeight={90}>
- {!attempting && !hash && (
- <ContentWrapper gap="lg">
- <RowBetween>
- <TYPE.mediumHeader>Withdraw</TYPE.mediumHeader>
- <CloseIcon onClick={wrappedOndismiss} />
- </RowBetween>
- {stakingInfo?.stakedAmount && (
- <AutoColumn justify="center" gap="md">
- <TYPE.body fontWeight={600} fontSize={36}>
- {<FormattedCurrencyAmount currencyAmount={stakingInfo.stakedAmount} />}
- </TYPE.body>
- <TYPE.body>Deposited liquidity:</TYPE.body>
- </AutoColumn>
- )}
- {stakingInfo?.earnedAmount && (
- <AutoColumn justify="center" gap="md">
- <TYPE.body fontWeight={600} fontSize={36}>
- {<FormattedCurrencyAmount currencyAmount={stakingInfo?.earnedAmount} />}
- </TYPE.body>
- <TYPE.body>Unclaimed UNI</TYPE.body>
- </AutoColumn>
- )}
- <TYPE.subHeader style={{ textAlign: 'center' }}>
- When you withdraw, your UNI is claimed and your liquidity is removed from the mining pool.
- </TYPE.subHeader>
- <ButtonError disabled={!!error} error={!!error && !!stakingInfo?.stakedAmount} onClick={onWithdraw}>
- {error ?? 'Withdraw & Claim'}
- </ButtonError>
- </ContentWrapper>
- )}
- {attempting && !hash && (
- <LoadingView onDismiss={wrappedOndismiss}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.body fontSize={20}>Withdrawing {stakingInfo?.stakedAmount?.toSignificant(4)} UNI-V2</TYPE.body>
- <TYPE.body fontSize={20}>Claiming {stakingInfo?.earnedAmount?.toSignificant(4)} UNI</TYPE.body>
- </AutoColumn>
- </LoadingView>
- )}
- {hash && (
- <SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
- <TYPE.body fontSize={20}>Withdrew UNI-V2!</TYPE.body>
- <TYPE.body fontSize={20}>Claimed UNI!</TYPE.body>
- </AutoColumn>
- </SubmittedView>
- )}
- </Modal>
- )
-}
diff --git a/src/components/earn/styled.ts b/src/components/earn/styled.ts
deleted file mode 100644
index b9ae3f4..0000000
--- a/src/components/earn/styled.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import styled from 'styled-components'
-import { AutoColumn } from '../Column'
-
-import uImage from '../../assets/images/big_unicorn.png'
-import xlUnicorn from '../../assets/images/xl_uni.png'
-import noise from '../../assets/images/noise.png'
-
-export const TextBox = styled.div`
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 4px 12px;
- border: 1px solid rgba(255, 255, 255, 0.4);
- border-radius: 20px;
- width: fit-content;
- justify-self: flex-end;
-`
-
-export const DataCard = styled(AutoColumn)<{ disabled?: boolean }>`
- background: radial-gradient(76.02% 75.41% at 1.84% 0%, #ff007a 0%, #2172e5 100%);
- border-radius: 12px;
- width: 100%;
- position: relative;
- overflow: hidden;
-`
-
-export const CardBGImage = styled.span<{ desaturate?: boolean }>`
- background: url(${uImage});
- width: 1000px;
- height: 600px;
- position: absolute;
- border-radius: 12px;
- opacity: 0.4;
- top: -100px;
- left: -100px;
- transform: rotate(-15deg);
- user-select: none;
-
- ${({ desaturate }) => desaturate && `filter: saturate(0)`}
-`
-
-export const CardBGImageSmaller = styled.span<{ desaturate?: boolean }>`
- background: url(${xlUnicorn});
- width: 1200px;
- height: 1200px;
- position: absolute;
- border-radius: 12px;
- top: -300px;
- left: -300px;
- opacity: 0.4;
- user-select: none;
-
- ${({ desaturate }) => desaturate && `filter: saturate(0)`}
-`
-
-export const CardNoise = styled.span`
- background: url(${noise});
- background-size: cover;
- mix-blend-mode: overlay;
- border-radius: 12px;
- width: 100%;
- height: 100%;
- opacity: 0.15;
- position: absolute;
- top: 0;
- left: 0;
- user-select: none;
-`
-
-export const CardSection = styled(AutoColumn)<{ disabled?: boolean }>`
- padding: 1rem;
- z-index: 1;
- opacity: ${({ disabled }) => disabled && '0.4'};
-`
-
-export const Break = styled.div`
- width: 100%;
- background-color: rgba(255, 255, 255, 0.2);
- height: 1px;
-`
diff --git a/src/components/swap/AdvancedSwapDetails.tsx b/src/components/swap/AdvancedSwapDetails.tsx
deleted file mode 100644
index be902ba..0000000
--- a/src/components/swap/AdvancedSwapDetails.tsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import { Trade, TradeType } from '@uniswap/sdk'
-import React, { useContext } from 'react'
-import styled, { ThemeContext } from 'styled-components'
-import { Field } from '../../state/swap/actions'
-import { useUserSlippageTolerance } from '../../state/user/hooks'
-import { TYPE, ExternalLink } from '../../theme'
-import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown } from '../../utils/prices'
-import { AutoColumn } from '../Column'
-import QuestionHelper from '../QuestionHelper'
-import { RowBetween, RowFixed } from '../Row'
-import FormattedPriceImpact from './FormattedPriceImpact'
-import SwapRoute from './SwapRoute'
-
-const InfoLink = styled(ExternalLink)`
- width: 100%;
- border: 1px solid ${({ theme }) => theme.bg3};
- padding: 6px 6px;
- border-radius: 8px;
- text-align: center;
- font-size: 14px;
- color: ${({ theme }) => theme.text1};
-`
-
-function TradeSummary({ trade, allowedSlippage }: { trade: Trade; allowedSlippage: number }) {
- const theme = useContext(ThemeContext)
- const { priceImpactWithoutFee, realizedLPFee } = computeTradePriceBreakdown(trade)
- const isExactIn = trade.tradeType === TradeType.EXACT_INPUT
- const slippageAdjustedAmounts = computeSlippageAdjustedAmounts(trade, allowedSlippage)
-
- return (
- <>
- <AutoColumn style={{ padding: '0 16px' }}>
- <RowBetween>
- <RowFixed>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- {isExactIn ? 'Minimum received' : 'Maximum sold'}
- </TYPE.black>
- <QuestionHelper text="Your transaction will revert if there is a large, unfavorable price movement before it is confirmed." />
- </RowFixed>
- <RowFixed>
- <TYPE.black color={theme.text1} fontSize={14}>
- {isExactIn
- ? `${slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4)} ${trade.outputAmount.currency.symbol}` ??
- '-'
- : `${slippageAdjustedAmounts[Field.INPUT]?.toSignificant(4)} ${trade.inputAmount.currency.symbol}` ??
- '-'}
- </TYPE.black>
- </RowFixed>
- </RowBetween>
- <RowBetween>
- <RowFixed>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- Price Impact
- </TYPE.black>
- <QuestionHelper text="The difference between the market price and estimated price due to trade size." />
- </RowFixed>
- <FormattedPriceImpact priceImpact={priceImpactWithoutFee} />
- </RowBetween>
-
- <RowBetween>
- <RowFixed>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- Liquidity Provider Fee
- </TYPE.black>
- <QuestionHelper text="A portion of each trade (0.30%) goes to liquidity providers as a protocol incentive." />
- </RowFixed>
- <TYPE.black fontSize={14} color={theme.text1}>
- {realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${trade.inputAmount.currency.symbol}` : '-'}
- </TYPE.black>
- </RowBetween>
- </AutoColumn>
- </>
- )
-}
-
-export interface AdvancedSwapDetailsProps {
- trade?: Trade
-}
-
-export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
- const theme = useContext(ThemeContext)
-
- const [allowedSlippage] = useUserSlippageTolerance()
-
- const showRoute = Boolean(trade && trade.route.path.length > 2)
-
- return (
- <AutoColumn gap="0px">
- {trade && (
- <>
- <TradeSummary trade={trade} allowedSlippage={allowedSlippage} />
- {showRoute && (
- <>
- <RowBetween style={{ padding: '0 16px' }}>
- <span style={{ display: 'flex', alignItems: 'center' }}>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- Route
- </TYPE.black>
- <QuestionHelper text="Routing through these tokens resulted in the best price for your trade." />
- </span>
- <SwapRoute trade={trade} />
- </RowBetween>
- </>
- )}
- {!showRoute && (
- <AutoColumn style={{ padding: '12px 16px 0 16px' }}>
- <InfoLink
- href={'https://uniswap.info/pair/' + trade.route.pairs[0].liquidityToken.address}
- target="_blank"
- >
- View pair analytics ↗
- </InfoLink>
- </AutoColumn>
- )}
- </>
- )}
- </AutoColumn>
- )
-}
diff --git a/src/components/swap/AdvancedSwapDetailsDropdown.tsx b/src/components/swap/AdvancedSwapDetailsDropdown.tsx
deleted file mode 100644
index 399996e..0000000
--- a/src/components/swap/AdvancedSwapDetailsDropdown.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-import { useLastTruthy } from '../../hooks/useLast'
-import { AdvancedSwapDetails, AdvancedSwapDetailsProps } from './AdvancedSwapDetails'
-
-const AdvancedDetailsFooter = styled.div<{ show: boolean }>`
- padding-top: calc(16px + 2rem);
- padding-bottom: 16px;
- margin-top: -2rem;
- width: 100%;
- max-width: 400px;
- border-bottom-left-radius: 20px;
- border-bottom-right-radius: 20px;
- color: ${({ theme }) => theme.text2};
- background-color: ${({ theme }) => theme.advancedBG};
- z-index: -1;
-
- transform: ${({ show }) => (show ? 'translateY(0%)' : 'translateY(-100%)')};
- transition: transform 300ms ease-in-out;
-`
-
-export default function AdvancedSwapDetailsDropdown({ trade, ...rest }: AdvancedSwapDetailsProps) {
- const lastTrade = useLastTruthy(trade)
-
- return (
- <AdvancedDetailsFooter show={Boolean(trade)}>
- <AdvancedSwapDetails {...rest} trade={trade ?? lastTrade ?? undefined} />
- </AdvancedDetailsFooter>
- )
-}
diff --git a/src/components/swap/BetterTradeLink.tsx b/src/components/swap/BetterTradeLink.tsx
deleted file mode 100644
index c084008..0000000
--- a/src/components/swap/BetterTradeLink.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import { stringify } from 'qs'
-import React, { useContext, useMemo } from 'react'
-import { useLocation } from 'react-router'
-import { Text } from 'rebass'
-import { ThemeContext } from 'styled-components'
-import useParsedQueryString from '../../hooks/useParsedQueryString'
-import useToggledVersion, { DEFAULT_VERSION, Version } from '../../hooks/useToggledVersion'
-
-import { StyledInternalLink } from '../../theme'
-import { YellowCard } from '../Card'
-import { AutoColumn } from '../Column'
-
-function VersionLinkContainer({ children }: { children: React.ReactNode }) {
- const theme = useContext(ThemeContext)
-
- return (
- <YellowCard style={{ marginTop: '12px', padding: '0.5rem 0.5rem' }}>
- <AutoColumn gap="sm" justify="center" style={{ alignItems: 'center', textAlign: 'center' }}>
- <Text lineHeight="145.23%;" fontSize={14} fontWeight={400} color={theme.text1}>
- {children}
- </Text>
- </AutoColumn>
- </YellowCard>
- )
-}
-
-export default function BetterTradeLink({ version }: { version: Version }) {
- const location = useLocation()
- const search = useParsedQueryString()
-
- const linkDestination = useMemo(() => {
- return {
- ...location,
- search: `?${stringify({
- ...search,
- use: version !== DEFAULT_VERSION ? version : undefined,
- })}`,
- }
- }, [location, search, version])
-
- return (
- <VersionLinkContainer>
- There is a better price for this trade on{' '}
- <StyledInternalLink to={linkDestination}>
- <b>Uniswap {version.toUpperCase()} ↗</b>
- </StyledInternalLink>
- </VersionLinkContainer>
- )
-}
-
-export function DefaultVersionLink() {
- const location = useLocation()
- const search = useParsedQueryString()
- const version = useToggledVersion()
-
- const linkDestination = useMemo(() => {
- return {
- ...location,
- search: `?${stringify({
- ...search,
- use: DEFAULT_VERSION,
- })}`,
- }
- }, [location, search])
-
- return (
- <VersionLinkContainer>
- Showing {version.toUpperCase()} price.{' '}
- <StyledInternalLink to={linkDestination}>
- <b>Switch to Uniswap {DEFAULT_VERSION.toUpperCase()} ↗</b>
- </StyledInternalLink>
- </VersionLinkContainer>
- )
-}
diff --git a/src/components/swap/ConfirmSwapModal.tsx b/src/components/swap/ConfirmSwapModal.tsx
deleted file mode 100644
index bc7ec1e..0000000
--- a/src/components/swap/ConfirmSwapModal.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import { currencyEquals, Trade } from '@uniswap/sdk'
-import React, { useCallback, useMemo } from 'react'
-import TransactionConfirmationModal, {
- ConfirmationModalContent,
- TransactionErrorContent,
-} from '../TransactionConfirmationModal'
-import SwapModalFooter from './SwapModalFooter'
-import SwapModalHeader from './SwapModalHeader'
-
-/**
- * Returns true if the trade requires a confirmation of details before we can submit it
- * @param tradeA trade A
- * @param tradeB trade B
- */
-function tradeMeaningfullyDiffers(tradeA: Trade, tradeB: Trade): boolean {
- return (
- tradeA.tradeType !== tradeB.tradeType ||
- !currencyEquals(tradeA.inputAmount.currency, tradeB.inputAmount.currency) ||
- !tradeA.inputAmount.equalTo(tradeB.inputAmount) ||
- !currencyEquals(tradeA.outputAmount.currency, tradeB.outputAmount.currency) ||
- !tradeA.outputAmount.equalTo(tradeB.outputAmount)
- )
-}
-
-export default function ConfirmSwapModal({
- trade,
- originalTrade,
- onAcceptChanges,
- allowedSlippage,
- onConfirm,
- onDismiss,
- recipient,
- swapErrorMessage,
- isOpen,
- attemptingTxn,
- txHash,
-}: {
- isOpen: boolean
- trade: Trade | undefined
- originalTrade: Trade | undefined
- attemptingTxn: boolean
- txHash: string | undefined
- recipient: string | null
- allowedSlippage: number
- onAcceptChanges: () => void
- onConfirm: () => void
- swapErrorMessage: string | undefined
- onDismiss: () => void
-}) {
- const showAcceptChanges = useMemo(
- () => Boolean(trade && originalTrade && tradeMeaningfullyDiffers(trade, originalTrade)),
- [originalTrade, trade]
- )
-
- const modalHeader = useCallback(() => {
- return trade ? (
- <SwapModalHeader
- trade={trade}
- allowedSlippage={allowedSlippage}
- recipient={recipient}
- showAcceptChanges={showAcceptChanges}
- onAcceptChanges={onAcceptChanges}
- />
- ) : null
- }, [allowedSlippage, onAcceptChanges, recipient, showAcceptChanges, trade])
-
- const modalBottom = useCallback(() => {
- return trade ? (
- <SwapModalFooter
- onConfirm={onConfirm}
- trade={trade}
- disabledConfirm={showAcceptChanges}
- swapErrorMessage={swapErrorMessage}
- allowedSlippage={allowedSlippage}
- />
- ) : null
- }, [allowedSlippage, onConfirm, showAcceptChanges, swapErrorMessage, trade])
-
- // text to show while loading
- const pendingText = `Swapping ${trade?.inputAmount?.toSignificant(6)} ${
- trade?.inputAmount?.currency?.symbol
- } for ${trade?.outputAmount?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
-
- const confirmationContent = useCallback(
- () =>
- swapErrorMessage ? (
- <TransactionErrorContent onDismiss={onDismiss} message={swapErrorMessage} />
- ) : (
- <ConfirmationModalContent
- title="Confirm Swap"
- onDismiss={onDismiss}
- topContent={modalHeader}
- bottomContent={modalBottom}
- />
- ),
- [onDismiss, modalBottom, modalHeader, swapErrorMessage]
- )
-
- return (
- <TransactionConfirmationModal
- isOpen={isOpen}
- onDismiss={onDismiss}
- attemptingTxn={attemptingTxn}
- hash={txHash}
- content={confirmationContent}
- pendingText={pendingText}
- currencyToAdd={trade?.outputAmount.currency}
- />
- )
-}
diff --git a/src/components/swap/FormattedPriceImpact.tsx b/src/components/swap/FormattedPriceImpact.tsx
deleted file mode 100644
index c67727e..0000000
--- a/src/components/swap/FormattedPriceImpact.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Percent } from '@uniswap/sdk'
-import React from 'react'
-import { ONE_BIPS } from '../../constants'
-import { warningSeverity } from '../../utils/prices'
-import { ErrorText } from './styleds'
-
-/**
- * Formatted version of price impact text with warning colors
- */
-export default function FormattedPriceImpact({ priceImpact }: { priceImpact?: Percent }) {
- return (
- <ErrorText fontWeight={500} fontSize={14} severity={warningSeverity(priceImpact)}>
- {priceImpact ? (priceImpact.lessThan(ONE_BIPS) ? '<0.01%' : `${priceImpact.toFixed(2)}%`) : '-'}
- </ErrorText>
- )
-}
diff --git a/src/components/swap/SwapHeader.tsx b/src/components/swap/SwapHeader.tsx
deleted file mode 100644
index a612304..0000000
--- a/src/components/swap/SwapHeader.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-import Settings from '../Settings'
-import { RowBetween } from '../Row'
-import { TYPE } from '../../theme'
-
-const StyledSwapHeader = styled.div`
- padding: 12px 1rem 0px 1.5rem;
- margin-bottom: -4px;
- width: 100%;
- max-width: 420px;
- color: ${({ theme }) => theme.text2};
-`
-
-export default function SwapHeader() {
- return (
- <StyledSwapHeader>
- <RowBetween>
- <TYPE.black fontWeight={500}>Swap</TYPE.black>
- <Settings />
- </RowBetween>
- </StyledSwapHeader>
- )
-}
diff --git a/src/components/swap/SwapModalFooter.tsx b/src/components/swap/SwapModalFooter.tsx
deleted file mode 100644
index 9604de9..0000000
--- a/src/components/swap/SwapModalFooter.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Trade, TradeType } from '@uniswap/sdk'
-import React, { useContext, useMemo, useState } from 'react'
-import { Repeat } from 'react-feather'
-import { Text } from 'rebass'
-import { ThemeContext } from 'styled-components'
-import { Field } from '../../state/swap/actions'
-import { TYPE } from '../../theme'
-import {
- computeSlippageAdjustedAmounts,
- computeTradePriceBreakdown,
- formatExecutionPrice,
- warningSeverity,
-} from '../../utils/prices'
-import { ButtonError } from '../Button'
-import { AutoColumn } from '../Column'
-import QuestionHelper from '../QuestionHelper'
-import { AutoRow, RowBetween, RowFixed } from '../Row'
-import FormattedPriceImpact from './FormattedPriceImpact'
-import { StyledBalanceMaxMini, SwapCallbackError } from './styleds'
-
-export default function SwapModalFooter({
- trade,
- onConfirm,
- allowedSlippage,
- swapErrorMessage,
- disabledConfirm,
-}: {
- trade: Trade
- allowedSlippage: number
- onConfirm: () => void
- swapErrorMessage: string | undefined
- disabledConfirm: boolean
-}) {
- const [showInverted, setShowInverted] = useState<boolean>(false)
- const theme = useContext(ThemeContext)
- const slippageAdjustedAmounts = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage), [
- allowedSlippage,
- trade,
- ])
- const { priceImpactWithoutFee, realizedLPFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
- const severity = warningSeverity(priceImpactWithoutFee)
-
- return (
- <>
- <AutoColumn gap="0px">
- <RowBetween align="center">
- <Text fontWeight={400} fontSize={14} color={theme.text2}>
- Price
- </Text>
- <Text
- fontWeight={500}
- fontSize={14}
- color={theme.text1}
- style={{
- justifyContent: 'center',
- alignItems: 'center',
- display: 'flex',
- textAlign: 'right',
- paddingLeft: '10px',
- }}
- >
- {formatExecutionPrice(trade, showInverted)}
- <StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}>
- <Repeat size={14} />
- </StyledBalanceMaxMini>
- </Text>
- </RowBetween>
-
- <RowBetween>
- <RowFixed>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- {trade.tradeType === TradeType.EXACT_INPUT ? 'Minimum received' : 'Maximum sold'}
- </TYPE.black>
- <QuestionHelper text="Your transaction will revert if there is a large, unfavorable price movement before it is confirmed." />
- </RowFixed>
- <RowFixed>
- <TYPE.black fontSize={14}>
- {trade.tradeType === TradeType.EXACT_INPUT
- ? slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4) ?? '-'
- : slippageAdjustedAmounts[Field.INPUT]?.toSignificant(4) ?? '-'}
- </TYPE.black>
- <TYPE.black fontSize={14} marginLeft={'4px'}>
- {trade.tradeType === TradeType.EXACT_INPUT
- ? trade.outputAmount.currency.symbol
- : trade.inputAmount.currency.symbol}
- </TYPE.black>
- </RowFixed>
- </RowBetween>
- <RowBetween>
- <RowFixed>
- <TYPE.black color={theme.text2} fontSize={14} fontWeight={400}>
- Price Impact
- </TYPE.black>
- <QuestionHelper text="The difference between the market price and your price due to trade size." />
- </RowFixed>
- <FormattedPriceImpact priceImpact={priceImpactWithoutFee} />
- </RowBetween>
- <RowBetween>
- <RowFixed>
- <TYPE.black fontSize={14} fontWeight={400} color={theme.text2}>
- Liquidity Provider Fee
- </TYPE.black>
- <QuestionHelper text="A portion of each trade (0.30%) goes to liquidity providers as a protocol incentive." />
- </RowFixed>
- <TYPE.black fontSize={14}>
- {realizedLPFee ? realizedLPFee?.toSignificant(6) + ' ' + trade.inputAmount.currency.symbol : '-'}
- </TYPE.black>
- </RowBetween>
- </AutoColumn>
-
- <AutoRow>
- <ButtonError
- onClick={onConfirm}
- disabled={disabledConfirm}
- error={severity > 2}
- style={{ margin: '10px 0 0 0' }}
- id="confirm-swap-or-send"
- >
- <Text fontSize={20} fontWeight={500}>
- {severity > 2 ? 'Swap Anyway' : 'Confirm Swap'}
- </Text>
- </ButtonError>
-
- {swapErrorMessage ? <SwapCallbackError error={swapErrorMessage} /> : null}
- </AutoRow>
- </>
- )
-}
diff --git a/src/components/swap/SwapModalHeader.tsx b/src/components/swap/SwapModalHeader.tsx
deleted file mode 100644
index 0a1c94c..0000000
--- a/src/components/swap/SwapModalHeader.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Trade, TradeType } from '@uniswap/sdk'
-import React, { useContext, useMemo } from 'react'
-import { ArrowDown, AlertTriangle } from 'react-feather'
-import { Text } from 'rebass'
-import { ThemeContext } from 'styled-components'
-import { Field } from '../../state/swap/actions'
-import { TYPE } from '../../theme'
-import { ButtonPrimary } from '../Button'
-import { isAddress, shortenAddress } from '../../utils'
-import { computeSlippageAdjustedAmounts, computeTradePriceBreakdown, warningSeverity } from '../../utils/prices'
-import { AutoColumn } from '../Column'
-import CurrencyLogo from '../CurrencyLogo'
-import { RowBetween, RowFixed } from '../Row'
-import { TruncatedText, SwapShowAcceptChanges } from './styleds'
-
-export default function SwapModalHeader({
- trade,
- allowedSlippage,
- recipient,
- showAcceptChanges,
- onAcceptChanges,
-}: {
- trade: Trade
- allowedSlippage: number
- recipient: string | null
- showAcceptChanges: boolean
- onAcceptChanges: () => void
-}) {
- const slippageAdjustedAmounts = useMemo(() => computeSlippageAdjustedAmounts(trade, allowedSlippage), [
- trade,
- allowedSlippage,
- ])
- const { priceImpactWithoutFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
- const priceImpactSeverity = warningSeverity(priceImpactWithoutFee)
-
- const theme = useContext(ThemeContext)
-
- return (
- <AutoColumn gap={'md'} style={{ marginTop: '20px' }}>
- <RowBetween align="flex-end">
- <RowFixed gap={'0px'}>
- <CurrencyLogo currency={trade.inputAmount.currency} size={'24px'} style={{ marginRight: '12px' }} />
- <TruncatedText
- fontSize={24}
- fontWeight={500}
- color={showAcceptChanges && trade.tradeType === TradeType.EXACT_OUTPUT ? theme.primary1 : ''}
- >
- {trade.inputAmount.toSignificant(6)}
- </TruncatedText>
- </RowFixed>
- <RowFixed gap={'0px'}>
- <Text fontSize={24} fontWeight={500} style={{ marginLeft: '10px' }}>
- {trade.inputAmount.currency.symbol}
- </Text>
- </RowFixed>
- </RowBetween>
- <RowFixed>
- <ArrowDown size="16" color={theme.text2} style={{ marginLeft: '4px', minWidth: '16px' }} />
- </RowFixed>
- <RowBetween align="flex-end">
- <RowFixed gap={'0px'}>
- <CurrencyLogo currency={trade.outputAmount.currency} size={'24px'} style={{ marginRight: '12px' }} />
- <TruncatedText
- fontSize={24}
- fontWeight={500}
- color={
- priceImpactSeverity > 2
- ? theme.red1
- : showAcceptChanges && trade.tradeType === TradeType.EXACT_INPUT
- ? theme.primary1
- : ''
- }
- >
- {trade.outputAmount.toSignificant(6)}
- </TruncatedText>
- </RowFixed>
- <RowFixed gap={'0px'}>
- <Text fontSize={24} fontWeight={500} style={{ marginLeft: '10px' }}>
- {trade.outputAmount.currency.symbol}
- </Text>
- </RowFixed>
- </RowBetween>
- {showAcceptChanges ? (
- <SwapShowAcceptChanges justify="flex-start" gap={'0px'}>
- <RowBetween>
- <RowFixed>
- <AlertTriangle size={20} style={{ marginRight: '8px', minWidth: 24 }} />
- <TYPE.main color={theme.primary1}> Price Updated</TYPE.main>
- </RowFixed>
- <ButtonPrimary
- style={{ padding: '.5rem', width: 'fit-content', fontSize: '0.825rem', borderRadius: '12px' }}
- onClick={onAcceptChanges}
- >
- Accept
- </ButtonPrimary>
- </RowBetween>
- </SwapShowAcceptChanges>
- ) : null}
- <AutoColumn justify="flex-start" gap="sm" style={{ padding: '12px 0 0 0px' }}>
- {trade.tradeType === TradeType.EXACT_INPUT ? (
- <TYPE.italic textAlign="left" style={{ width: '100%' }}>
- {`Output is estimated. You will receive at least `}
- <b>
- {slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(6)} {trade.outputAmount.currency.symbol}
- </b>
- {' or the transaction will revert.'}
- </TYPE.italic>
- ) : (
- <TYPE.italic textAlign="left" style={{ width: '100%' }}>
- {`Input is estimated. You will sell at most `}
- <b>
- {slippageAdjustedAmounts[Field.INPUT]?.toSignificant(6)} {trade.inputAmount.currency.symbol}
- </b>
- {' or the transaction will revert.'}
- </TYPE.italic>
- )}
- </AutoColumn>
- {recipient !== null ? (
- <AutoColumn justify="flex-start" gap="sm" style={{ padding: '12px 0 0 0px' }}>
- <TYPE.main>
- Output will be sent to{' '}
- <b title={recipient}>{isAddress(recipient) ? shortenAddress(recipient) : recipient}</b>
- </TYPE.main>
- </AutoColumn>
- ) : null}
- </AutoColumn>
- )
-}
diff --git a/src/components/swap/SwapRoute.tsx b/src/components/swap/SwapRoute.tsx
deleted file mode 100644
index be35362..0000000
--- a/src/components/swap/SwapRoute.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Trade } from '@uniswap/sdk'
-import React, { Fragment, memo, useContext } from 'react'
-import { ChevronRight } from 'react-feather'
-import { Flex } from 'rebass'
-import { ThemeContext } from 'styled-components'
-import { TYPE } from '../../theme'
-import { unwrappedToken } from 'utils/wrappedCurrency'
-
-export default memo(function SwapRoute({ trade }: { trade: Trade }) {
- const theme = useContext(ThemeContext)
- return (
- <Flex flexWrap="wrap" width="100%" justifyContent="flex-end" alignItems="center">
- {trade.route.path.map((token, i, path) => {
- const isLastItem: boolean = i === path.length - 1
- const currency = unwrappedToken(token)
- return (
- <Fragment key={i}>
- <Flex alignItems="end">
- <TYPE.black fontSize={14} color={theme.text1} ml="0.125rem" mr="0.125rem">
- {currency.symbol}
- </TYPE.black>
- </Flex>
- {isLastItem ? null : <ChevronRight size={12} color={theme.text2} />}
- </Fragment>
- )
- })}
- </Flex>
- )
-})
diff --git a/src/components/swap/TradePrice.tsx b/src/components/swap/TradePrice.tsx
deleted file mode 100644
index 32efebf..0000000
--- a/src/components/swap/TradePrice.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import React from 'react'
-import { Price } from '@uniswap/sdk'
-import { useContext } from 'react'
-import { Repeat } from 'react-feather'
-import { Text } from 'rebass'
-import { ThemeContext } from 'styled-components'
-import { StyledBalanceMaxMini } from './styleds'
-
-interface TradePriceProps {
- price?: Price
- showInverted: boolean
- setShowInverted: (showInverted: boolean) => void
-}
-
-export default function TradePrice({ price, showInverted, setShowInverted }: TradePriceProps) {
- const theme = useContext(ThemeContext)
-
- const formattedPrice = showInverted ? price?.toSignificant(6) : price?.invert()?.toSignificant(6)
-
- const show = Boolean(price?.baseCurrency && price?.quoteCurrency)
- const label = showInverted
- ? `${price?.quoteCurrency?.symbol} per ${price?.baseCurrency?.symbol}`
- : `${price?.baseCurrency?.symbol} per ${price?.quoteCurrency?.symbol}`
-
- return (
- <Text
- fontWeight={500}
- fontSize={14}
- color={theme.text2}
- style={{ justifyContent: 'center', alignItems: 'center', display: 'flex' }}
- >
- {show ? (
- <>
- {formattedPrice ?? '-'} {label}
- <StyledBalanceMaxMini onClick={() => setShowInverted(!showInverted)}>
- <Repeat size={14} />
- </StyledBalanceMaxMini>
- </>
- ) : (
- '-'
- )}
- </Text>
- )
-}
diff --git a/src/components/swap/UnsupportedCurrencyFooter.tsx b/src/components/swap/UnsupportedCurrencyFooter.tsx
deleted file mode 100644
index b270a99..0000000
--- a/src/components/swap/UnsupportedCurrencyFooter.tsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import React, { useState } from 'react'
-import styled from 'styled-components'
-import { TYPE, CloseIcon, ExternalLink } from 'theme'
-import { ButtonEmpty } from 'components/Button'
-import Modal from 'components/Modal'
-import Card, { OutlineCard } from 'components/Card'
-import { RowBetween, AutoRow } from 'components/Row'
-import { AutoColumn } from 'components/Column'
-import CurrencyLogo from 'components/CurrencyLogo'
-import { useActiveWeb3React } from 'hooks'
-import { getEtherscanLink } from 'utils'
-import { Currency, Token } from '@uniswap/sdk'
-import { wrappedCurrency } from 'utils/wrappedCurrency'
-import { useUnsupportedTokens } from '../../hooks/Tokens'
-
-const DetailsFooter = styled.div<{ show: boolean }>`
- padding-top: calc(16px + 2rem);
- padding-bottom: 20px;
- margin-top: -2rem;
- width: 100%;
- max-width: 400px;
- border-bottom-left-radius: 20px;
- border-bottom-right-radius: 20px;
- color: ${({ theme }) => theme.text2};
- background-color: ${({ theme }) => theme.advancedBG};
- z-index: -1;
-
- transform: ${({ show }) => (show ? 'translateY(0%)' : 'translateY(-100%)')};
- transition: transform 300ms ease-in-out;
- text-align: center;
-`
-
-const AddressText = styled(TYPE.blue)`
- font-size: 12px;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- font-size: 10px;
-`}
-`
-
-export default function UnsupportedCurrencyFooter({
- show,
- currencies,
-}: {
- show: boolean
- currencies: (Currency | undefined)[]
-}) {
- const { chainId } = useActiveWeb3React()
- const [showDetails, setShowDetails] = useState(false)
-
- const tokens =
- chainId && currencies
- ? currencies.map((currency) => {
- return wrappedCurrency(currency, chainId)
- })
- : []
-
- const unsupportedTokens: { [address: string]: Token } = useUnsupportedTokens()
-
- return (
- <DetailsFooter show={show}>
- <Modal isOpen={showDetails} onDismiss={() => setShowDetails(false)}>
- <Card padding="2rem">
- <AutoColumn gap="lg">
- <RowBetween>
- <TYPE.mediumHeader>Unsupported Assets</TYPE.mediumHeader>
-
- <CloseIcon onClick={() => setShowDetails(false)} />
- </RowBetween>
- {tokens.map((token) => {
- return (
- token &&
- unsupportedTokens &&
- Object.keys(unsupportedTokens).includes(token.address) && (
- <OutlineCard key={token.address?.concat('not-supported')}>
- <AutoColumn gap="10px">
- <AutoRow gap="5px" align="center">
- <CurrencyLogo currency={token} size={'24px'} />
- <TYPE.body fontWeight={500}>{token.symbol}</TYPE.body>
- </AutoRow>
- {chainId && (
- <ExternalLink href={getEtherscanLink(chainId, token.address, 'address')}>
- <AddressText>{token.address}</AddressText>
- </ExternalLink>
- )}
- </AutoColumn>
- </OutlineCard>
- )
- )
- })}
- <AutoColumn gap="lg">
- <TYPE.body fontWeight={500}>
- Some assets are not available through this interface because they may not work well with our smart
- contract or we are unable to allow trading for legal reasons.
- </TYPE.body>
- </AutoColumn>
- </AutoColumn>
- </Card>
- </Modal>
- <ButtonEmpty padding={'0'} onClick={() => setShowDetails(true)}>
- <TYPE.blue>Read more about unsupported assets</TYPE.blue>
- </ButtonEmpty>
- </DetailsFooter>
- )
-}
diff --git a/src/components/swap/confirmPriceImpactWithoutFee.ts b/src/components/swap/confirmPriceImpactWithoutFee.ts
deleted file mode 100644
index 1b955c3..0000000
--- a/src/components/swap/confirmPriceImpactWithoutFee.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { Percent } from '@uniswap/sdk'
-import { ALLOWED_PRICE_IMPACT_HIGH, PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN } from '../../constants'
-
-/**
- * Given the price impact, get user confirmation.
- *
- * @param priceImpactWithoutFee price impact of the trade without the fee.
- */
-export default function confirmPriceImpactWithoutFee(priceImpactWithoutFee: Percent): boolean {
- if (!priceImpactWithoutFee.lessThan(PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN)) {
- return (
- window.prompt(
- `This swap has a price impact of at least ${PRICE_IMPACT_WITHOUT_FEE_CONFIRM_MIN.toFixed(
- 0
- )}%. Please type the word "confirm" to continue with this swap.`
- ) === 'confirm'
- )
- } else if (!priceImpactWithoutFee.lessThan(ALLOWED_PRICE_IMPACT_HIGH)) {
- return window.confirm(
- `This swap has a price impact of at least ${ALLOWED_PRICE_IMPACT_HIGH.toFixed(
- 0
- )}%. Please confirm that you would like to continue with this swap.`
- )
- }
- return true
-}
diff --git a/src/components/swap/styleds.tsx b/src/components/swap/styleds.tsx
deleted file mode 100644
index 8c1452f..0000000
--- a/src/components/swap/styleds.tsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import { transparentize } from 'polished'
-import React from 'react'
-import { AlertTriangle } from 'react-feather'
-import styled, { css } from 'styled-components'
-import { Text } from 'rebass'
-import { AutoColumn } from '../Column'
-
-export const Wrapper = styled.div`
- position: relative;
- padding: 1rem;
-`
-
-export const ArrowWrapper = styled.div<{ clickable: boolean }>`
- padding: 2px;
-
- ${({ clickable }) =>
- clickable
- ? css`
- :hover {
- cursor: pointer;
- opacity: 0.8;
- }
- `
- : null}
-`
-
-export const SectionBreak = styled.div`
- height: 1px;
- width: 100%;
- background-color: ${({ theme }) => theme.bg3};
-`
-
-export const BottomGrouping = styled.div`
- margin-top: 1rem;
-`
-
-export const ErrorText = styled(Text)<{ severity?: 0 | 1 | 2 | 3 | 4 }>`
- color: ${({ theme, severity }) =>
- severity === 3 || severity === 4
- ? theme.red1
- : severity === 2
- ? theme.yellow2
- : severity === 1
- ? theme.text1
- : theme.green1};
-`
-
-export const StyledBalanceMaxMini = styled.button`
- height: 22px;
- width: 22px;
- background-color: ${({ theme }) => theme.bg2};
- border: none;
- border-radius: 50%;
- padding: 0.2rem;
- font-size: 0.875rem;
- font-weight: 400;
- margin-left: 0.4rem;
- cursor: pointer;
- color: ${({ theme }) => theme.text2};
- display: flex;
- justify-content: center;
- align-items: center;
- float: right;
-
- :hover {
- background-color: ${({ theme }) => theme.bg3};
- }
- :focus {
- background-color: ${({ theme }) => theme.bg3};
- outline: none;
- }
-`
-
-export const TruncatedText = styled(Text)`
- text-overflow: ellipsis;
- width: 220px;
- overflow: hidden;
-`
-
-// styles
-export const Dots = styled.span`
- &::after {
- display: inline-block;
- animation: ellipsis 1.25s infinite;
- content: '.';
- width: 1em;
- text-align: left;
- }
- @keyframes ellipsis {
- 0% {
- content: '.';
- }
- 33% {
- content: '..';
- }
- 66% {
- content: '...';
- }
- }
-`
-
-const SwapCallbackErrorInner = styled.div`
- background-color: ${({ theme }) => transparentize(0.9, theme.red1)};
- border-radius: 1rem;
- display: flex;
- align-items: center;
- font-size: 0.825rem;
- width: 100%;
- padding: 3rem 1.25rem 1rem 1rem;
- margin-top: -2rem;
- color: ${({ theme }) => theme.red1};
- z-index: -1;
- p {
- padding: 0;
- margin: 0;
- font-weight: 500;
- }
-`
-
-const SwapCallbackErrorInnerAlertTriangle = styled.div`
- background-color: ${({ theme }) => transparentize(0.9, theme.red1)};
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: 12px;
- border-radius: 12px;
- min-width: 48px;
- height: 48px;
-`
-
-export function SwapCallbackError({ error }: { error: string }) {
- return (
- <SwapCallbackErrorInner>
- <SwapCallbackErrorInnerAlertTriangle>
- <AlertTriangle size={24} />
- </SwapCallbackErrorInnerAlertTriangle>
- <p>{error}</p>
- </SwapCallbackErrorInner>
- )
-}
-
-export const SwapShowAcceptChanges = styled(AutoColumn)`
- background-color: ${({ theme }) => transparentize(0.9, theme.primary1)};
- color: ${({ theme }) => theme.primary1};
- padding: 0.5rem;
- border-radius: 12px;
- margin-top: 8px;
-`
-export const Separator = styled.div`
- width: 100%;
- height: 1px;
- background-color: ${({ theme }) => theme.bg2};
-`
diff --git a/src/components/vote/DelegateModal.tsx b/src/components/vote/DelegateModal.tsx
deleted file mode 100644
index d867ec4..0000000
--- a/src/components/vote/DelegateModal.tsx
+++ /dev/null
@@ -1,133 +0,0 @@
-import React, { useState } from 'react'
-
-import Modal from '../Modal'
-import { AutoColumn } from '../Column'
-import styled from 'styled-components'
-import { RowBetween } from '../Row'
-import { TYPE } from '../../theme'
-import { X } from 'react-feather'
-import { ButtonPrimary } from '../Button'
-import { useActiveWeb3React } from '../../hooks'
-import AddressInputPanel from '../AddressInputPanel'
-import { isAddress } from 'ethers/lib/utils'
-import useENS from '../../hooks/useENS'
-import { useDelegateCallback } from '../../state/governance/hooks'
-import { useTokenBalance } from '../../state/wallet/hooks'
-import { UNI } from '../../constants'
-import { LoadingView, SubmittedView } from '../ModalViews'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
- padding: 24px;
-`
-
-const StyledClosed = styled(X)`
- :hover {
- cursor: pointer;
- }
-`
-
-const TextButton = styled.div`
- :hover {
- cursor: pointer;
- }
-`
-
-interface VoteModalProps {
- isOpen: boolean
- onDismiss: () => void
- title: string
-}
-
-export default function DelegateModal({ isOpen, onDismiss, title }: VoteModalProps) {
- const { account, chainId } = useActiveWeb3React()
-
- // state for delegate input
- const [usingDelegate, setUsingDelegate] = useState(false)
- const [typed, setTyped] = useState('')
- function handleRecipientType(val: string) {
- setTyped(val)
- }
-
- // monitor for self delegation or input for third part delegate
- // default is self delegation
- const activeDelegate = usingDelegate ? typed : account
- const { address: parsedAddress } = useENS(activeDelegate)
-
- // get the number of votes available to delegate
- const uniBalance = useTokenBalance(account ?? undefined, chainId ? UNI[chainId] : undefined)
-
- const delegateCallback = useDelegateCallback()
-
- // monitor call to help UI loading state
- const [hash, setHash] = useState<string | undefined>()
- const [attempting, setAttempting] = useState(false)
-
- // wrapper to reset state on modal close
- function wrappedOndismiss() {
- setHash(undefined)
- setAttempting(false)
- onDismiss()
- }
-
- async function onDelegate() {
- setAttempting(true)
-
- // if callback not returned properly ignore
- if (!delegateCallback) return
-
- // try delegation and store hash
- const hash = await delegateCallback(parsedAddress ?? undefined)?.catch((error) => {
- setAttempting(false)
- console.log(error)
- })
-
- if (hash) {
- setHash(hash)
- }
- }
-
- return (
- <Modal isOpen={isOpen} onDismiss={wrappedOndismiss} maxHeight={90}>
- {!attempting && !hash && (
- <ContentWrapper gap="lg">
- <AutoColumn gap="lg" justify="center">
- <RowBetween>
- <TYPE.mediumHeader fontWeight={500}>{title}</TYPE.mediumHeader>
- <StyledClosed stroke="black" onClick={wrappedOndismiss} />
- </RowBetween>
- <TYPE.body>Earned UNI tokens represent voting shares in Uniswap governance.</TYPE.body>
- <TYPE.body>
- You can either vote on each proposal yourself or delegate your votes to a third party.
- </TYPE.body>
- {usingDelegate && <AddressInputPanel value={typed} onChange={handleRecipientType} />}
- <ButtonPrimary disabled={!isAddress(parsedAddress ?? '')} onClick={onDelegate}>
- <TYPE.mediumHeader color="white">{usingDelegate ? 'Delegate Votes' : 'Self Delegate'}</TYPE.mediumHeader>
- </ButtonPrimary>
- <TextButton onClick={() => setUsingDelegate(!usingDelegate)}>
- <TYPE.blue>
- {usingDelegate ? 'Remove' : 'Add'} Delegate {!usingDelegate && '+'}
- </TYPE.blue>
- </TextButton>
- </AutoColumn>
- </ContentWrapper>
- )}
- {attempting && !hash && (
- <LoadingView onDismiss={wrappedOndismiss}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>{usingDelegate ? 'Delegating votes' : 'Unlocking Votes'}</TYPE.largeHeader>
- <TYPE.main fontSize={36}>{uniBalance?.toSignificant(4)}</TYPE.main>
- </AutoColumn>
- </LoadingView>
- )}
- {hash && (
- <SubmittedView onDismiss={wrappedOndismiss} hash={hash}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
- <TYPE.main fontSize={36}>{uniBalance?.toSignificant(4)}</TYPE.main>
- </AutoColumn>
- </SubmittedView>
- )}
- </Modal>
- )
-}
diff --git a/src/components/vote/VoteModal.tsx b/src/components/vote/VoteModal.tsx
deleted file mode 100644
index 5390f87..0000000
--- a/src/components/vote/VoteModal.tsx
+++ /dev/null
@@ -1,144 +0,0 @@
-import React, { useState, useContext } from 'react'
-import { useActiveWeb3React } from '../../hooks'
-
-import Modal from '../Modal'
-import { AutoColumn, ColumnCenter } from '../Column'
-import styled, { ThemeContext } from 'styled-components'
-import { RowBetween } from '../Row'
-import { TYPE, CustomLightSpinner } from '../../theme'
-import { X, ArrowUpCircle } from 'react-feather'
-import { ButtonPrimary } from '../Button'
-import Circle from '../../assets/images/blue-loader.svg'
-import { useVoteCallback, useUserVotes } from '../../state/governance/hooks'
-import { getEtherscanLink } from '../../utils'
-import { ExternalLink } from '../../theme/components'
-import { TokenAmount } from '@uniswap/sdk'
-
-const ContentWrapper = styled(AutoColumn)`
- width: 100%;
- padding: 24px;
-`
-
-const StyledClosed = styled(X)`
- :hover {
- cursor: pointer;
- }
-`
-
-const ConfirmOrLoadingWrapper = styled.div`
- width: 100%;
- padding: 24px;
-`
-
-const ConfirmedIcon = styled(ColumnCenter)`
- padding: 60px 0;
-`
-
-interface VoteModalProps {
- isOpen: boolean
- onDismiss: () => void
- support: boolean // if user is for or against proposal
- proposalId: string | undefined // id for the proposal to vote on
-}
-
-export default function VoteModal({ isOpen, onDismiss, proposalId, support }: VoteModalProps) {
- const { chainId } = useActiveWeb3React()
- const {
- voteCallback,
- }: {
- voteCallback: (proposalId: string | undefined, support: boolean) => Promise<string> | undefined
- } = useVoteCallback()
- const availableVotes: TokenAmount | undefined = useUserVotes()
-
- // monitor call to help UI loading state
- const [hash, setHash] = useState<string | undefined>()
- const [attempting, setAttempting] = useState<boolean>(false)
-
- // get theme for colors
- const theme = useContext(ThemeContext)
-
- // wrapper to reset state on modal close
- function wrappedOndismiss() {
- setHash(undefined)
- setAttempting(false)
- onDismiss()
- }
-
- async function onVote() {
- setAttempting(true)
-
- // if callback not returned properly ignore
- if (!voteCallback) return
-
- // try delegation and store hash
- const hash = await voteCallback(proposalId, support)?.catch((error) => {
- setAttempting(false)
- console.log(error)
- })
-
- if (hash) {
- setHash(hash)
- }
- }
-
- return (
- <Modal isOpen={isOpen} onDismiss={wrappedOndismiss} maxHeight={90}>
- {!attempting && !hash && (
- <ContentWrapper gap="lg">
- <AutoColumn gap="lg" justify="center">
- <RowBetween>
- <TYPE.mediumHeader fontWeight={500}>{`Vote ${
- support ? 'for ' : 'against'
- } proposal ${proposalId}`}</TYPE.mediumHeader>
- <StyledClosed stroke="black" onClick={wrappedOndismiss} />
- </RowBetween>
- <TYPE.largeHeader>{availableVotes?.toSignificant(4)} Votes</TYPE.largeHeader>
- <ButtonPrimary onClick={onVote}>
- <TYPE.mediumHeader color="white">{`Vote ${
- support ? 'for ' : 'against'
- } proposal ${proposalId}`}</TYPE.mediumHeader>
- </ButtonPrimary>
- </AutoColumn>
- </ContentWrapper>
- )}
- {attempting && !hash && (
- <ConfirmOrLoadingWrapper>
- <RowBetween>
- <div />
- <StyledClosed onClick={wrappedOndismiss} />
- </RowBetween>
- <ConfirmedIcon>
- <CustomLightSpinner src={Circle} alt="loader" size={'90px'} />
- </ConfirmedIcon>
- <AutoColumn gap="100px" justify={'center'}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Submitting Vote</TYPE.largeHeader>
- </AutoColumn>
- <TYPE.subHeader>Confirm this transaction in your wallet</TYPE.subHeader>
- </AutoColumn>
- </ConfirmOrLoadingWrapper>
- )}
- {hash && (
- <ConfirmOrLoadingWrapper>
- <RowBetween>
- <div />
- <StyledClosed onClick={wrappedOndismiss} />
- </RowBetween>
- <ConfirmedIcon>
- <ArrowUpCircle strokeWidth={0.5} size={90} color={theme.primary1} />
- </ConfirmedIcon>
- <AutoColumn gap="100px" justify={'center'}>
- <AutoColumn gap="12px" justify={'center'}>
- <TYPE.largeHeader>Transaction Submitted</TYPE.largeHeader>
- </AutoColumn>
- {chainId && (
- <ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')} style={{ marginLeft: '4px' }}>
- <TYPE.subHeader>View transaction on Etherscan</TYPE.subHeader>
- </ExternalLink>
- )}
- </AutoColumn>
- </ConfirmOrLoadingWrapper>
- )}
- </Modal>
- )
-}
diff --git a/src/constants/index.ts b/src/constants/index.ts
index e11a228..0f9cf11 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -7,8 +7,6 @@ export const ROUTER_ADDRESS = '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D'
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
-export { PRELOADED_PROPOSALS } from './proposals'
-
// a list of tokens by chain
type ChainTokenList = {
readonly [chainId in ChainId]: Token[]
@@ -75,12 +73,6 @@ export const CUSTOM_BASES: { [chainId in ChainId]?: { [tokenAddress: string]: To
},
}
-// used for display in the default list when adding liquidity
-export const SUGGESTED_BASES: ChainTokenList = {
- ...WETH_ONLY,
- [ChainId.MAINNET]: [...WETH_ONLY[ChainId.MAINNET], DAI, USDC, USDT, WBTC],
-}
-
// used to construct the list of all pairs we consider by default in the frontend
export const BASES_TO_TRACK_LIQUIDITY_FOR: ChainTokenList = {
...WETH_ONLY,
@@ -176,11 +168,6 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
export const NetworkContextName = 'NETWORK'
-// default allowed slippage, in bips
-export const INITIAL_ALLOWED_SLIPPAGE = 50
-// 20 minutes, denominated in seconds
-export const DEFAULT_DEADLINE_FROM_NOW = 60 * 20
-
// used for rewards deadlines
export const BIG_INT_SECONDS_IN_WEEK = JSBI.BigInt(60 * 60 * 24 * 7)
diff --git a/src/constants/proposals/index.ts b/src/constants/proposals/index.ts
deleted file mode 100644
index 0eae736..0000000
--- a/src/constants/proposals/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { UNISWAP_GRANTS } from './uniswap_grants'
-
-// Proposals are 0-indexed
-export const PRELOADED_PROPOSALS = new Map([[2, UNISWAP_GRANTS]])
diff --git a/src/constants/proposals/uniswap_grants.ts b/src/constants/proposals/uniswap_grants.ts
deleted file mode 100644
index 496fe98..0000000
--- a/src/constants/proposals/uniswap_grants.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-export const UNISWAP_GRANTS = `# Uniswap Grants Program v0.1
-
-*co-authored with [Ken Ng](https://twitter.com/nkennethk?lang=en)*
-
-## Summary:
-
-**This post outlines a framework for funding Uniswap ecosystem development with grants from the[ UNI Community Treasury](https://uniswap.org/blog/uni/).** The program starts small—sponsoring hackathons, [for example](https://gov.uniswap.org/c/proposal-discussion/5)—but could grow in significance over time (with renewals approved by governance) to fund core protocol development. Grants administration is a subjective process that cannot be easily automated, and thus we propose a nimble committee of 6 members —1 lead and 5 reviewers—to deliver an efficient, predictable process to applicants, such that funding can be administered without having to put each application to a vote. We propose the program start with an initial cap of $750K per quarter and a limit of 2 quarters before renewal—a sum that we feel is appropriate for an MVP relative to the size of the treasury that UNI token holders are entrusted with allocating.
-
-**Purpose:**
-
-**The mission of the UGP is to provide valuable resources to help grow the Uniswap ecosystem.** Through public discourse and inbound applications, the community will get first-hand exposure to identify and respond to the most pressing needs of the ecosystem, as well as the ability to support innovative projects expanding the capabilities of Uniswap. By rewarding talent early with developer incentives, bounties, and infrastructure support, UGP acts as a catalyst for growth and helps to maintain Uniswap as a nexus for DeFi on Ethereum.
-
-**Quarterly Budget:**
-
-* Max quarterly budget of up to $750k
-* Budget and caps to be assessed every six months
-
-**Grant Allocation Committee:**
-
-* Of 6 committee members: 1 lead and 5 reviewers
-* Each committee has a term of 2 quarters (6 months) after which the program needs to be renewed by UNI governance
-* Committee functions as a 4 of 5 multi-sig
-
-**Committee Members**
-
-While the goals and priorities of the grant program will be thoroughly discussed and reviewed by the community through public discourse, **the decision to start UGP by operating as a small committee is to ensure that the application and decision process will be efficient and predictable, so applicants have clear objectives and timely decisions.**
-
-Starting with just six members enables the committee to efficiently fund projects with tight feedback loops and rapid iterations. The purpose of this committee would be to test the hypothesis that the Grants Program can successfully provide value for the UNI ecosystem before scaling the program.
-
-**We suggest the grants program is administered by a single lead. Here we propose Kenneth Ng, a co-author of this post**. Ken has helped grow the Ethereum Foundation Grants Program over the last two years in establishing high level priorities and adapting for the ecosystems needs.
-
-**The other 5 committee members should be thought of as “reviewers” — UNI community members who will keep the grants program functional by ensuring Ken is leading effectively and, of course, not absconding with funds.** Part of the reviewers job is to hold the program accountable for success (defined below) and/or return any excess funds to the UNI treasury. Reviewers are not compensated as part of this proposal as we expect their time commitment to be minimal. Compensation for the lead role is discussed below, as we expect this to be a labor intensive role.
-
-**Program Lead:** [Ken Ng](https://twitter.com/nkennethk?lang=en) (HL Creative Corp)
-*Ecosystem Support Program at the Ethereum Foundation*
-
-1. Reviewer: [Jesse Walden](https://twitter.com/jessewldn) (o/b/o Unofficial LLC dba [Variant Fund](http://twitter.com/variantfund))
-*Founder and Investor at Variant Fund (holds UNI)*
-
-2. Reviewer: [Monet Supply](https://twitter.com/MonetSupply)
-*Risk Analyst at MakerDAO*
-
-3. Reviewer: [Robert Leshner](https://twitter.com/rleshner)
-*Founder and CEO of Compound Finance*
-
-4. Reviewer: [Kain Warwick](https://twitter.com/kaiynne)
-*Founder of Synthetix*
-
-5. Reviewer: [Ashleigh Schap](https://twitter.com/ashleighschap)
-*Growth Lead, Uniswap (Company)*
-
-## Methodology
-
-**1.1 Budget**
-
-This proposal recommends a max cap of $750K per quarter, with the ability to reevaluate biannually at each epoch (two fiscal quarters). While the UGP Grants Committee will be the decision makers around individual grants, respective budgets, roadmaps, and milestones, any top-level changes to UGP including epochs and max cap, will require full community quorum (4% approval).
-
-The UGP will be funded by the UNI treasury according to the[ release schedule](https://uniswap.org/blog/uni/) set out by the Uniswap team, whereby 43% of the UNI treasury is released over a four-year timeline. In Year 1 this will total to 172,000,000 UNI (~$344M as of writing).
-
-Taking into consideration the current landscape of ecosystem funding across Ethereum, the community would be hard-pressed to allocate even 5% of Year 1’s treasury. For context Gitcoin CLR Round 7 distributed $725k ($450k in matched) across 857 projects and YTD, Moloch has granted just under $200k but in contrast, the EF has committed to somewhere in the 8 figure range.
-
-**1.2 Committee Compensation**
-
-Operating a successful grants program takes considerable time and effort. Take, for instance, the EF Ecosystem Support Program, which has awarded grants since 2018, consists of an internal team at the Foundation as well as an ever increasing roster of community advisors in order to keep expanding and adapting to best serve the needs of the Ethereum ecosystem. While the structure of the allocation committee has six members, we propose that only the lead will be remunerated for their work in establishing the initial processes, vetting applications, and managing the program overall as this role is expected to be time consuming if the program is to be succesful. We propose that the other committee members be unpaid UNI ecosystem stakeholders who have an interest in seeing the protocol ecosystem continue to operate and grow.
-
-**We propose the lead be compensated 25 UNI/hr (approximately $100 USD at time of this writing) capped at 30 hours/week. This compensation, along with the quarterly budget, will be allocated to the UGP multisig from the UNI treasury**. In keeping with the committee’s commitment to the community, hours and duties will be logged publicly and transparently .
-
-**2.1 Priorities**
-
-Initially, the program aims to start narrow in scope, funding peripheral ecosystem initiatives, such as targeted bounties, hackathon sponsorships, and other low-stakes means of building out the Uniswap developer ecosystem. Over time, if the program proves effective, the grant allocations can grow in scope to include, for example, improved frontends, trading interfaces, and eventually, core protocol development.
-
-![|624x199](upload://vNP0APCOjiwQMurCmYI47cTLklc.png)
-
-With the initial priorities in mind, some effective measures for quick successes might look like:
-
-* Total number of projects funded
-* Quarterly increase in applications
-* Project engagement post-event/funding
-* Overall community engagement/sentiment
-
-**2.2 Timeline**
-
-In keeping with the fast pace of the UNI ecosystem, we organize time in epochs, or two calendar quarters. Each epoch will see two funding rounds, one per quarter, after which the community can review and create proposals to improve or revamp the program as they deem fit.
-
-**![|624x245](upload://n56TSh5X3mt4TSqVVMFhbnZM0eM.png)**
-
-**Rolling Wave 1 & 2 Applications**
-
-* Starting in Q1 2021, UGP will start accepting applications for events looking for support in the form of bounties or prizes that in parallel can be proactively sourced. During these first two waves of funding projects, the allocation committee lead can begin laying out guardrails for continued funding
-
-* Considering the immediate feedback loops for the first epoch, we expect these allocation decisions to be discussed and reviewed by the larger community. Should this not be of value, the community can submit a formal governance proposal to change any piece of UGP that was not effective
-
-**Wave 3 & Beyond**
-
-* Beginning with Wave 3, there should have been enough time with impactful projects funded to be considered for follow-on funding, should it make sense. In the same vein, projects within scope will be expanded to also include those working on integrations and and other key components.
-
-* Beyond the second epoch, as the community helps to review and help adapt UGP to be most effective, the scope will continue to grow in order to accommodate the state of the ecosystem including that of core protocol improvements
-
-## Conclusion:
-
-**If this proposal is successfully approved, UGP will start accepting applications on a rolling basis beginning at the start of 2021.** With the phases and priorities laid out above, UGP will aim to make a significant impact by catalyzing growth and innovation in the UNI ecosystem.
-
-**This program is meant to be the simplest possible MVP of a Uniswap Ecosystem Grants initiative.** While the multi-sig committee comes with trust assumptions about the members, our hope is the community will approve this limited engagement to get the ball rolling in an efficient structure. **After the first epoch (2 fiscal quarters) the burden of proof will be on UGP to show empirical evidence that the program is worth continuing in its existing form and will submit to governance to renew treasury funding.**
-
-If this program proves successful, we hope it will inspire others to follow suit and create their own funding committees for allocating treasury capital—ideally with different specializations.
-`
diff --git a/src/constants/v1/index.ts b/src/constants/v1/index.ts
deleted file mode 100644
index 9adf780..0000000
--- a/src/constants/v1/index.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Interface } from '@ethersproject/abi'
-import { ChainId } from '@uniswap/sdk'
-import V1_EXCHANGE_ABI from './v1_exchange.json'
-import V1_FACTORY_ABI from './v1_factory.json'
-
-const V1_FACTORY_ADDRESSES: { [chainId in ChainId]: string } = {
- [ChainId.MAINNET]: '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95',
- [ChainId.ROPSTEN]: '0x9c83dCE8CA20E9aAF9D3efc003b2ea62aBC08351',
- [ChainId.RINKEBY]: '0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36',
- [ChainId.GÖRLI]: '0x6Ce570d02D73d4c384b46135E87f8C592A8c86dA',
- [ChainId.KOVAN]: '0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30',
-}
-
-const V1_FACTORY_INTERFACE = new Interface(V1_FACTORY_ABI)
-const V1_EXCHANGE_INTERFACE = new Interface(V1_EXCHANGE_ABI)
-
-export { V1_FACTORY_ADDRESSES, V1_FACTORY_INTERFACE, V1_FACTORY_ABI, V1_EXCHANGE_INTERFACE, V1_EXCHANGE_ABI }
diff --git a/src/constants/v1/v1_exchange.json b/src/constants/v1/v1_exchange.json
deleted file mode 100644
index 9448326..0000000
--- a/src/constants/v1/v1_exchange.json
+++ /dev/null
@@ -1,971 +0,0 @@
-[
- {
- "name": "TokenPurchase",
- "inputs": [
- {
- "type": "address",
- "name": "buyer",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "eth_sold",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "tokens_bought",
- "indexed": true
- }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "EthPurchase",
- "inputs": [
- {
- "type": "address",
- "name": "buyer",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "tokens_sold",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "eth_bought",
- "indexed": true
- }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "AddLiquidity",
- "inputs": [
- {
- "type": "address",
- "name": "provider",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "eth_amount",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "token_amount",
- "indexed": true
- }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "RemoveLiquidity",
- "inputs": [
- {
- "type": "address",
- "name": "provider",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "eth_amount",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "token_amount",
- "indexed": true
- }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "Transfer",
- "inputs": [
- {
- "type": "address",
- "name": "_from",
- "indexed": true
- },
- {
- "type": "address",
- "name": "_to",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "_value",
- "indexed": false
- }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "Approval",
- "inputs": [
- {
- "type": "address",
- "name": "_owner",
- "indexed": true
- },
- {
- "type": "address",
- "name": "_spender",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "_value",
- "indexed": false
- }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "setup",
- "outputs": [],
- "inputs": [
- {
- "type": "address",
- "name": "token_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "addLiquidity",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "min_liquidity"
- },
- {
- "type": "uint256",
- "name": "max_tokens"
- },
- {
- "type": "uint256",
- "name": "deadline"
- }
- ],
- "constant": false,
- "payable": true,
- "type": "function"
- },
- {
- "name": "removeLiquidity",
- "outputs": [
- {
- "type": "uint256",
- "name": "outA"
- },
- {
- "type": "uint256",
- "name": "outB"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "amount"
- },
- {
- "type": "uint256",
- "name": "min_eth"
- },
- {
- "type": "uint256",
- "name": "min_tokens"
- },
- {
- "type": "uint256",
- "name": "deadline"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "__default__",
- "outputs": [],
- "inputs": [],
- "constant": false,
- "payable": true,
- "type": "function"
- },
- {
- "name": "ethToTokenSwapInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "min_tokens"
- },
- {
- "type": "uint256",
- "name": "deadline"
- }
- ],
- "constant": false,
- "payable": true,
- "type": "function"
- },
- {
- "name": "ethToTokenTransferInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "min_tokens"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- }
- ],
- "constant": false,
- "payable": true,
- "type": "function"
- },
- {
- "name": "ethToTokenSwapOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- },
- {
- "type": "uint256",
- "name": "deadline"
- }
- ],
- "constant": false,
- "payable": true,
- "type": "function"
- },
- {
- "name": "ethToTokenTransferOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- }
- ],
- "constant": false,
- "payable": true,
- "type": "function"
- },
- {
- "name": "tokenToEthSwapInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- },
- {
- "type": "uint256",
- "name": "min_eth"
- },
- {
- "type": "uint256",
- "name": "deadline"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToEthTransferInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- },
- {
- "type": "uint256",
- "name": "min_eth"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToEthSwapOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "eth_bought"
- },
- {
- "type": "uint256",
- "name": "max_tokens"
- },
- {
- "type": "uint256",
- "name": "deadline"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToEthTransferOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "eth_bought"
- },
- {
- "type": "uint256",
- "name": "max_tokens"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToTokenSwapInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- },
- {
- "type": "uint256",
- "name": "min_tokens_bought"
- },
- {
- "type": "uint256",
- "name": "min_eth_bought"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "token_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToTokenTransferInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- },
- {
- "type": "uint256",
- "name": "min_tokens_bought"
- },
- {
- "type": "uint256",
- "name": "min_eth_bought"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- },
- {
- "type": "address",
- "name": "token_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToTokenSwapOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- },
- {
- "type": "uint256",
- "name": "max_tokens_sold"
- },
- {
- "type": "uint256",
- "name": "max_eth_sold"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "token_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToTokenTransferOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- },
- {
- "type": "uint256",
- "name": "max_tokens_sold"
- },
- {
- "type": "uint256",
- "name": "max_eth_sold"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- },
- {
- "type": "address",
- "name": "token_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToExchangeSwapInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- },
- {
- "type": "uint256",
- "name": "min_tokens_bought"
- },
- {
- "type": "uint256",
- "name": "min_eth_bought"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "exchange_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToExchangeTransferInput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- },
- {
- "type": "uint256",
- "name": "min_tokens_bought"
- },
- {
- "type": "uint256",
- "name": "min_eth_bought"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- },
- {
- "type": "address",
- "name": "exchange_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToExchangeSwapOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- },
- {
- "type": "uint256",
- "name": "max_tokens_sold"
- },
- {
- "type": "uint256",
- "name": "max_eth_sold"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "exchange_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenToExchangeTransferOutput",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- },
- {
- "type": "uint256",
- "name": "max_tokens_sold"
- },
- {
- "type": "uint256",
- "name": "max_eth_sold"
- },
- {
- "type": "uint256",
- "name": "deadline"
- },
- {
- "type": "address",
- "name": "recipient"
- },
- {
- "type": "address",
- "name": "exchange_addr"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getEthToTokenInputPrice",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "eth_sold"
- }
- ],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getEthToTokenOutputPrice",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_bought"
- }
- ],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getTokenToEthInputPrice",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "tokens_sold"
- }
- ],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getTokenToEthOutputPrice",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "uint256",
- "name": "eth_bought"
- }
- ],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenAddress",
- "outputs": [
- {
- "type": "address",
- "name": "out"
- }
- ],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "factoryAddress",
- "outputs": [
- {
- "type": "address",
- "name": "out"
- }
- ],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "balanceOf",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "address",
- "name": "_owner"
- }
- ],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "transfer",
- "outputs": [
- {
- "type": "bool",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "address",
- "name": "_to"
- },
- {
- "type": "uint256",
- "name": "_value"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "transferFrom",
- "outputs": [
- {
- "type": "bool",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "address",
- "name": "_from"
- },
- {
- "type": "address",
- "name": "_to"
- },
- {
- "type": "uint256",
- "name": "_value"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "approve",
- "outputs": [
- {
- "type": "bool",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "address",
- "name": "_spender"
- },
- {
- "type": "uint256",
- "name": "_value"
- }
- ],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "allowance",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [
- {
- "type": "address",
- "name": "_owner"
- },
- {
- "type": "address",
- "name": "_spender"
- }
- ],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "name",
- "outputs": [
- {
- "type": "bytes32",
- "name": "out"
- }
- ],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "symbol",
- "outputs": [
- {
- "type": "bytes32",
- "name": "out"
- }
- ],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "decimals",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "totalSupply",
- "outputs": [
- {
- "type": "uint256",
- "name": "out"
- }
- ],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- }
-]
diff --git a/src/constants/v1/v1_factory.json b/src/constants/v1/v1_factory.json
deleted file mode 100644
index cbdf5fa..0000000
--- a/src/constants/v1/v1_factory.json
+++ /dev/null
@@ -1,67 +0,0 @@
-[
- {
- "name": "NewExchange",
- "inputs": [
- { "type": "address", "name": "token", "indexed": true },
- { "type": "address", "name": "exchange", "indexed": true }
- ],
- "anonymous": false,
- "type": "event"
- },
- {
- "name": "initializeFactory",
- "outputs": [],
- "inputs": [{ "type": "address", "name": "template" }],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "createExchange",
- "outputs": [{ "type": "address", "name": "out" }],
- "inputs": [{ "type": "address", "name": "token" }],
- "constant": false,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getExchange",
- "outputs": [{ "type": "address", "name": "out" }],
- "inputs": [{ "type": "address", "name": "token" }],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getToken",
- "outputs": [{ "type": "address", "name": "out" }],
- "inputs": [{ "type": "address", "name": "exchange" }],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "getTokenWithId",
- "outputs": [{ "type": "address", "name": "out" }],
- "inputs": [{ "type": "uint256", "name": "token_id" }],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "exchangeTemplate",
- "outputs": [{ "type": "address", "name": "out" }],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- },
- {
- "name": "tokenCount",
- "outputs": [{ "type": "uint256", "name": "out" }],
- "inputs": [],
- "constant": true,
- "payable": false,
- "type": "function"
- }
-]
diff --git a/src/data/Allowances.ts b/src/data/Allowances.ts
deleted file mode 100644
index 3acee34..0000000
--- a/src/data/Allowances.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Token, TokenAmount } from '@uniswap/sdk'
-import { useMemo } from 'react'
-
-import { useTokenContract } from '../hooks/useContract'
-import { useSingleCallResult } from '../state/multicall/hooks'
-
-export function useTokenAllowance(token?: Token, owner?: string, spender?: string): TokenAmount | undefined {
- const contract = useTokenContract(token?.address, false)
-
- const inputs = useMemo(() => [owner, spender], [owner, spender])
- const allowance = useSingleCallResult(contract, 'allowance', inputs).result
-
- return useMemo(() => (token && allowance ? new TokenAmount(token, allowance.toString()) : undefined), [
- token,
- allowance,
- ])
-}
diff --git a/src/data/Reserves.ts b/src/data/Reserves.ts
deleted file mode 100644
index 27fd364..0000000
--- a/src/data/Reserves.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { TokenAmount, Pair, Currency } from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { abi as IUniswapV2PairABI } from '@uniswap/v2-core/build/IUniswapV2Pair.json'
-import { Interface } from '@ethersproject/abi'
-import { useActiveWeb3React } from '../hooks'
-
-import { useMultipleContractSingleData } from '../state/multicall/hooks'
-import { wrappedCurrency } from '../utils/wrappedCurrency'
-
-const PAIR_INTERFACE = new Interface(IUniswapV2PairABI)
-
-export enum PairState {
- LOADING,
- NOT_EXISTS,
- EXISTS,
- INVALID,
-}
-
-export function usePairs(currencies: [Currency | undefined, Currency | undefined][]): [PairState, Pair | null][] {
- const { chainId } = useActiveWeb3React()
-
- const tokens = useMemo(
- () =>
- currencies.map(([currencyA, currencyB]) => [
- wrappedCurrency(currencyA, chainId),
- wrappedCurrency(currencyB, chainId),
- ]),
- [chainId, currencies]
- )
-
- const pairAddresses = useMemo(
- () =>
- tokens.map(([tokenA, tokenB]) => {
- return tokenA && tokenB && !tokenA.equals(tokenB) ? Pair.getAddress(tokenA, tokenB) : undefined
- }),
- [tokens]
- )
-
- const results = useMultipleContractSingleData(pairAddresses, PAIR_INTERFACE, 'getReserves')
-
- return useMemo(() => {
- return results.map((result, i) => {
- const { result: reserves, loading } = result
- const tokenA = tokens[i][0]
- const tokenB = tokens[i][1]
-
- if (loading) return [PairState.LOADING, null]
- if (!tokenA || !tokenB || tokenA.equals(tokenB)) return [PairState.INVALID, null]
- if (!reserves) return [PairState.NOT_EXISTS, null]
- const { reserve0, reserve1 } = reserves
- const [token0, token1] = tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
- return [
- PairState.EXISTS,
- new Pair(new TokenAmount(token0, reserve0.toString()), new TokenAmount(token1, reserve1.toString())),
- ]
- })
- }, [results, tokens])
-}
-
-export function usePair(tokenA?: Currency, tokenB?: Currency): [PairState, Pair | null] {
- return usePairs([[tokenA, tokenB]])[0]
-}
diff --git a/src/data/TotalSupply.ts b/src/data/TotalSupply.ts
deleted file mode 100644
index e970ec8..0000000
--- a/src/data/TotalSupply.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { BigNumber } from '@ethersproject/bignumber'
-import { Token, TokenAmount } from '@uniswap/sdk'
-import { useTokenContract } from '../hooks/useContract'
-import { useSingleCallResult } from '../state/multicall/hooks'
-
-// returns undefined if input token is undefined, or fails to get token contract,
-// or contract total supply cannot be fetched
-export function useTotalSupply(token?: Token): TokenAmount | undefined {
- const contract = useTokenContract(token?.address, false)
-
- const totalSupply: BigNumber = useSingleCallResult(contract, 'totalSupply')?.result?.[0]
-
- return token && totalSupply ? new TokenAmount(token, totalSupply.toString()) : undefined
-}
diff --git a/src/data/V1.ts b/src/data/V1.ts
deleted file mode 100644
index 74ecec0..0000000
--- a/src/data/V1.ts
+++ /dev/null
@@ -1,157 +0,0 @@
-import { AddressZero } from '@ethersproject/constants'
-import {
- BigintIsh,
- Currency,
- CurrencyAmount,
- ETHER,
- JSBI,
- Pair,
- Route,
- Token,
- TokenAmount,
- Trade,
- TradeType,
- WETH,
-} from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { useActiveWeb3React } from '../hooks'
-import { useAllTokens } from '../hooks/Tokens'
-import { useV1FactoryContract } from '../hooks/useContract'
-import { Version } from '../hooks/useToggledVersion'
-import { NEVER_RELOAD, useSingleCallResult, useSingleContractMultipleData } from '../state/multicall/hooks'
-import { useETHBalances, useTokenBalance, useTokenBalances } from '../state/wallet/hooks'
-
-export function useV1ExchangeAddress(tokenAddress?: string): string | undefined {
- const contract = useV1FactoryContract()
-
- const inputs = useMemo(() => [tokenAddress], [tokenAddress])
- return useSingleCallResult(contract, 'getExchange', inputs)?.result?.[0]
-}
-
-export class MockV1Pair extends Pair {
- constructor(etherAmount: BigintIsh, tokenAmount: TokenAmount) {
- super(tokenAmount, new TokenAmount(WETH[tokenAmount.token.chainId], etherAmount))
- }
-}
-
-function useMockV1Pair(inputCurrency?: Currency): MockV1Pair | undefined {
- const token = inputCurrency instanceof Token ? inputCurrency : undefined
-
- const isWETH = Boolean(token && token.equals(WETH[token.chainId]))
- const v1PairAddress = useV1ExchangeAddress(isWETH ? undefined : token?.address)
- const tokenBalance = useTokenBalance(v1PairAddress, token)
- const ETHBalance = useETHBalances([v1PairAddress])[v1PairAddress ?? '']
-
- return useMemo(
- () =>
- token && tokenBalance && ETHBalance && inputCurrency ? new MockV1Pair(ETHBalance.raw, tokenBalance) : undefined,
- [ETHBalance, inputCurrency, token, tokenBalance]
- )
-}
-
-// returns all v1 exchange addresses in the user's token list
-export function useAllTokenV1Exchanges(): { [exchangeAddress: string]: Token } {
- const allTokens = useAllTokens()
- const factory = useV1FactoryContract()
- const args = useMemo(() => Object.keys(allTokens).map((tokenAddress) => [tokenAddress]), [allTokens])
-
- const data = useSingleContractMultipleData(factory, 'getExchange', args, NEVER_RELOAD)
-
- return useMemo(
- () =>
- data?.reduce<{ [exchangeAddress: string]: Token }>((memo, { result }, ix) => {
- if (result?.[0] && result[0] !== AddressZero) {
- memo[result[0]] = allTokens[args[ix][0]]
- }
- return memo
- }, {}) ?? {},
- [allTokens, args, data]
- )
-}
-
-// returns whether any of the tokens in the user's token list have liquidity on v1
-export function useUserHasLiquidityInAllTokens(): boolean | undefined {
- const { account, chainId } = useActiveWeb3React()
-
- const exchanges = useAllTokenV1Exchanges()
-
- const v1ExchangeLiquidityTokens = useMemo(
- () =>
- chainId ? Object.keys(exchanges).map((address) => new Token(chainId, address, 18, 'UNI-V1', 'Uniswap V1')) : [],
- [chainId, exchanges]
- )
-
- const balances = useTokenBalances(account ?? undefined, v1ExchangeLiquidityTokens)
-
- return useMemo(
- () =>
- Object.keys(balances).some((tokenAddress) => {
- const b = balances[tokenAddress]?.raw
- return b && JSBI.greaterThan(b, JSBI.BigInt(0))
- }),
- [balances]
- )
-}
-
-/**
- * Returns the trade to execute on V1 to go between input and output token
- */
-export function useV1Trade(
- isExactIn?: boolean,
- inputCurrency?: Currency,
- outputCurrency?: Currency,
- exactAmount?: CurrencyAmount
-): Trade | undefined {
- // get the mock v1 pairs
- const inputPair = useMockV1Pair(inputCurrency)
- const outputPair = useMockV1Pair(outputCurrency)
-
- const inputIsETH = inputCurrency === ETHER
- const outputIsETH = outputCurrency === ETHER
-
- // construct a direct or through ETH v1 route
- let pairs: Pair[] = []
- if (inputIsETH && outputPair) {
- pairs = [outputPair]
- } else if (outputIsETH && inputPair) {
- pairs = [inputPair]
- }
- // if neither are ETH, it's token-to-token (if they both exist)
- else if (inputPair && outputPair) {
- pairs = [inputPair, outputPair]
- }
-
- const route = inputCurrency && pairs && pairs.length > 0 && new Route(pairs, inputCurrency, outputCurrency)
- let v1Trade: Trade | undefined
- try {
- v1Trade =
- route && exactAmount
- ? new Trade(route, exactAmount, isExactIn ? TradeType.EXACT_INPUT : TradeType.EXACT_OUTPUT)
- : undefined
- } catch (error) {
- console.debug('Failed to create V1 trade', error)
- }
- return v1Trade
-}
-
-export function getTradeVersion(trade?: Trade): Version | undefined {
- const isV1 = trade?.route?.pairs?.some((pair) => pair instanceof MockV1Pair)
- if (isV1) return Version.v1
- if (isV1 === false) return Version.v2
- return undefined
-}
-
-// returns the v1 exchange against which a trade should be executed
-export function useV1TradeExchangeAddress(trade: Trade | undefined): string | undefined {
- const tokenAddress: string | undefined = useMemo(() => {
- if (!trade) return undefined
- const isV1 = getTradeVersion(trade) === Version.v1
- if (!isV1) return undefined
- return trade.inputAmount instanceof TokenAmount
- ? trade.inputAmount.token.address
- : trade.outputAmount instanceof TokenAmount
- ? trade.outputAmount.token.address
- : undefined
- }, [trade])
- return useV1ExchangeAddress(tokenAddress)
-}
diff --git a/src/hooks/StakingRewards.json b/src/hooks/StakingRewards.json
deleted file mode 100644
index ae51df9..0000000
--- a/src/hooks/StakingRewards.json
+++ /dev/null
@@ -1,474 +0,0 @@
-{
- "abi": [
- {
- "inputs": [
- {
- "internalType": "address",
- "name": "_rewardsDistribution",
- "type": "address"
- },
- {
- "internalType": "address",
- "name": "_rewardsToken",
- "type": "address"
- },
- {
- "internalType": "address",
- "name": "_stakingToken",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "constructor"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": false,
- "internalType": "uint256",
- "name": "reward",
- "type": "uint256"
- }
- ],
- "name": "RewardAdded",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "internalType": "address",
- "name": "user",
- "type": "address"
- },
- {
- "indexed": false,
- "internalType": "uint256",
- "name": "reward",
- "type": "uint256"
- }
- ],
- "name": "RewardPaid",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "internalType": "address",
- "name": "user",
- "type": "address"
- },
- {
- "indexed": false,
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
- }
- ],
- "name": "Staked",
- "type": "event"
- },
- {
- "anonymous": false,
- "inputs": [
- {
- "indexed": true,
- "internalType": "address",
- "name": "user",
- "type": "address"
- },
- {
- "indexed": false,
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
- }
- ],
- "name": "Withdrawn",
- "type": "event"
- },
- {
- "constant": true,
- "inputs": [
- {
- "internalType": "address",
- "name": "account",
- "type": "address"
- }
- ],
- "name": "balanceOf",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "internalType": "address",
- "name": "account",
- "type": "address"
- }
- ],
- "name": "earned",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "exit",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "getReward",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "getRewardForDuration",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "lastTimeRewardApplicable",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "lastUpdateTime",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "internalType": "uint256",
- "name": "reward",
- "type": "uint256"
- }
- ],
- "name": "notifyRewardAmount",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "periodFinish",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "rewardPerToken",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "rewardPerTokenStored",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "rewardRate",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "internalType": "address",
- "name": "",
- "type": "address"
- }
- ],
- "name": "rewards",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "rewardsDistribution",
- "outputs": [
- {
- "internalType": "address",
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "rewardsDuration",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "rewardsToken",
- "outputs": [
- {
- "internalType": "contract IERC20",
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
- }
- ],
- "name": "stake",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
- },
- {
- "internalType": "uint256",
- "name": "deadline",
- "type": "uint256"
- },
- {
- "internalType": "uint8",
- "name": "v",
- "type": "uint8"
- },
- {
- "internalType": "bytes32",
- "name": "r",
- "type": "bytes32"
- },
- {
- "internalType": "bytes32",
- "name": "s",
- "type": "bytes32"
- }
- ],
- "name": "stakeWithPermit",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "stakingToken",
- "outputs": [
- {
- "internalType": "contract IERC20",
- "name": "",
- "type": "address"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [
- {
- "internalType": "address",
- "name": "",
- "type": "address"
- }
- ],
- "name": "userRewardPerTokenPaid",
- "outputs": [
- {
- "internalType": "uint256",
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "internalType": "uint256",
- "name": "amount",
- "type": "uint256"
- }
- ],
- "name": "withdraw",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- }
- ],
- "evm": {
- "bytecode": {
- "linkReferences": {},
- "object": "608060405260006004556000600555624f1a0060065534801561002157600080fd5b506040516117853803806117858339818101604052606081101561004457600080fd5b508051602082015160409092015160018055600280546001600160a01b039485166001600160a01b0319918216179091556003805492851692821692909217909155600080549390921692169190911790556116e0806100a56000396000f3fe608060405234801561001057600080fd5b50600436106101815760003560e01c80637b0a47ee116100d8578063cd3daf9d1161008c578063e9fad8ee11610066578063e9fad8ee14610346578063ebe2b12b1461034e578063ecd9ba821461035657610181565b8063cd3daf9d1461032e578063d1af0c7d14610336578063df136d651461033e57610181565b80638b876347116100bd5780638b876347146102d6578063a694fc3a14610309578063c8f33c911461032657610181565b80637b0a47ee146102c657806380faa57d146102ce57610181565b8063386a95251161013a5780633fc6df6e116101145780633fc6df6e1461025a57806370a082311461028b57806372f702f3146102be57610181565b8063386a95251461022d5780633c6b16ab146102355780633d18b9121461025257610181565b806318160ddd1161016b57806318160ddd146101fe5780631c1f78eb146102065780632e1a7d4d1461020e57610181565b80628cc262146101865780630700037d146101cb575b600080fd5b6101b96004803603602081101561019c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661038e565b60408051918252519081900360200190f35b6101b9600480360360208110156101e157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661043e565b6101b9610450565b6101b9610457565b61022b6004803603602081101561022457600080fd5b5035610475565b005b6101b961067d565b61022b6004803603602081101561024b57600080fd5b5035610683565b61022b610955565b610262610acc565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101b9600480360360208110156102a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610ae8565b610262610b10565b6101b9610b2c565b6101b9610b32565b6101b9600480360360208110156102ec57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b40565b61022b6004803603602081101561031f57600080fd5b5035610b52565b6101b9610d57565b6101b9610d5d565b610262610db7565b6101b9610dd3565b61022b610dd9565b6101b9610dfc565b61022b600480360360a081101561036c57600080fd5b5080359060208101359060ff6040820135169060608101359060800135610e02565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a60209081526040808320546009909252822054610438919061042c90670de0b6b3a764000090610420906103ee906103e2610d5d565b9063ffffffff6110c616565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600c60205260409020549063ffffffff61113d16565b9063ffffffff6111b716565b9063ffffffff61123b16565b92915050565b600a6020526000908152604090205481565b600b545b90565b600061047060065460055461113d90919063ffffffff16565b905090565b6001805481019081905533610488610d5d565b600855610493610b32565b60075573ffffffffffffffffffffffffffffffffffffffff8116156104f4576104bb8161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b6000831161056357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43616e6e6f742077697468647261772030000000000000000000000000000000604482015290519081900360640190fd5b600b54610576908463ffffffff6110c616565b600b55336000908152600c6020526040902054610599908463ffffffff6110c616565b336000818152600c60205260409020919091556003546105d29173ffffffffffffffffffffffffffffffffffffffff90911690856112af565b60408051848152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a250600154811461067957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050565b60065481565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611658602a913960400191505060405180910390fd5b60006106fd610d5d565b600855610708610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610769576107308161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b600454421061078e5760065461078690839063ffffffff6111b716565b6005556107dd565b6004546000906107a4904263ffffffff6110c616565b905060006107bd6005548361113d90919063ffffffff16565b6006549091506107d790610420868463ffffffff61123b16565b60055550505b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561084e57600080fd5b505afa158015610862573d6000803e3d6000fd5b505050506040513d602081101561087857600080fd5b505160065490915061089190829063ffffffff6111b716565b600554111561090157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015290519081900360640190fd5b42600781905560065461091a919063ffffffff61123b16565b6004556040805184815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a1505050565b6001805481019081905533610968610d5d565b600855610973610b32565b60075573ffffffffffffffffffffffffffffffffffffffff8116156109d45761099b8161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b336000908152600a60205260409020548015610a5757336000818152600a6020526040812055600254610a209173ffffffffffffffffffffffffffffffffffffffff90911690836112af565b60408051828152905133917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a25b50506001548114610ac957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205490565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60055481565b600061047042600454611341565b60096020526000908152604090205481565b6001805481019081905533610b65610d5d565b600855610b70610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610bd157610b988161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b60008311610c4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610c53908463ffffffff61123b16565b600b55336000908152600c6020526040902054610c76908463ffffffff61123b16565b336000818152600c6020526040902091909155600354610cb09173ffffffffffffffffffffffffffffffffffffffff909116903086611357565b60408051848152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a250600154811461067957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60075481565b6000600b5460001415610d735750600854610454565b610470610da8600b54610420670de0b6b3a7640000610d9c600554610d9c6007546103e2610b32565b9063ffffffff61113d16565b6008549063ffffffff61123b16565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60085481565b336000908152600c6020526040902054610df290610475565b610dfa610955565b565b60045481565b6001805481019081905533610e15610d5d565b600855610e20610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610e8157610e488161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b60008711610ef057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610f03908863ffffffff61123b16565b600b55336000908152600c6020526040902054610f26908863ffffffff61123b16565b336000818152600c60205260408082209390935560035483517fd505accf0000000000000000000000000000000000000000000000000000000081526004810193909352306024840152604483018b9052606483018a905260ff8916608484015260a4830188905260c48301879052925173ffffffffffffffffffffffffffffffffffffffff9093169263d505accf9260e480820193929182900301818387803b158015610fd357600080fd5b505af1158015610fe7573d6000803e3d6000fd5b5050600354611017925073ffffffffffffffffffffffffffffffffffffffff16905033308a63ffffffff61135716565b60408051888152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25060015481146110be57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b60008282111561113757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008261114c57506000610438565b8282028284828161115957fe5b04146111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806116376021913960400191505060405180910390fd5b9392505050565b600080821161122757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161123257fe5b04949350505050565b6000828201838110156111b057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261133c9084906113f2565b505050565b600081831061135057816111b0565b5090919050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526113ec9085906113f2565b50505050565b6114118273ffffffffffffffffffffffffffffffffffffffff16611630565b61147c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106114e557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016114a8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611547576040519150601f19603f3d011682016040523d82523d6000602084013e61154c565b606091505b5091509150816115bd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156113ec578080602001905160208110156115d957600080fd5b50516113ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611682602a913960400191505060405180910390fd5b3b15159056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f742052657761726473446973747269627574696f6e20636f6e74726163745361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72315820f909fa3a0910f3b22e95648cbca716b06606dafe47e4b95662d41e95d993a43764736f6c63430005100032",
- "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x0 PUSH1 0x4 SSTORE PUSH1 0x0 PUSH1 0x5 SSTORE PUSH3 0x4F1A00 PUSH1 0x6 SSTORE CALLVALUE DUP1 ISZERO PUSH2 0x21 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x40 MLOAD PUSH2 0x1785 CODESIZE SUB DUP1 PUSH2 0x1785 DUP4 CODECOPY DUP2 DUP2 ADD PUSH1 0x40 MSTORE PUSH1 0x60 DUP2 LT ISZERO PUSH2 0x44 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP DUP1 MLOAD PUSH1 0x20 DUP3 ADD MLOAD PUSH1 0x40 SWAP1 SWAP3 ADD MLOAD PUSH1 0x1 DUP1 SSTORE PUSH1 0x2 DUP1 SLOAD PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB SWAP5 DUP6 AND PUSH1 0x1 PUSH1 0x1 PUSH1 0xA0 SHL SUB NOT SWAP2 DUP3 AND OR SWAP1 SWAP2 SSTORE PUSH1 0x3 DUP1 SLOAD SWAP3 DUP6 AND SWAP3 DUP3 AND SWAP3 SWAP1 SWAP3 OR SWAP1 SWAP2 SSTORE PUSH1 0x0 DUP1 SLOAD SWAP4 SWAP1 SWAP3 AND SWAP3 AND SWAP2 SWAP1 SWAP2 OR SWAP1 SSTORE PUSH2 0x16E0 DUP1 PUSH2 0xA5 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x181 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x7B0A47EE GT PUSH2 0xD8 JUMPI DUP1 PUSH4 0xCD3DAF9D GT PUSH2 0x8C JUMPI DUP1 PUSH4 0xE9FAD8EE GT PUSH2 0x66 JUMPI DUP1 PUSH4 0xE9FAD8EE EQ PUSH2 0x346 JUMPI DUP1 PUSH4 0xEBE2B12B EQ PUSH2 0x34E JUMPI DUP1 PUSH4 0xECD9BA82 EQ PUSH2 0x356 JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0xCD3DAF9D EQ PUSH2 0x32E JUMPI DUP1 PUSH4 0xD1AF0C7D EQ PUSH2 0x336 JUMPI DUP1 PUSH4 0xDF136D65 EQ PUSH2 0x33E JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x8B876347 GT PUSH2 0xBD JUMPI DUP1 PUSH4 0x8B876347 EQ PUSH2 0x2D6 JUMPI DUP1 PUSH4 0xA694FC3A EQ PUSH2 0x309 JUMPI DUP1 PUSH4 0xC8F33C91 EQ PUSH2 0x326 JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x7B0A47EE EQ PUSH2 0x2C6 JUMPI DUP1 PUSH4 0x80FAA57D EQ PUSH2 0x2CE JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x386A9525 GT PUSH2 0x13A JUMPI DUP1 PUSH4 0x3FC6DF6E GT PUSH2 0x114 JUMPI DUP1 PUSH4 0x3FC6DF6E EQ PUSH2 0x25A JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x28B JUMPI DUP1 PUSH4 0x72F702F3 EQ PUSH2 0x2BE JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x386A9525 EQ PUSH2 0x22D JUMPI DUP1 PUSH4 0x3C6B16AB EQ PUSH2 0x235 JUMPI DUP1 PUSH4 0x3D18B912 EQ PUSH2 0x252 JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x18160DDD GT PUSH2 0x16B JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x1FE JUMPI DUP1 PUSH4 0x1C1F78EB EQ PUSH2 0x206 JUMPI DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x20E JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH3 0x8CC262 EQ PUSH2 0x186 JUMPI DUP1 PUSH4 0x700037D EQ PUSH2 0x1CB JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x19C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x38E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x1E1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x43E JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0x450 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0x457 JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x224 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0x475 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x1B9 PUSH2 0x67D JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x24B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0x683 JUMP JUMPDEST PUSH2 0x22B PUSH2 0x955 JUMP JUMPDEST PUSH2 0x262 PUSH2 0xACC JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2A1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0xAE8 JUMP JUMPDEST PUSH2 0x262 PUSH2 0xB10 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xB2C JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xB32 JUMP JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2EC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0xB40 JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x31F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0xB52 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xD57 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xD5D JUMP JUMPDEST PUSH2 0x262 PUSH2 0xDB7 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xDD3 JUMP JUMPDEST PUSH2 0x22B PUSH2 0xDD9 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xDFC JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0xA0 DUP2 LT ISZERO PUSH2 0x36C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 DUP2 ADD CALLDATALOAD SWAP1 PUSH1 0xFF PUSH1 0x40 DUP3 ADD CALLDATALOAD AND SWAP1 PUSH1 0x60 DUP2 ADD CALLDATALOAD SWAP1 PUSH1 0x80 ADD CALLDATALOAD PUSH2 0xE02 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SLOAD PUSH1 0x9 SWAP1 SWAP3 MSTORE DUP3 KECCAK256 SLOAD PUSH2 0x438 SWAP2 SWAP1 PUSH2 0x42C SWAP1 PUSH8 0xDE0B6B3A7640000 SWAP1 PUSH2 0x420 SWAP1 PUSH2 0x3EE SWAP1 PUSH2 0x3E2 PUSH2 0xD5D JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP9 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x113D AND JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x11B7 AND JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0xA PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0xB SLOAD JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x470 PUSH1 0x6 SLOAD PUSH1 0x5 SLOAD PUSH2 0x113D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0x488 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0x493 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0x4F4 JUMPI PUSH2 0x4BB DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x0 DUP4 GT PUSH2 0x563 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x11 PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x43616E6E6F742077697468647261772030000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0xB SLOAD PUSH2 0x576 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST PUSH1 0xB SSTORE CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0x599 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SWAP2 SWAP1 SWAP2 SSTORE PUSH1 0x3 SLOAD PUSH2 0x5D2 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 DUP6 PUSH2 0x12AF JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0x7084F5476618D8E60B11EF0D7D3F06914655ADB8793E28FF7F018D4C76D505D5 SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0x679 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER EQ PUSH2 0x6F3 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1658 PUSH1 0x2A SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x6FD PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0x708 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0x769 JUMPI PUSH2 0x730 DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x4 SLOAD TIMESTAMP LT PUSH2 0x78E JUMPI PUSH1 0x6 SLOAD PUSH2 0x786 SWAP1 DUP4 SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x11B7 AND JUMP JUMPDEST PUSH1 0x5 SSTORE PUSH2 0x7DD JUMP JUMPDEST PUSH1 0x4 SLOAD PUSH1 0x0 SWAP1 PUSH2 0x7A4 SWAP1 TIMESTAMP PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x7BD PUSH1 0x5 SLOAD DUP4 PUSH2 0x113D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x6 SLOAD SWAP1 SWAP2 POP PUSH2 0x7D7 SWAP1 PUSH2 0x420 DUP7 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0x5 SSTORE POP POP JUMPDEST PUSH1 0x2 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH32 0x70A0823100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE ADDRESS PUSH1 0x4 DUP3 ADD MSTORE SWAP1 MLOAD PUSH1 0x0 SWAP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP2 PUSH4 0x70A08231 SWAP2 PUSH1 0x24 DUP1 DUP4 ADD SWAP3 PUSH1 0x20 SWAP3 SWAP2 SWAP1 DUP3 SWAP1 SUB ADD DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x84E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x862 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x878 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP MLOAD PUSH1 0x6 SLOAD SWAP1 SWAP2 POP PUSH2 0x891 SWAP1 DUP3 SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x11B7 AND JUMP JUMPDEST PUSH1 0x5 SLOAD GT ISZERO PUSH2 0x901 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x18 PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x50726F76696465642072657761726420746F6F20686967680000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST TIMESTAMP PUSH1 0x7 DUP2 SWAP1 SSTORE PUSH1 0x6 SLOAD PUSH2 0x91A SWAP2 SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0x4 SSTORE PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xDE88A922E0D3B88B24E9623EFEB464919C6BF9F66857A65E2BFCF2CE87A9433D SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP POP POP JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0x968 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0x973 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0x9D4 JUMPI PUSH2 0x99B DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP1 ISZERO PUSH2 0xA57 JUMPI CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 SSTORE PUSH1 0x2 SLOAD PUSH2 0xA20 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 DUP4 PUSH2 0x12AF JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP3 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0xE2403640BA68FED3A2F88B7557551D1993F84B99BB10FF833F0CF8DB0C5E0486 SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 JUMPDEST POP POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0xAC9 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD SWAP1 JUMP JUMPDEST PUSH1 0x3 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x5 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x470 TIMESTAMP PUSH1 0x4 SLOAD PUSH2 0x1341 JUMP JUMPDEST PUSH1 0x9 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0xB65 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0xB70 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0xBD1 JUMPI PUSH2 0xB98 DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x0 DUP4 GT PUSH2 0xC40 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x43616E6E6F74207374616B652030000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0xB SLOAD PUSH2 0xC53 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0xB SSTORE CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0xC76 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SWAP2 SWAP1 SWAP2 SSTORE PUSH1 0x3 SLOAD PUSH2 0xCB0 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 ADDRESS DUP7 PUSH2 0x1357 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0x9E71BC8EEA02A63969F509818F2DAFB9254532904319F9DBDA79B67BD34A5F3D SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0x679 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x7 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0xB SLOAD PUSH1 0x0 EQ ISZERO PUSH2 0xD73 JUMPI POP PUSH1 0x8 SLOAD PUSH2 0x454 JUMP JUMPDEST PUSH2 0x470 PUSH2 0xDA8 PUSH1 0xB SLOAD PUSH2 0x420 PUSH8 0xDE0B6B3A7640000 PUSH2 0xD9C PUSH1 0x5 SLOAD PUSH2 0xD9C PUSH1 0x7 SLOAD PUSH2 0x3E2 PUSH2 0xB32 JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x113D AND JUMP JUMPDEST PUSH1 0x8 SLOAD SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0x2 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x8 SLOAD DUP2 JUMP JUMPDEST CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0xDF2 SWAP1 PUSH2 0x475 JUMP JUMPDEST PUSH2 0xDFA PUSH2 0x955 JUMP JUMPDEST JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0xE15 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0xE20 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0xE81 JUMPI PUSH2 0xE48 DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x0 DUP8 GT PUSH2 0xEF0 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x43616E6E6F74207374616B652030000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0xB SLOAD PUSH2 0xF03 SWAP1 DUP9 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0xB SSTORE CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0xF26 SWAP1 DUP9 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x3 SLOAD DUP4 MLOAD PUSH32 0xD505ACCF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 DUP2 ADD SWAP4 SWAP1 SWAP4 MSTORE ADDRESS PUSH1 0x24 DUP5 ADD MSTORE PUSH1 0x44 DUP4 ADD DUP12 SWAP1 MSTORE PUSH1 0x64 DUP4 ADD DUP11 SWAP1 MSTORE PUSH1 0xFF DUP10 AND PUSH1 0x84 DUP5 ADD MSTORE PUSH1 0xA4 DUP4 ADD DUP9 SWAP1 MSTORE PUSH1 0xC4 DUP4 ADD DUP8 SWAP1 MSTORE SWAP3 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP4 AND SWAP3 PUSH4 0xD505ACCF SWAP3 PUSH1 0xE4 DUP1 DUP3 ADD SWAP4 SWAP3 SWAP2 DUP3 SWAP1 SUB ADD DUP2 DUP4 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0xFD3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0xFE7 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x3 SLOAD PUSH2 0x1017 SWAP3 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 POP CALLER ADDRESS DUP11 PUSH4 0xFFFFFFFF PUSH2 0x1357 AND JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP9 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0x9E71BC8EEA02A63969F509818F2DAFB9254532904319F9DBDA79B67BD34A5F3D SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0x10BE JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO PUSH2 0x1137 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1E PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x536166654D6174683A207375627472616374696F6E206F766572666C6F770000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP SWAP1 SUB SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH2 0x114C JUMPI POP PUSH1 0x0 PUSH2 0x438 JUMP JUMPDEST DUP3 DUP3 MUL DUP3 DUP5 DUP3 DUP2 PUSH2 0x1159 JUMPI INVALID JUMPDEST DIV EQ PUSH2 0x11B0 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x21 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1637 PUSH1 0x21 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 GT PUSH2 0x1227 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1A PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x536166654D6174683A206469766973696F6E206279207A65726F000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP5 DUP2 PUSH2 0x1232 JUMPI INVALID JUMPDEST DIV SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 ADD DUP4 DUP2 LT ISZERO PUSH2 0x11B0 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1B PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP5 AND PUSH1 0x24 DUP3 ADD MSTORE PUSH1 0x44 DUP1 DUP3 ADD DUP5 SWAP1 MSTORE DUP3 MLOAD DUP1 DUP4 SUB SWAP1 SWAP2 ADD DUP2 MSTORE PUSH1 0x64 SWAP1 SWAP2 ADD SWAP1 SWAP2 MSTORE PUSH1 0x20 DUP2 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xA9059CBB00000000000000000000000000000000000000000000000000000000 OR SWAP1 MSTORE PUSH2 0x133C SWAP1 DUP5 SWAP1 PUSH2 0x13F2 JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP4 LT PUSH2 0x1350 JUMPI DUP2 PUSH2 0x11B0 JUMP JUMPDEST POP SWAP1 SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP6 DUP2 AND PUSH1 0x24 DUP4 ADD MSTORE DUP5 AND PUSH1 0x44 DUP3 ADD MSTORE PUSH1 0x64 DUP1 DUP3 ADD DUP5 SWAP1 MSTORE DUP3 MLOAD DUP1 DUP4 SUB SWAP1 SWAP2 ADD DUP2 MSTORE PUSH1 0x84 SWAP1 SWAP2 ADD SWAP1 SWAP2 MSTORE PUSH1 0x20 DUP2 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x23B872DD00000000000000000000000000000000000000000000000000000000 OR SWAP1 MSTORE PUSH2 0x13EC SWAP1 DUP6 SWAP1 PUSH2 0x13F2 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH2 0x1411 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x1630 JUMP JUMPDEST PUSH2 0x147C JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5361666545524332303A2063616C6C20746F206E6F6E2D636F6E747261637400 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x14E5 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x14A8 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x1547 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x154C JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x15BD JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD DUP2 SWAP1 MSTORE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5361666545524332303A206C6F772D6C6576656C2063616C6C206661696C6564 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST DUP1 MLOAD ISZERO PUSH2 0x13EC JUMPI DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x15D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP MLOAD PUSH2 0x13EC JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1682 PUSH1 0x2A SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST EXTCODESIZE ISZERO ISZERO SWAP1 JUMP INVALID MSTORE8 PUSH2 0x6665 0x4D PUSH2 0x7468 GASPRICE KECCAK256 PUSH14 0x756C7469706C69636174696F6E20 PUSH16 0x766572666C6F7743616C6C6572206973 KECCAK256 PUSH15 0x6F7420526577617264734469737472 PUSH10 0x627574696F6E20636F6E PUSH21 0x726163745361666545524332303A20455243323020 PUSH16 0x7065726174696F6E20646964206E6F74 KECCAK256 PUSH20 0x756363656564A265627A7A72315820F909FA3A09 LT RETURN 0xB2 0x2E SWAP6 PUSH5 0x8CBCA716B0 PUSH7 0x6DAFE47E4B956 PUSH3 0xD41E95 0xD9 SWAP4 LOG4 CALLDATACOPY PUSH5 0x736F6C6343 STOP SDIV LT STOP ORIGIN ",
- "sourceMap": "485:5520:1:-;;;789:1;759:31;;824:1;796:29;;864:7;831:40;;1197:276;8:9:-1;5:2;;;30:1;27;20:12;5:2;1197:276:1;;;;;;;;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1197:276:1;;;;;;;;;;;884:1:16;868:17;;1332:12:1;:36;;-1:-1:-1;1332:36:1;;;-1:-1:-1;1332:36:1;;;;;;;1378:12;:36;;;;;;;;;;;;;;-1:-1:-1;1424:42:1;;;;;;;;;;;;;;;-1:-1:-1;;;;485:5520:1;;;;"
- },
- "deployedBytecode": {
- "linkReferences": {},
- "object": "608060405234801561001057600080fd5b50600436106101815760003560e01c80637b0a47ee116100d8578063cd3daf9d1161008c578063e9fad8ee11610066578063e9fad8ee14610346578063ebe2b12b1461034e578063ecd9ba821461035657610181565b8063cd3daf9d1461032e578063d1af0c7d14610336578063df136d651461033e57610181565b80638b876347116100bd5780638b876347146102d6578063a694fc3a14610309578063c8f33c911461032657610181565b80637b0a47ee146102c657806380faa57d146102ce57610181565b8063386a95251161013a5780633fc6df6e116101145780633fc6df6e1461025a57806370a082311461028b57806372f702f3146102be57610181565b8063386a95251461022d5780633c6b16ab146102355780633d18b9121461025257610181565b806318160ddd1161016b57806318160ddd146101fe5780631c1f78eb146102065780632e1a7d4d1461020e57610181565b80628cc262146101865780630700037d146101cb575b600080fd5b6101b96004803603602081101561019c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661038e565b60408051918252519081900360200190f35b6101b9600480360360208110156101e157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661043e565b6101b9610450565b6101b9610457565b61022b6004803603602081101561022457600080fd5b5035610475565b005b6101b961067d565b61022b6004803603602081101561024b57600080fd5b5035610683565b61022b610955565b610262610acc565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101b9600480360360208110156102a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610ae8565b610262610b10565b6101b9610b2c565b6101b9610b32565b6101b9600480360360208110156102ec57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b40565b61022b6004803603602081101561031f57600080fd5b5035610b52565b6101b9610d57565b6101b9610d5d565b610262610db7565b6101b9610dd3565b61022b610dd9565b6101b9610dfc565b61022b600480360360a081101561036c57600080fd5b5080359060208101359060ff6040820135169060608101359060800135610e02565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a60209081526040808320546009909252822054610438919061042c90670de0b6b3a764000090610420906103ee906103e2610d5d565b9063ffffffff6110c616565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600c60205260409020549063ffffffff61113d16565b9063ffffffff6111b716565b9063ffffffff61123b16565b92915050565b600a6020526000908152604090205481565b600b545b90565b600061047060065460055461113d90919063ffffffff16565b905090565b6001805481019081905533610488610d5d565b600855610493610b32565b60075573ffffffffffffffffffffffffffffffffffffffff8116156104f4576104bb8161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b6000831161056357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43616e6e6f742077697468647261772030000000000000000000000000000000604482015290519081900360640190fd5b600b54610576908463ffffffff6110c616565b600b55336000908152600c6020526040902054610599908463ffffffff6110c616565b336000818152600c60205260409020919091556003546105d29173ffffffffffffffffffffffffffffffffffffffff90911690856112af565b60408051848152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a250600154811461067957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050565b60065481565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611658602a913960400191505060405180910390fd5b60006106fd610d5d565b600855610708610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610769576107308161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b600454421061078e5760065461078690839063ffffffff6111b716565b6005556107dd565b6004546000906107a4904263ffffffff6110c616565b905060006107bd6005548361113d90919063ffffffff16565b6006549091506107d790610420868463ffffffff61123b16565b60055550505b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561084e57600080fd5b505afa158015610862573d6000803e3d6000fd5b505050506040513d602081101561087857600080fd5b505160065490915061089190829063ffffffff6111b716565b600554111561090157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015290519081900360640190fd5b42600781905560065461091a919063ffffffff61123b16565b6004556040805184815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a1505050565b6001805481019081905533610968610d5d565b600855610973610b32565b60075573ffffffffffffffffffffffffffffffffffffffff8116156109d45761099b8161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b336000908152600a60205260409020548015610a5757336000818152600a6020526040812055600254610a209173ffffffffffffffffffffffffffffffffffffffff90911690836112af565b60408051828152905133917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a25b50506001548114610ac957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205490565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60055481565b600061047042600454611341565b60096020526000908152604090205481565b6001805481019081905533610b65610d5d565b600855610b70610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610bd157610b988161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b60008311610c4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610c53908463ffffffff61123b16565b600b55336000908152600c6020526040902054610c76908463ffffffff61123b16565b336000818152600c6020526040902091909155600354610cb09173ffffffffffffffffffffffffffffffffffffffff909116903086611357565b60408051848152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a250600154811461067957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60075481565b6000600b5460001415610d735750600854610454565b610470610da8600b54610420670de0b6b3a7640000610d9c600554610d9c6007546103e2610b32565b9063ffffffff61113d16565b6008549063ffffffff61123b16565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60085481565b336000908152600c6020526040902054610df290610475565b610dfa610955565b565b60045481565b6001805481019081905533610e15610d5d565b600855610e20610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610e8157610e488161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b60008711610ef057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610f03908863ffffffff61123b16565b600b55336000908152600c6020526040902054610f26908863ffffffff61123b16565b336000818152600c60205260408082209390935560035483517fd505accf0000000000000000000000000000000000000000000000000000000081526004810193909352306024840152604483018b9052606483018a905260ff8916608484015260a4830188905260c48301879052925173ffffffffffffffffffffffffffffffffffffffff9093169263d505accf9260e480820193929182900301818387803b158015610fd357600080fd5b505af1158015610fe7573d6000803e3d6000fd5b5050600354611017925073ffffffffffffffffffffffffffffffffffffffff16905033308a63ffffffff61135716565b60408051888152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25060015481146110be57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b60008282111561113757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008261114c57506000610438565b8282028284828161115957fe5b04146111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806116376021913960400191505060405180910390fd5b9392505050565b600080821161122757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161123257fe5b04949350505050565b6000828201838110156111b057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261133c9084906113f2565b505050565b600081831061135057816111b0565b5090919050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526113ec9085906113f2565b50505050565b6114118273ffffffffffffffffffffffffffffffffffffffff16611630565b61147c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106114e557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016114a8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611547576040519150601f19603f3d011682016040523d82523d6000602084013e61154c565b606091505b5091509150816115bd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156113ec578080602001905160208110156115d957600080fd5b50516113ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611682602a913960400191505060405180910390fd5b3b15159056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f742052657761726473446973747269627574696f6e20636f6e74726163745361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72315820f909fa3a0910f3b22e95648cbca716b06606dafe47e4b95662d41e95d993a43764736f6c63430005100032",
- "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x181 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x7B0A47EE GT PUSH2 0xD8 JUMPI DUP1 PUSH4 0xCD3DAF9D GT PUSH2 0x8C JUMPI DUP1 PUSH4 0xE9FAD8EE GT PUSH2 0x66 JUMPI DUP1 PUSH4 0xE9FAD8EE EQ PUSH2 0x346 JUMPI DUP1 PUSH4 0xEBE2B12B EQ PUSH2 0x34E JUMPI DUP1 PUSH4 0xECD9BA82 EQ PUSH2 0x356 JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0xCD3DAF9D EQ PUSH2 0x32E JUMPI DUP1 PUSH4 0xD1AF0C7D EQ PUSH2 0x336 JUMPI DUP1 PUSH4 0xDF136D65 EQ PUSH2 0x33E JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x8B876347 GT PUSH2 0xBD JUMPI DUP1 PUSH4 0x8B876347 EQ PUSH2 0x2D6 JUMPI DUP1 PUSH4 0xA694FC3A EQ PUSH2 0x309 JUMPI DUP1 PUSH4 0xC8F33C91 EQ PUSH2 0x326 JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x7B0A47EE EQ PUSH2 0x2C6 JUMPI DUP1 PUSH4 0x80FAA57D EQ PUSH2 0x2CE JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x386A9525 GT PUSH2 0x13A JUMPI DUP1 PUSH4 0x3FC6DF6E GT PUSH2 0x114 JUMPI DUP1 PUSH4 0x3FC6DF6E EQ PUSH2 0x25A JUMPI DUP1 PUSH4 0x70A08231 EQ PUSH2 0x28B JUMPI DUP1 PUSH4 0x72F702F3 EQ PUSH2 0x2BE JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x386A9525 EQ PUSH2 0x22D JUMPI DUP1 PUSH4 0x3C6B16AB EQ PUSH2 0x235 JUMPI DUP1 PUSH4 0x3D18B912 EQ PUSH2 0x252 JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH4 0x18160DDD GT PUSH2 0x16B JUMPI DUP1 PUSH4 0x18160DDD EQ PUSH2 0x1FE JUMPI DUP1 PUSH4 0x1C1F78EB EQ PUSH2 0x206 JUMPI DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x20E JUMPI PUSH2 0x181 JUMP JUMPDEST DUP1 PUSH3 0x8CC262 EQ PUSH2 0x186 JUMPI DUP1 PUSH4 0x700037D EQ PUSH2 0x1CB JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x19C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x38E JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD SWAP2 DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x1E1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x43E JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0x450 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0x457 JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x224 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0x475 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x1B9 PUSH2 0x67D JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x24B JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0x683 JUMP JUMPDEST PUSH2 0x22B PUSH2 0x955 JUMP JUMPDEST PUSH2 0x262 PUSH2 0xACC JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP3 AND DUP3 MSTORE MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 RETURN JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2A1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0xAE8 JUMP JUMPDEST PUSH2 0x262 PUSH2 0xB10 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xB2C JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xB32 JUMP JUMPDEST PUSH2 0x1B9 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x2EC JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0xB40 JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x31F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP CALLDATALOAD PUSH2 0xB52 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xD57 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xD5D JUMP JUMPDEST PUSH2 0x262 PUSH2 0xDB7 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xDD3 JUMP JUMPDEST PUSH2 0x22B PUSH2 0xDD9 JUMP JUMPDEST PUSH2 0x1B9 PUSH2 0xDFC JUMP JUMPDEST PUSH2 0x22B PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0xA0 DUP2 LT ISZERO PUSH2 0x36C JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 DUP2 ADD CALLDATALOAD SWAP1 PUSH1 0xFF PUSH1 0x40 DUP3 ADD CALLDATALOAD AND SWAP1 PUSH1 0x60 DUP2 ADD CALLDATALOAD SWAP1 PUSH1 0x80 ADD CALLDATALOAD PUSH2 0xE02 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SLOAD PUSH1 0x9 SWAP1 SWAP3 MSTORE DUP3 KECCAK256 SLOAD PUSH2 0x438 SWAP2 SWAP1 PUSH2 0x42C SWAP1 PUSH8 0xDE0B6B3A7640000 SWAP1 PUSH2 0x420 SWAP1 PUSH2 0x3EE SWAP1 PUSH2 0x3E2 PUSH2 0xD5D JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP9 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x113D AND JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x11B7 AND JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0xA PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0xB SLOAD JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x470 PUSH1 0x6 SLOAD PUSH1 0x5 SLOAD PUSH2 0x113D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST SWAP1 POP SWAP1 JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0x488 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0x493 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0x4F4 JUMPI PUSH2 0x4BB DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x0 DUP4 GT PUSH2 0x563 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x11 PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x43616E6E6F742077697468647261772030000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0xB SLOAD PUSH2 0x576 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST PUSH1 0xB SSTORE CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0x599 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SWAP2 SWAP1 SWAP2 SSTORE PUSH1 0x3 SLOAD PUSH2 0x5D2 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 DUP6 PUSH2 0x12AF JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0x7084F5476618D8E60B11EF0D7D3F06914655ADB8793E28FF7F018D4C76D505D5 SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0x679 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP POP JUMP JUMPDEST PUSH1 0x6 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND CALLER EQ PUSH2 0x6F3 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1658 PUSH1 0x2A SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH2 0x6FD PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0x708 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0x769 JUMPI PUSH2 0x730 DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x4 SLOAD TIMESTAMP LT PUSH2 0x78E JUMPI PUSH1 0x6 SLOAD PUSH2 0x786 SWAP1 DUP4 SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x11B7 AND JUMP JUMPDEST PUSH1 0x5 SSTORE PUSH2 0x7DD JUMP JUMPDEST PUSH1 0x4 SLOAD PUSH1 0x0 SWAP1 PUSH2 0x7A4 SWAP1 TIMESTAMP PUSH4 0xFFFFFFFF PUSH2 0x10C6 AND JUMP JUMPDEST SWAP1 POP PUSH1 0x0 PUSH2 0x7BD PUSH1 0x5 SLOAD DUP4 PUSH2 0x113D SWAP1 SWAP2 SWAP1 PUSH4 0xFFFFFFFF AND JUMP JUMPDEST PUSH1 0x6 SLOAD SWAP1 SWAP2 POP PUSH2 0x7D7 SWAP1 PUSH2 0x420 DUP7 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0x5 SSTORE POP POP JUMPDEST PUSH1 0x2 SLOAD PUSH1 0x40 DUP1 MLOAD PUSH32 0x70A0823100000000000000000000000000000000000000000000000000000000 DUP2 MSTORE ADDRESS PUSH1 0x4 DUP3 ADD MSTORE SWAP1 MLOAD PUSH1 0x0 SWAP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP2 PUSH4 0x70A08231 SWAP2 PUSH1 0x24 DUP1 DUP4 ADD SWAP3 PUSH1 0x20 SWAP3 SWAP2 SWAP1 DUP3 SWAP1 SUB ADD DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0x84E JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x862 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP PUSH1 0x40 MLOAD RETURNDATASIZE PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x878 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP MLOAD PUSH1 0x6 SLOAD SWAP1 SWAP2 POP PUSH2 0x891 SWAP1 DUP3 SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x11B7 AND JUMP JUMPDEST PUSH1 0x5 SLOAD GT ISZERO PUSH2 0x901 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x18 PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x50726F76696465642072657761726420746F6F20686967680000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST TIMESTAMP PUSH1 0x7 DUP2 SWAP1 SSTORE PUSH1 0x6 SLOAD PUSH2 0x91A SWAP2 SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0x4 SSTORE PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD PUSH32 0xDE88A922E0D3B88B24E9623EFEB464919C6BF9F66857A65E2BFCF2CE87A9433D SWAP2 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG1 POP POP POP JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0x968 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0x973 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0x9D4 JUMPI PUSH2 0x99B DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP1 ISZERO PUSH2 0xA57 JUMPI CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 MSTORE PUSH1 0x40 DUP2 KECCAK256 SSTORE PUSH1 0x2 SLOAD PUSH2 0xA20 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 DUP4 PUSH2 0x12AF JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP3 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0xE2403640BA68FED3A2F88B7557551D1993F84B99BB10FF833F0CF8DB0C5E0486 SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 JUMPDEST POP POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0xAC9 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP JUMP JUMPDEST PUSH1 0x0 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD SWAP1 JUMP JUMPDEST PUSH1 0x3 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x5 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH2 0x470 TIMESTAMP PUSH1 0x4 SLOAD PUSH2 0x1341 JUMP JUMPDEST PUSH1 0x9 PUSH1 0x20 MSTORE PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0xB65 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0xB70 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0xBD1 JUMPI PUSH2 0xB98 DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x0 DUP4 GT PUSH2 0xC40 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x43616E6E6F74207374616B652030000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0xB SLOAD PUSH2 0xC53 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0xB SSTORE CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0xC76 SWAP1 DUP5 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SWAP2 SWAP1 SWAP2 SSTORE PUSH1 0x3 SLOAD PUSH2 0xCB0 SWAP2 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP2 AND SWAP1 ADDRESS DUP7 PUSH2 0x1357 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP5 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0x9E71BC8EEA02A63969F509818F2DAFB9254532904319F9DBDA79B67BD34A5F3D SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0x679 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x7 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x0 PUSH1 0xB SLOAD PUSH1 0x0 EQ ISZERO PUSH2 0xD73 JUMPI POP PUSH1 0x8 SLOAD PUSH2 0x454 JUMP JUMPDEST PUSH2 0x470 PUSH2 0xDA8 PUSH1 0xB SLOAD PUSH2 0x420 PUSH8 0xDE0B6B3A7640000 PUSH2 0xD9C PUSH1 0x5 SLOAD PUSH2 0xD9C PUSH1 0x7 SLOAD PUSH2 0x3E2 PUSH2 0xB32 JUMP JUMPDEST SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x113D AND JUMP JUMPDEST PUSH1 0x8 SLOAD SWAP1 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0x2 SLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP2 JUMP JUMPDEST PUSH1 0x8 SLOAD DUP2 JUMP JUMPDEST CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0xDF2 SWAP1 PUSH2 0x475 JUMP JUMPDEST PUSH2 0xDFA PUSH2 0x955 JUMP JUMPDEST JUMP JUMPDEST PUSH1 0x4 SLOAD DUP2 JUMP JUMPDEST PUSH1 0x1 DUP1 SLOAD DUP2 ADD SWAP1 DUP2 SWAP1 SSTORE CALLER PUSH2 0xE15 PUSH2 0xD5D JUMP JUMPDEST PUSH1 0x8 SSTORE PUSH2 0xE20 PUSH2 0xB32 JUMP JUMPDEST PUSH1 0x7 SSTORE PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND ISZERO PUSH2 0xE81 JUMPI PUSH2 0xE48 DUP2 PUSH2 0x38E JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP3 AND PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xA PUSH1 0x20 SWAP1 DUP2 MSTORE PUSH1 0x40 DUP1 DUP4 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x8 SLOAD PUSH1 0x9 SWAP1 SWAP2 MSTORE SWAP2 SWAP1 KECCAK256 SSTORE JUMPDEST PUSH1 0x0 DUP8 GT PUSH2 0xEF0 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0xE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x43616E6E6F74207374616B652030000000000000000000000000000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0xB SLOAD PUSH2 0xF03 SWAP1 DUP9 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST PUSH1 0xB SSTORE CALLER PUSH1 0x0 SWAP1 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 SWAP1 KECCAK256 SLOAD PUSH2 0xF26 SWAP1 DUP9 PUSH4 0xFFFFFFFF PUSH2 0x123B AND JUMP JUMPDEST CALLER PUSH1 0x0 DUP2 DUP2 MSTORE PUSH1 0xC PUSH1 0x20 MSTORE PUSH1 0x40 DUP1 DUP3 KECCAK256 SWAP4 SWAP1 SWAP4 SSTORE PUSH1 0x3 SLOAD DUP4 MLOAD PUSH32 0xD505ACCF00000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 DUP2 ADD SWAP4 SWAP1 SWAP4 MSTORE ADDRESS PUSH1 0x24 DUP5 ADD MSTORE PUSH1 0x44 DUP4 ADD DUP12 SWAP1 MSTORE PUSH1 0x64 DUP4 ADD DUP11 SWAP1 MSTORE PUSH1 0xFF DUP10 AND PUSH1 0x84 DUP5 ADD MSTORE PUSH1 0xA4 DUP4 ADD DUP9 SWAP1 MSTORE PUSH1 0xC4 DUP4 ADD DUP8 SWAP1 MSTORE SWAP3 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP1 SWAP4 AND SWAP3 PUSH4 0xD505ACCF SWAP3 PUSH1 0xE4 DUP1 DUP3 ADD SWAP4 SWAP3 SWAP2 DUP3 SWAP1 SUB ADD DUP2 DUP4 DUP8 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH2 0xFD3 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS CALL ISZERO DUP1 ISZERO PUSH2 0xFE7 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x3 SLOAD PUSH2 0x1017 SWAP3 POP PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND SWAP1 POP CALLER ADDRESS DUP11 PUSH4 0xFFFFFFFF PUSH2 0x1357 AND JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP9 DUP2 MSTORE SWAP1 MLOAD CALLER SWAP2 PUSH32 0x9E71BC8EEA02A63969F509818F2DAFB9254532904319F9DBDA79B67BD34A5F3D SWAP2 SWAP1 DUP2 SWAP1 SUB PUSH1 0x20 ADD SWAP1 LOG2 POP PUSH1 0x1 SLOAD DUP2 EQ PUSH2 0x10BE JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5265656E7472616E637947756172643A207265656E7472616E742063616C6C00 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 GT ISZERO PUSH2 0x1137 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1E PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x536166654D6174683A207375627472616374696F6E206F766572666C6F770000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST POP SWAP1 SUB SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH2 0x114C JUMPI POP PUSH1 0x0 PUSH2 0x438 JUMP JUMPDEST DUP3 DUP3 MUL DUP3 DUP5 DUP3 DUP2 PUSH2 0x1159 JUMPI INVALID JUMPDEST DIV EQ PUSH2 0x11B0 JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x21 DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1637 PUSH1 0x21 SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 GT PUSH2 0x1227 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1A PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x536166654D6174683A206469766973696F6E206279207A65726F000000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x0 DUP3 DUP5 DUP2 PUSH2 0x1232 JUMPI INVALID JUMPDEST DIV SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 DUP3 ADD DUP4 DUP2 LT ISZERO PUSH2 0x11B0 JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1B PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x536166654D6174683A206164646974696F6E206F766572666C6F770000000000 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP5 AND PUSH1 0x24 DUP3 ADD MSTORE PUSH1 0x44 DUP1 DUP3 ADD DUP5 SWAP1 MSTORE DUP3 MLOAD DUP1 DUP4 SUB SWAP1 SWAP2 ADD DUP2 MSTORE PUSH1 0x64 SWAP1 SWAP2 ADD SWAP1 SWAP2 MSTORE PUSH1 0x20 DUP2 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0xA9059CBB00000000000000000000000000000000000000000000000000000000 OR SWAP1 MSTORE PUSH2 0x133C SWAP1 DUP5 SWAP1 PUSH2 0x13F2 JUMP JUMPDEST POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 DUP4 LT PUSH2 0x1350 JUMPI DUP2 PUSH2 0x11B0 JUMP JUMPDEST POP SWAP1 SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP6 DUP2 AND PUSH1 0x24 DUP4 ADD MSTORE DUP5 AND PUSH1 0x44 DUP3 ADD MSTORE PUSH1 0x64 DUP1 DUP3 ADD DUP5 SWAP1 MSTORE DUP3 MLOAD DUP1 DUP4 SUB SWAP1 SWAP2 ADD DUP2 MSTORE PUSH1 0x84 SWAP1 SWAP2 ADD SWAP1 SWAP2 MSTORE PUSH1 0x20 DUP2 ADD DUP1 MLOAD PUSH28 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x23B872DD00000000000000000000000000000000000000000000000000000000 OR SWAP1 MSTORE PUSH2 0x13EC SWAP1 DUP6 SWAP1 PUSH2 0x13F2 JUMP JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH2 0x1411 DUP3 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH2 0x1630 JUMP JUMPDEST PUSH2 0x147C JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD MSTORE PUSH1 0x1F PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5361666545524332303A2063616C6C20746F206E6F6E2D636F6E747261637400 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP4 PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND DUP4 PUSH1 0x40 MLOAD DUP1 DUP3 DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 JUMPDEST PUSH1 0x20 DUP4 LT PUSH2 0x14E5 JUMPI DUP1 MLOAD DUP3 MSTORE PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 SWAP1 SWAP3 ADD SWAP2 PUSH1 0x20 SWAP2 DUP3 ADD SWAP2 ADD PUSH2 0x14A8 JUMP JUMPDEST PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB DUP1 NOT DUP3 MLOAD AND DUP2 DUP5 MLOAD AND DUP1 DUP3 OR DUP6 MSTORE POP POP POP POP POP POP SWAP1 POP ADD SWAP2 POP POP PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 PUSH1 0x0 DUP7 GAS CALL SWAP2 POP POP RETURNDATASIZE DUP1 PUSH1 0x0 DUP2 EQ PUSH2 0x1547 JUMPI PUSH1 0x40 MLOAD SWAP2 POP PUSH1 0x1F NOT PUSH1 0x3F RETURNDATASIZE ADD AND DUP3 ADD PUSH1 0x40 MSTORE RETURNDATASIZE DUP3 MSTORE RETURNDATASIZE PUSH1 0x0 PUSH1 0x20 DUP5 ADD RETURNDATACOPY PUSH2 0x154C JUMP JUMPDEST PUSH1 0x60 SWAP2 POP JUMPDEST POP SWAP2 POP SWAP2 POP DUP2 PUSH2 0x15BD JUMPI PUSH1 0x40 DUP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x20 PUSH1 0x4 DUP3 ADD DUP2 SWAP1 MSTORE PUSH1 0x24 DUP3 ADD MSTORE PUSH32 0x5361666545524332303A206C6F772D6C6576656C2063616C6C206661696C6564 PUSH1 0x44 DUP3 ADD MSTORE SWAP1 MLOAD SWAP1 DUP2 SWAP1 SUB PUSH1 0x64 ADD SWAP1 REVERT JUMPDEST DUP1 MLOAD ISZERO PUSH2 0x13EC JUMPI DUP1 DUP1 PUSH1 0x20 ADD SWAP1 MLOAD PUSH1 0x20 DUP2 LT ISZERO PUSH2 0x15D9 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP MLOAD PUSH2 0x13EC JUMPI PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE PUSH1 0x2A DUP2 MSTORE PUSH1 0x20 ADD DUP1 PUSH2 0x1682 PUSH1 0x2A SWAP2 CODECOPY PUSH1 0x40 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST EXTCODESIZE ISZERO ISZERO SWAP1 JUMP INVALID MSTORE8 PUSH2 0x6665 0x4D PUSH2 0x7468 GASPRICE KECCAK256 PUSH14 0x756C7469706C69636174696F6E20 PUSH16 0x766572666C6F7743616C6C6572206973 KECCAK256 PUSH15 0x6F7420526577617264734469737472 PUSH10 0x627574696F6E20636F6E PUSH21 0x726163745361666545524332303A20455243323020 PUSH16 0x7065726174696F6E20646964206E6F74 KECCAK256 PUSH20 0x756363656564A265627A7A72315820F909FA3A09 LT RETURN 0xB2 0x2E SWAP6 PUSH5 0x8CBCA716B0 PUSH7 0x6DAFE47E4B956 PUSH3 0xD41E95 0xD9 SWAP4 LOG4 CALLDATACOPY PUSH5 0x736F6C6343 STOP SDIV LT STOP ORIGIN ",
- "sourceMap": "485:5520:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;485:5520:1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2194:196;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2194:196:1;;;;:::i;:::-;;;;;;;;;;;;;;;;1017:42;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1017:42:1;;;;:::i;1518:91::-;;;:::i;2396:119::-;;;:::i;3496:351::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3496:351:1;;:::i;:::-;;831:40;;;:::i;4313:1064::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;4313:1064:1;;:::i;3853:300::-;;;:::i;70:34:0:-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1615:110:1;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1615:110:1;;;;:::i;727:26::-;;;:::i;796:29::-;;;:::i;1731:129::-;;;:::i;954:57::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;954:57:1;;;;:::i;3127:363::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3127:363:1;;:::i;877:29::-;;;:::i;1866:322::-;;;:::i;695:26::-;;;:::i;912:35::-;;;:::i;4159:94::-;;;:::i;759:31::-;;;:::i;2573:548::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;2573:548:1;;;;;;;;;;;;;;;;;;;;;;;;:::i;2194:196::-;2366:16;;;2248:7;2366:16;;;:7;:16;;;;;;;;;2318:22;:31;;;;;;2274:109;;2366:16;2274:87;;2356:4;;2274:77;;2297:53;;:16;:14;:16::i;:::-;:20;:53;:20;:53;:::i;:::-;2274:18;;;;;;;:9;:18;;;;;;;:77;:22;:77;:::i;:::-;:81;:87;:81;:87;:::i;:::-;:91;:109;:91;:109;:::i;:::-;2267:116;2194:196;-1:-1:-1;;2194:196:1:o;1017:42::-;;;;;;;;;;;;;:::o;1518:91::-;1590:12;;1518:91;;:::o;2396:119::-;2451:7;2477:31;2492:15;;2477:10;;:14;;:31;;;;:::i;:::-;2470:38;;2396:119;:::o;3496:351::-;1318:1:16;1301:18;;;;;;;;3563:10:1;5498:16;:14;:16::i;:::-;5475:20;:39;5541:26;:24;:26::i;:::-;5524:14;:43;5581:21;;;;5577:154;;5637:15;5644:7;5637:6;:15::i;:::-;5618:16;;;;;;;:7;:16;;;;;;;;:34;;;;5700:20;;5666:22;:31;;;;;;:54;5577:154;3602:1;3593:6;:10;3585:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3650:12;;:24;;3667:6;3650:24;:16;:24;:::i;:::-;3635:12;:39;3718:10;3708:21;;;;:9;:21;;;;;;:33;;3734:6;3708:33;:25;:33;:::i;:::-;3694:10;3684:21;;;;:9;:21;;;;;:57;;;;3751:12;;:45;;3684:21;3751:12;;;;3789:6;3751:25;:45::i;:::-;3811:29;;;;;;;;3821:10;;3811:29;;;;;;;;;;1375:1:16;1410:13;;1394:12;:29;1386:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3496:351:1;;:::o;831:40::-;;;;:::o;4313:1064::-;237:19:0;;;;223:10;:33;215:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4411:1:1;5498:16;:14;:16::i;:::-;5475:20;:39;5541:26;:24;:26::i;:::-;5524:14;:43;5581:21;;;;5577:154;;5637:15;5644:7;5637:6;:15::i;:::-;5618:16;;;;;;;:7;:16;;;;;;;;:34;;;;5700:20;;5666:22;:31;;;;;;:54;5577:154;4448:12;;4429:15;:31;4425:312;;4500:15;;4489:27;;:6;;:27;:10;:27;:::i;:::-;4476:10;:40;4425:312;;;4567:12;;4547:17;;4567:33;;4584:15;4567:33;:16;:33;:::i;:::-;4547:53;;4614:16;4633:25;4647:10;;4633:9;:13;;:25;;;;:::i;:::-;4710:15;;4614:44;;-1:-1:-1;4685:41:1;;:20;:6;4614:44;4685:20;:10;:20;:::i;:41::-;4672:10;:54;-1:-1:-1;;4425:312:1;5106:12;;:37;;;;;;5137:4;5106:37;;;;;;5091:12;;5106;;;:22;;:37;;;;;;;;;;;;;;:12;:37;;;5:2:-1;;;;30:1;27;20:12;5:2;5106:37:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5106:37:1;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5106:37:1;5187:15;;5106:37;;-1:-1:-1;5175:28:1;;5106:37;;5175:28;:11;:28;:::i;:::-;5161:10;;:42;;5153:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5260:15;5243:14;:32;;;5320:15;;5300:36;;5260:15;5300:36;:19;:36;:::i;:::-;5285:12;:51;5351:19;;;;;;;;;;;;;;;;;5740:1;313::0;4313:1064:1;:::o;3853:300::-;1318:1:16;1301:18;;;;;;;;3907:10:1;5498:16;:14;:16::i;:::-;5475:20;:39;5541:26;:24;:26::i;:::-;5524:14;:43;5581:21;;;;5577:154;;5637:15;5644:7;5637:6;:15::i;:::-;5618:16;;;;;;;:7;:16;;;;;;;;:34;;;;5700:20;;5666:22;:31;;;;;;:54;5577:154;3954:10;3929:14;3946:19;;;:7;:19;;;;;;3979:10;;3975:172;;4013:10;4027:1;4005:19;;;:7;:19;;;;;:23;4042:12;;:45;;4005:19;4042:12;;;;4080:6;4042:25;:45::i;:::-;4106:30;;;;;;;;4117:10;;4106:30;;;;;;;;;;3975:172;5740:1;1375::16;1410:13;;1394:12;:29;1386:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3853:300:1;:::o;70:34:0:-;;;;;;:::o;1615:110:1:-;1700:18;;1674:7;1700:18;;;:9;:18;;;;;;;1615:110::o;727:26::-;;;;;;:::o;796:29::-;;;;:::o;1731:129::-;1788:7;1814:39;1823:15;1840:12;;1814:8;:39::i;954:57::-;;;;;;;;;;;;;:::o;3127:363::-;1318:1:16;1301:18;;;;;;;;3193:10:1;5498:16;:14;:16::i;:::-;5475:20;:39;5541:26;:24;:26::i;:::-;5524:14;:43;5581:21;;;;5577:154;;5637:15;5644:7;5637:6;:15::i;:::-;5618:16;;;;;;;:7;:16;;;;;;;;:34;;;;5700:20;;5666:22;:31;;;;;;:54;5577:154;3232:1;3223:6;:10;3215:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3277:12;;:24;;3294:6;3277:24;:16;:24;:::i;:::-;3262:12;:39;3345:10;3335:21;;;;:9;:21;;;;;;:33;;3361:6;3335:33;:25;:33;:::i;:::-;3321:10;3311:21;;;;:9;:21;;;;;:57;;;;3378:12;;:64;;3311:21;3378:12;;;;3428:4;3435:6;3378:29;:64::i;:::-;3457:26;;;;;;;;3464:10;;3457:26;;;;;;;;;;1375:1:16;1410:13;;1394:12;:29;1386:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;877:29:1;;;;:::o;1866:322::-;1913:7;1936:12;;1952:1;1936:17;1932:75;;;-1:-1:-1;1976:20:1;;1969:27;;1932:75;2035:146;2077:90;2154:12;;2077:72;2144:4;2077:62;2128:10;;2077:46;2108:14;;2077:26;:24;:26::i;:46::-;:50;:62;:50;:62;:::i;:90::-;2035:20;;;:146;:24;:146;:::i;695:26::-;;;;;;:::o;912:35::-;;;;:::o;4159:94::-;4213:10;4203:21;;;;:9;:21;;;;;;4194:31;;:8;:31::i;:::-;4235:11;:9;:11::i;:::-;4159:94::o;759:31::-;;;;:::o;2573:548::-;1318:1:16;1301:18;;;;;;;;2695:10:1;5498:16;:14;:16::i;:::-;5475:20;:39;5541:26;:24;:26::i;:::-;5524:14;:43;5581:21;;;;5577:154;;5637:15;5644:7;5637:6;:15::i;:::-;5618:16;;;;;;;:7;:16;;;;;;;;:34;;;;5700:20;;5666:22;:31;;;;;;:54;5577:154;2734:1;2725:6;:10;2717:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2779:12;;:24;;2796:6;2779:24;:16;:24;:::i;:::-;2764:12;:39;2847:10;2837:21;;;;:9;:21;;;;;;:33;;2863:6;2837:33;:25;:33;:::i;:::-;2823:10;2813:21;;;;:9;:21;;;;;;:57;;;;2923:12;;2899:99;;;;;;;;;;;;2965:4;2899:99;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2813:21;2923:12;;;;2899:45;;:99;;;;;2813:21;2899:99;;;;;;2813:21;2923:12;2899:99;;;5:2:-1;;;;30:1;27;20:12;5:2;2899:99:1;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;3009:12:1;;:64;;-1:-1:-1;3009:12:1;;;-1:-1:-1;3039:10:1;3059:4;3066:6;3009:64;:29;:64;:::i;:::-;3088:26;;;;;;;;3095:10;;3088:26;;;;;;;;;;1375:1:16;1410:13;;1394:12;:29;1386:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2573:548:1;;;;;;:::o;1274:179:8:-;1332:7;1364:1;1359;:6;;1351:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1422:5:8;;;1274:179::o;1693:458::-;1751:7;1991:6;1987:45;;-1:-1:-1;2020:1:8;2013:8;;1987:45;2054:5;;;2058:1;2054;:5;:1;2077:5;;;;;:10;2069:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2143:1;1693:458;-1:-1:-1;;;1693:458:8:o;2606:326::-;2664:7;2761:1;2757;:5;2749:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2803:9;2819:1;2815;:5;;;;;;;2606:326;-1:-1:-1;;;;2606:326:8:o;834:176::-;892:7;923:5;;;946:6;;;;938:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;662:174:14;770:58;;;793:14;770:58;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;770:58:14;;;;;;;;25:18:-1;;61:17;;770:58:14;182:15:-1;793:23:14;179:29:-1;160:49;;744:85:14;;763:5;;744:18;:85::i;:::-;662:174;;;:::o;358:104:7:-;416:7;446:1;442;:5;:13;;454:1;442:13;;;-1:-1:-1;450:1:7;;435:20;-1:-1:-1;358:104:7:o;842:202:14:-;968:68;;;991:18;968:68;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;968:68:14;;;;;;;;25:18:-1;;61:17;;968:68:14;182:15:-1;991:27:14;179:29:-1;160:49;;942:95:14;;961:5;;942:18;:95::i;:::-;842:202;;;;:::o;2621:1095::-;3216:27;3224:5;3216:25;;;:27::i;:::-;3208:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3350:12;3364:23;3399:5;3391:19;;3411:4;3391:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;139:12;;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;3391:25:14;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;3349:67:14;;;;3434:7;3426:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3493:17;;:21;3489:221;;3633:10;3622:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;3622:30:14;3614:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;542:413:15;902:20;940:8;;;542:413::o"
- }
- },
- "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardsDistribution\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_rewardsToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_stakingToken\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"name\":\"RewardAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"name\":\"RewardPaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Staked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"earned\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"exit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getReward\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getRewardForDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"lastTimeRewardApplicable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"lastUpdateTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"}],\"name\":\"notifyRewardAmount\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"periodFinish\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardPerTokenStored\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardsDistribution\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardsDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardsToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"stake\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"stakeWithPermit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"stakingToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userRewardPerTokenPaid\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"contracts/StakingRewards.sol\":\"StakingRewards\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"contracts/RewardsDistributionRecipient.sol\":{\"keccak256\":\"0xebea058941ff78622282c57efa04f6727ced1375a52e403b600c033ca7954973\",\"urls\":[\"bzz-raw://1c93d3853b4f30b4918048c550450cc2d6b9331961325de1dd095843ec74335f\",\"dweb:/ipfs/QmPERrLjbxT5zGnENNGVUgMWbo1wiGpXKRTtxDjN1dq5m5\"]},\"contracts/StakingRewards.sol\":{\"keccak256\":\"0x83f0cba6c751fd04d0d59c1261b706e32a802e47f6f288f07ec5e5c55058a14f\",\"urls\":[\"bzz-raw://2c0ff0badbeccfa5730d99e2e413202d217be98ad2394a732b45bf3244ceb318\",\"dweb:/ipfs/QmeCsnoRP6c8Sn93hsM6K5GD6yZJt2HWcUwy6NCsKTscWs\"]},\"contracts/interfaces/IStakingRewards.sol\":{\"keccak256\":\"0xc44170af419f2c3372ea279c4d145f19931fcfcdcb7cc3e65f38c087e50a951a\",\"urls\":[\"bzz-raw://1afec57ee670b8f6772924850e3baf0a6d523e928aea4a985473625038225875\",\"dweb:/ipfs/QmZMdXzHJPKAtFa4mMZx1Fa35r2EJEWgAmN58Ks6pwMuj5\"]},\"openzeppelin-solidity-2.3.0/contracts/math/Math.sol\":{\"keccak256\":\"0x4b5aa451e4e8801478708f94b118a7821c0500d676255eaf89fc78c14856ce4e\",\"urls\":[\"bzz-raw://bed15b3f35ed05505efc8fb5cb01d06c52230fbcaadf4ed24a85b1ac2f15f33c\",\"dweb:/ipfs/QmS6tW81u8E4tvzVfVuqEuMCkdwAozQ6pKJPRBR4JEVmQp\"]},\"openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol\":{\"keccak256\":\"0x4ccf2d7b51873db1ccfd54ca2adae5eac3b184f9699911ed4490438419f1c690\",\"urls\":[\"bzz-raw://d62d769b2219d5de39013093412623e624fa887f871826ea3bae6052ee893610\",\"dweb:/ipfs/QmV3yVktya1s617QmuzQR2CfuJgUi3dR2xEZY9ecmqZ2G1\"]},\"openzeppelin-solidity-2.3.0/contracts/token/ERC20/ERC20Detailed.sol\":{\"keccak256\":\"0xc61b3603089b09a730d8ca72e9133a496cc4405da40e9b87c12f073245d774bf\",\"urls\":[\"bzz-raw://de8bb0003d53de236913f0e0102e7a9d015e02098f2495edd000f207fe2be2f4\",\"dweb:/ipfs/QmbtwNwAJEehWWL7yGGyyMoenQvcqtz91pqLgQPpLRoLYC\"]},\"openzeppelin-solidity-2.3.0/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x90e8c2521653bbb1768b05889c5760031e688d9cd361f167489b89215e201b95\",\"urls\":[\"bzz-raw://d0abb99bb8bfc2bc0a89902b8ed1dc0442ad08cc78cee64c291b3df6a27bcccc\",\"dweb:/ipfs/QmP5NaEwZthQeM2ESz4WTT3osrP7jhbvu7ocbttBi2JAw6\"]},\"openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol\":{\"keccak256\":\"0xf6f89424e17870561dc23c5933c55c5726b66a68d51ad2a2c00c569a5f02f507\",\"urls\":[\"bzz-raw://005657a7ffbf6d12726ac0167b55be965dc473d43f061b605f883a54cc00ab4f\",\"dweb:/ipfs/QmaBzyvDQyNnn6DXQYewEtN9Go85orikSnW9PwNWqUGPEX\"]},\"openzeppelin-solidity-2.3.0/contracts/utils/Address.sol\":{\"keccak256\":\"0xf3358e5819ca73357abd6c90bdfffd0474af54364897f6b3e3234c4b71fbe9a1\",\"urls\":[\"bzz-raw://75ae8d04454d1511a2ed986cc8585736f05c5c25280683b3d24712a9f414a4bf\",\"dweb:/ipfs/Qmb3kNCoBUZdah1AgBBD4zMk898j5Qw8ahT1w5cCMYp5Y3\"]},\"openzeppelin-solidity-2.3.0/contracts/utils/ReentrancyGuard.sol\":{\"keccak256\":\"0x0441ff2b36d503f3a29d28d3754291f119064f4973d5c780698143d919037a78\",\"urls\":[\"bzz-raw://af27dd68d2371e68c8ed8cf297ec6d832bf906742d53367b70399ba918060cb7\",\"dweb:/ipfs/QmcMMjZceFepXgRrzSx577oWwt7SCSFzoqZiTF7tTxquF7\"]}},\"version\":1}",
- "bytecode": "608060405260006004556000600555624f1a0060065534801561002157600080fd5b506040516117853803806117858339818101604052606081101561004457600080fd5b508051602082015160409092015160018055600280546001600160a01b039485166001600160a01b0319918216179091556003805492851692821692909217909155600080549390921692169190911790556116e0806100a56000396000f3fe608060405234801561001057600080fd5b50600436106101815760003560e01c80637b0a47ee116100d8578063cd3daf9d1161008c578063e9fad8ee11610066578063e9fad8ee14610346578063ebe2b12b1461034e578063ecd9ba821461035657610181565b8063cd3daf9d1461032e578063d1af0c7d14610336578063df136d651461033e57610181565b80638b876347116100bd5780638b876347146102d6578063a694fc3a14610309578063c8f33c911461032657610181565b80637b0a47ee146102c657806380faa57d146102ce57610181565b8063386a95251161013a5780633fc6df6e116101145780633fc6df6e1461025a57806370a082311461028b57806372f702f3146102be57610181565b8063386a95251461022d5780633c6b16ab146102355780633d18b9121461025257610181565b806318160ddd1161016b57806318160ddd146101fe5780631c1f78eb146102065780632e1a7d4d1461020e57610181565b80628cc262146101865780630700037d146101cb575b600080fd5b6101b96004803603602081101561019c57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661038e565b60408051918252519081900360200190f35b6101b9600480360360208110156101e157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661043e565b6101b9610450565b6101b9610457565b61022b6004803603602081101561022457600080fd5b5035610475565b005b6101b961067d565b61022b6004803603602081101561024b57600080fd5b5035610683565b61022b610955565b610262610acc565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b6101b9600480360360208110156102a157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610ae8565b610262610b10565b6101b9610b2c565b6101b9610b32565b6101b9600480360360208110156102ec57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610b40565b61022b6004803603602081101561031f57600080fd5b5035610b52565b6101b9610d57565b6101b9610d5d565b610262610db7565b6101b9610dd3565b61022b610dd9565b6101b9610dfc565b61022b600480360360a081101561036c57600080fd5b5080359060208101359060ff6040820135169060608101359060800135610e02565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600a60209081526040808320546009909252822054610438919061042c90670de0b6b3a764000090610420906103ee906103e2610d5d565b9063ffffffff6110c616565b73ffffffffffffffffffffffffffffffffffffffff88166000908152600c60205260409020549063ffffffff61113d16565b9063ffffffff6111b716565b9063ffffffff61123b16565b92915050565b600a6020526000908152604090205481565b600b545b90565b600061047060065460055461113d90919063ffffffff16565b905090565b6001805481019081905533610488610d5d565b600855610493610b32565b60075573ffffffffffffffffffffffffffffffffffffffff8116156104f4576104bb8161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b6000831161056357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f43616e6e6f742077697468647261772030000000000000000000000000000000604482015290519081900360640190fd5b600b54610576908463ffffffff6110c616565b600b55336000908152600c6020526040902054610599908463ffffffff6110c616565b336000818152600c60205260409020919091556003546105d29173ffffffffffffffffffffffffffffffffffffffff90911690856112af565b60408051848152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a250600154811461067957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050565b60065481565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611658602a913960400191505060405180910390fd5b60006106fd610d5d565b600855610708610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610769576107308161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b600454421061078e5760065461078690839063ffffffff6111b716565b6005556107dd565b6004546000906107a4904263ffffffff6110c616565b905060006107bd6005548361113d90919063ffffffff16565b6006549091506107d790610420868463ffffffff61123b16565b60055550505b600254604080517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152905160009273ffffffffffffffffffffffffffffffffffffffff16916370a08231916024808301926020929190829003018186803b15801561084e57600080fd5b505afa158015610862573d6000803e3d6000fd5b505050506040513d602081101561087857600080fd5b505160065490915061089190829063ffffffff6111b716565b600554111561090157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f50726f76696465642072657761726420746f6f20686967680000000000000000604482015290519081900360640190fd5b42600781905560065461091a919063ffffffff61123b16565b6004556040805184815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a1505050565b6001805481019081905533610968610d5d565b600855610973610b32565b60075573ffffffffffffffffffffffffffffffffffffffff8116156109d45761099b8161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b336000908152600a60205260409020548015610a5757336000818152600a6020526040812055600254610a209173ffffffffffffffffffffffffffffffffffffffff90911690836112af565b60408051828152905133917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a25b50506001548114610ac957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b73ffffffffffffffffffffffffffffffffffffffff166000908152600c602052604090205490565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60055481565b600061047042600454611341565b60096020526000908152604090205481565b6001805481019081905533610b65610d5d565b600855610b70610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610bd157610b988161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b60008311610c4057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610c53908463ffffffff61123b16565b600b55336000908152600c6020526040902054610c76908463ffffffff61123b16565b336000818152600c6020526040902091909155600354610cb09173ffffffffffffffffffffffffffffffffffffffff909116903086611357565b60408051848152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a250600154811461067957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60075481565b6000600b5460001415610d735750600854610454565b610470610da8600b54610420670de0b6b3a7640000610d9c600554610d9c6007546103e2610b32565b9063ffffffff61113d16565b6008549063ffffffff61123b16565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60085481565b336000908152600c6020526040902054610df290610475565b610dfa610955565b565b60045481565b6001805481019081905533610e15610d5d565b600855610e20610b32565b60075573ffffffffffffffffffffffffffffffffffffffff811615610e8157610e488161038e565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a60209081526040808320939093556008546009909152919020555b60008711610ef057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f43616e6e6f74207374616b652030000000000000000000000000000000000000604482015290519081900360640190fd5b600b54610f03908863ffffffff61123b16565b600b55336000908152600c6020526040902054610f26908863ffffffff61123b16565b336000818152600c60205260408082209390935560035483517fd505accf0000000000000000000000000000000000000000000000000000000081526004810193909352306024840152604483018b9052606483018a905260ff8916608484015260a4830188905260c48301879052925173ffffffffffffffffffffffffffffffffffffffff9093169263d505accf9260e480820193929182900301818387803b158015610fd357600080fd5b505af1158015610fe7573d6000803e3d6000fd5b5050600354611017925073ffffffffffffffffffffffffffffffffffffffff16905033308a63ffffffff61135716565b60408051888152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25060015481146110be57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b60008282111561113757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008261114c57506000610438565b8282028284828161115957fe5b04146111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806116376021913960400191505060405180910390fd5b9392505050565b600080821161122757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161123257fe5b04949350505050565b6000828201838110156111b057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261133c9084906113f2565b505050565b600081831061135057816111b0565b5090919050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790526113ec9085906113f2565b50505050565b6114118273ffffffffffffffffffffffffffffffffffffffff16611630565b61147c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106114e557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016114a8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611547576040519150601f19603f3d011682016040523d82523d6000602084013e61154c565b606091505b5091509150816115bd57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156113ec578080602001905160208110156115d957600080fd5b50516113ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180611682602a913960400191505060405180910390fd5b3b15159056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f742052657761726473446973747269627574696f6e20636f6e74726163745361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72315820f909fa3a0910f3b22e95648cbca716b06606dafe47e4b95662d41e95d993a43764736f6c63430005100032"
-}
diff --git a/src/hooks/Tokens.ts b/src/hooks/Tokens.ts
index ccae45b..fc353c5 100644
--- a/src/hooks/Tokens.ts
+++ b/src/hooks/Tokens.ts
@@ -9,7 +9,6 @@ import { isAddress } from '../utils'
import { useActiveWeb3React } from './index'
import { useBytes32TokenContract, useTokenContract } from './useContract'
-import { filterTokens } from '../components/SearchModal/filtering'
import { arrayify } from 'ethers/lib/utils'
// reduce token map into standard address <-> Token mapping, optionally include user added tokens
@@ -90,21 +89,6 @@ export function useIsTokenActive(token: Token | undefined | null): boolean {
return !!activeTokens[token.address]
}
-// used to detect extra search results
-export function useFoundOnInactiveList(searchQuery: string): Token[] | undefined {
- const { chainId } = useActiveWeb3React()
- const inactiveTokens = useAllInactiveTokens()
-
- return useMemo(() => {
- if (!chainId || searchQuery === '') {
- return undefined
- } else {
- const tokens = filterTokens(Object.values(inactiveTokens), searchQuery)
- return tokens
- }
- }, [chainId, inactiveTokens, searchQuery])
-}
-
// Check if currency is included in custom list from user storage
export function useIsUserAddedToken(currency: Currency | undefined | null): boolean {
const userAddedTokens = useUserAddedTokens()
diff --git a/src/hooks/Trades.ts b/src/hooks/Trades.ts
deleted file mode 100644
index 32b7cba..0000000
--- a/src/hooks/Trades.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-import { isTradeBetter } from 'utils/trades'
-import { Currency, CurrencyAmount, Pair, Token, Trade } from '@uniswap/sdk'
-import flatMap from 'lodash.flatmap'
-import { useMemo } from 'react'
-
-import { BASES_TO_CHECK_TRADES_AGAINST, CUSTOM_BASES, BETTER_TRADE_LESS_HOPS_THRESHOLD } from '../constants'
-import { PairState, usePairs } from '../data/Reserves'
-import { wrappedCurrency } from '../utils/wrappedCurrency'
-
-import { useActiveWeb3React } from './index'
-import { useUnsupportedTokens } from './Tokens'
-import { useUserSingleHopOnly } from 'state/user/hooks'
-
-function useAllCommonPairs(currencyA?: Currency, currencyB?: Currency): Pair[] {
- const { chainId } = useActiveWeb3React()
-
- const bases: Token[] = chainId ? BASES_TO_CHECK_TRADES_AGAINST[chainId] : []
-
- const [tokenA, tokenB] = chainId
- ? [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
- : [undefined, undefined]
-
- const basePairs: [Token, Token][] = useMemo(
- () =>
- flatMap(bases, (base): [Token, Token][] => bases.map((otherBase) => [base, otherBase])).filter(
- ([t0, t1]) => t0.address !== t1.address
- ),
- [bases]
- )
-
- const allPairCombinations: [Token, Token][] = useMemo(
- () =>
- tokenA && tokenB
- ? [
- // the direct pair
- [tokenA, tokenB],
- // token A against all bases
- ...bases.map((base): [Token, Token] => [tokenA, base]),
- // token B against all bases
- ...bases.map((base): [Token, Token] => [tokenB, base]),
- // each base against all bases
- ...basePairs,
- ]
- .filter((tokens): tokens is [Token, Token] => Boolean(tokens[0] && tokens[1]))
- .filter(([t0, t1]) => t0.address !== t1.address)
- .filter(([tokenA, tokenB]) => {
- if (!chainId) return true
- const customBases = CUSTOM_BASES[chainId]
- if (!customBases) return true
-
- const customBasesA: Token[] | undefined = customBases[tokenA.address]
- const customBasesB: Token[] | undefined = customBases[tokenB.address]
-
- if (!customBasesA && !customBasesB) return true
-
- if (customBasesA && !customBasesA.find((base) => tokenB.equals(base))) return false
- if (customBasesB && !customBasesB.find((base) => tokenA.equals(base))) return false
-
- return true
- })
- : [],
- [tokenA, tokenB, bases, basePairs, chainId]
- )
-
- const allPairs = usePairs(allPairCombinations)
-
- // only pass along valid pairs, non-duplicated pairs
- return useMemo(
- () =>
- Object.values(
- allPairs
- // filter out invalid pairs
- .filter((result): result is [PairState.EXISTS, Pair] => Boolean(result[0] === PairState.EXISTS && result[1]))
- // filter out duplicated pairs
- .reduce<{ [pairAddress: string]: Pair }>((memo, [, curr]) => {
- memo[curr.liquidityToken.address] = memo[curr.liquidityToken.address] ?? curr
- return memo
- }, {})
- ),
- [allPairs]
- )
-}
-
-const MAX_HOPS = 3
-
-/**
- * Returns the best trade for the exact amount of tokens in to the given token out
- */
-export function useTradeExactIn(currencyAmountIn?: CurrencyAmount, currencyOut?: Currency): Trade | null {
- const allowedPairs = useAllCommonPairs(currencyAmountIn?.currency, currencyOut)
-
- const [singleHopOnly] = useUserSingleHopOnly()
-
- return useMemo(() => {
- if (currencyAmountIn && currencyOut && allowedPairs.length > 0) {
- if (singleHopOnly) {
- return (
- Trade.bestTradeExactIn(allowedPairs, currencyAmountIn, currencyOut, { maxHops: 1, maxNumResults: 1 })[0] ??
- null
- )
- }
- // search through trades with varying hops, find best trade out of them
- let bestTradeSoFar: Trade | null = null
- for (let i = 1; i <= MAX_HOPS; i++) {
- const currentTrade: Trade | null =
- Trade.bestTradeExactIn(allowedPairs, currencyAmountIn, currencyOut, { maxHops: i, maxNumResults: 1 })[0] ??
- null
- // if current trade is best yet, save it
- if (isTradeBetter(bestTradeSoFar, currentTrade, BETTER_TRADE_LESS_HOPS_THRESHOLD)) {
- bestTradeSoFar = currentTrade
- }
- }
- return bestTradeSoFar
- }
-
- return null
- }, [allowedPairs, currencyAmountIn, currencyOut, singleHopOnly])
-}
-
-/**
- * Returns the best trade for the token in to the exact amount of token out
- */
-export function useTradeExactOut(currencyIn?: Currency, currencyAmountOut?: CurrencyAmount): Trade | null {
- const allowedPairs = useAllCommonPairs(currencyIn, currencyAmountOut?.currency)
-
- const [singleHopOnly] = useUserSingleHopOnly()
-
- return useMemo(() => {
- if (currencyIn && currencyAmountOut && allowedPairs.length > 0) {
- if (singleHopOnly) {
- return (
- Trade.bestTradeExactOut(allowedPairs, currencyIn, currencyAmountOut, { maxHops: 1, maxNumResults: 1 })[0] ??
- null
- )
- }
- // search through trades with varying hops, find best trade out of them
- let bestTradeSoFar: Trade | null = null
- for (let i = 1; i <= MAX_HOPS; i++) {
- const currentTrade =
- Trade.bestTradeExactOut(allowedPairs, currencyIn, currencyAmountOut, { maxHops: i, maxNumResults: 1 })[0] ??
- null
- if (isTradeBetter(bestTradeSoFar, currentTrade, BETTER_TRADE_LESS_HOPS_THRESHOLD)) {
- bestTradeSoFar = currentTrade
- }
- }
- return bestTradeSoFar
- }
- return null
- }, [currencyIn, currencyAmountOut, allowedPairs, singleHopOnly])
-}
-
-export function useIsTransactionUnsupported(currencyIn?: Currency, currencyOut?: Currency): boolean {
- const unsupportedToken: { [address: string]: Token } = useUnsupportedTokens()
- const { chainId } = useActiveWeb3React()
-
- const tokenIn = wrappedCurrency(currencyIn, chainId)
- const tokenOut = wrappedCurrency(currencyOut, chainId)
-
- // if unsupported list loaded & either token on list, mark as unsupported
- if (unsupportedToken) {
- if (tokenIn && Object.keys(unsupportedToken).includes(tokenIn.address)) {
- return true
- }
- if (tokenOut && Object.keys(unsupportedToken).includes(tokenOut.address)) {
- return true
- }
- }
-
- return false
-}
diff --git a/src/hooks/useAddTokenToMetamask.ts b/src/hooks/useAddTokenToMetamask.ts
deleted file mode 100644
index 1c52eb6..0000000
--- a/src/hooks/useAddTokenToMetamask.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { getTokenLogoURL } from './../components/CurrencyLogo/index'
-import { wrappedCurrency } from 'utils/wrappedCurrency'
-import { Currency, Token } from '@uniswap/sdk'
-import { useCallback, useState } from 'react'
-import { useActiveWeb3React } from 'hooks'
-
-export default function useAddTokenToMetamask(
- currencyToAdd: Currency | undefined
-): { addToken: () => void; success: boolean | undefined } {
- const { library, chainId } = useActiveWeb3React()
-
- const token: Token | undefined = wrappedCurrency(currencyToAdd, chainId)
-
- const [success, setSuccess] = useState<boolean | undefined>()
-
- const addToken = useCallback(() => {
- if (library && library.provider.isMetaMask && library.provider.request && token) {
- library.provider
- .request({
- method: 'wallet_watchAsset',
- params: {
- //@ts-ignore // need this for incorrect ethers provider type
- type: 'ERC20',
- options: {
- address: token.address,
- symbol: token.symbol,
- decimals: token.decimals,
- image: getTokenLogoURL(token.address),
- },
- },
- })
- .then((success) => {
- setSuccess(success)
- })
- .catch(() => setSuccess(false))
- } else {
- setSuccess(false)
- }
- }, [library, token])
-
- return { addToken, success }
-}
diff --git a/src/hooks/useApproveCallback.ts b/src/hooks/useApproveCallback.ts
deleted file mode 100644
index 90396d5..0000000
--- a/src/hooks/useApproveCallback.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { MaxUint256 } from '@ethersproject/constants'
-import { TransactionResponse } from '@ethersproject/providers'
-import { Trade, TokenAmount, CurrencyAmount, ETHER } from '@uniswap/sdk'
-import { useCallback, useMemo } from 'react'
-import { ROUTER_ADDRESS } from '../constants'
-import { useTokenAllowance } from '../data/Allowances'
-import { getTradeVersion, useV1TradeExchangeAddress } from '../data/V1'
-import { Field } from '../state/swap/actions'
-import { useTransactionAdder, useHasPendingApproval } from '../state/transactions/hooks'
-import { computeSlippageAdjustedAmounts } from '../utils/prices'
-import { calculateGasMargin } from '../utils'
-import { useTokenContract } from './useContract'
-import { useActiveWeb3React } from './index'
-import { Version } from './useToggledVersion'
-
-export enum ApprovalState {
- UNKNOWN,
- NOT_APPROVED,
- PENDING,
- APPROVED,
-}
-
-// returns a variable indicating the state of the approval and a function which approves if necessary or early returns
-export function useApproveCallback(
- amountToApprove?: CurrencyAmount,
- spender?: string
-): [ApprovalState, () => Promise<void>] {
- const { account } = useActiveWeb3React()
- const token = amountToApprove instanceof TokenAmount ? amountToApprove.token : undefined
- const currentAllowance = useTokenAllowance(token, account ?? undefined, spender)
- const pendingApproval = useHasPendingApproval(token?.address, spender)
-
- // check the current approval status
- const approvalState: ApprovalState = useMemo(() => {
- if (!amountToApprove || !spender) return ApprovalState.UNKNOWN
- if (amountToApprove.currency === ETHER) return ApprovalState.APPROVED
- // we might not have enough data to know whether or not we need to approve
- if (!currentAllowance) return ApprovalState.UNKNOWN
-
- // amountToApprove will be defined if currentAllowance is
- return currentAllowance.lessThan(amountToApprove)
- ? pendingApproval
- ? ApprovalState.PENDING
- : ApprovalState.NOT_APPROVED
- : ApprovalState.APPROVED
- }, [amountToApprove, currentAllowance, pendingApproval, spender])
-
- const tokenContract = useTokenContract(token?.address)
- const addTransaction = useTransactionAdder()
-
- const approve = useCallback(async (): Promise<void> => {
- if (approvalState !== ApprovalState.NOT_APPROVED) {
- console.error('approve was called unnecessarily')
- return
- }
- if (!token) {
- console.error('no token')
- return
- }
-
- if (!tokenContract) {
- console.error('tokenContract is null')
- return
- }
-
- if (!amountToApprove) {
- console.error('missing amount to approve')
- return
- }
-
- if (!spender) {
- console.error('no spender')
- return
- }
-
- let useExact = false
- const estimatedGas = await tokenContract.estimateGas.approve(spender, MaxUint256).catch(() => {
- // general fallback for tokens who restrict approval amounts
- useExact = true
- return tokenContract.estimateGas.approve(spender, amountToApprove.raw.toString())
- })
-
- return tokenContract
- .approve(spender, useExact ? amountToApprove.raw.toString() : MaxUint256, {
- gasLimit: calculateGasMargin(estimatedGas),
- })
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: 'Approve ' + amountToApprove.currency.symbol,
- approval: { tokenAddress: token.address, spender: spender },
- })
- })
- .catch((error: Error) => {
- console.debug('Failed to approve token', error)
- throw error
- })
- }, [approvalState, token, tokenContract, amountToApprove, spender, addTransaction])
-
- return [approvalState, approve]
-}
-
-// wraps useApproveCallback in the context of a swap
-export function useApproveCallbackFromTrade(trade?: Trade, allowedSlippage = 0) {
- const amountToApprove = useMemo(
- () => (trade ? computeSlippageAdjustedAmounts(trade, allowedSlippage)[Field.INPUT] : undefined),
- [trade, allowedSlippage]
- )
- const tradeIsV1 = getTradeVersion(trade) === Version.v1
- const v1ExchangeAddress = useV1TradeExchangeAddress(trade)
- return useApproveCallback(amountToApprove, tradeIsV1 ? v1ExchangeAddress : ROUTER_ADDRESS)
-}
diff --git a/src/hooks/useContract.ts b/src/hooks/useContract.ts
index a4f85ae..9808d3f 100644
--- a/src/hooks/useContract.ts
+++ b/src/hooks/useContract.ts
@@ -19,7 +19,6 @@ import { MIGRATOR_ABI, MIGRATOR_ADDRESS } from '../constants/abis/migrator'
import UNISOCKS_ABI from '../constants/abis/unisocks.json'
import WETH_ABI from '../constants/abis/weth.json'
import { MULTICALL_ABI, MULTICALL_NETWORKS } from '../constants/multicall'
-import { V1_EXCHANGE_ABI, V1_FACTORY_ABI, V1_FACTORY_ADDRESSES } from '../constants/v1'
import { getContract } from '../utils'
import { useActiveWeb3React } from './index'
@@ -38,19 +37,10 @@ function useContract(address: string | undefined, ABI: any, withSignerIfPossible
}, [address, ABI, library, withSignerIfPossible, account])
}
-export function useV1FactoryContract(): Contract | null {
- const { chainId } = useActiveWeb3React()
- return useContract(chainId && V1_FACTORY_ADDRESSES[chainId], V1_FACTORY_ABI, false)
-}
-
export function useV2MigratorContract(): Contract | null {
return useContract(MIGRATOR_ADDRESS, MIGRATOR_ABI, true)
}
-export function useV1ExchangeContract(address?: string, withSignerIfPossible?: boolean): Contract | null {
- return useContract(address, V1_EXCHANGE_ABI, withSignerIfPossible)
-}
-
export function useTokenContract(tokenAddress?: string, withSignerIfPossible?: boolean): Contract | null {
return useContract(tokenAddress, ERC20_ABI, withSignerIfPossible)
}
@@ -102,24 +92,6 @@ export function useMulticallContract(): Contract | null {
return useContract(chainId && MULTICALL_NETWORKS[chainId], MULTICALL_ABI, false)
}
-export function useMerkleDistributorContract(): Contract | null {
- const { chainId } = useActiveWeb3React()
- return useContract(chainId ? MERKLE_DISTRIBUTOR_ADDRESS[chainId] : undefined, MERKLE_DISTRIBUTOR_ABI, true)
-}
-
-export function useGovernanceContract(): Contract | null {
- return useContract(GOVERNANCE_ADDRESS, GOVERNANCE_ABI, true)
-}
-
-export function useUniContract(): Contract | null {
- const { chainId } = useActiveWeb3React()
- return useContract(chainId ? UNI[chainId].address : undefined, UNI_ABI, true)
-}
-
-export function useStakingContract(stakingAddress?: string, withSignerIfPossible?: boolean): Contract | null {
- return useContract(stakingAddress, STAKING_REWARDS_ABI, withSignerIfPossible)
-}
-
export function useSocksController(): Contract | null {
const { chainId } = useActiveWeb3React()
return useContract(
diff --git a/src/hooks/useSwapCallback.ts b/src/hooks/useSwapCallback.ts
deleted file mode 100644
index 124de14..0000000
--- a/src/hooks/useSwapCallback.ts
+++ /dev/null
@@ -1,244 +0,0 @@
-import { BigNumber } from '@ethersproject/bignumber'
-import { Contract } from '@ethersproject/contracts'
-import { JSBI, Percent, Router, SwapParameters, Trade, TradeType } from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { BIPS_BASE, INITIAL_ALLOWED_SLIPPAGE } from '../constants'
-import { getTradeVersion, useV1TradeExchangeAddress } from '../data/V1'
-import { useTransactionAdder } from '../state/transactions/hooks'
-import { calculateGasMargin, getRouterContract, isAddress, shortenAddress } from '../utils'
-import isZero from '../utils/isZero'
-import v1SwapArguments from '../utils/v1SwapArguments'
-import { useActiveWeb3React } from './index'
-import { useV1ExchangeContract } from './useContract'
-import useTransactionDeadline from './useTransactionDeadline'
-import useENS from './useENS'
-import { Version } from './useToggledVersion'
-
-export enum SwapCallbackState {
- INVALID,
- LOADING,
- VALID,
-}
-
-interface SwapCall {
- contract: Contract
- parameters: SwapParameters
-}
-
-interface SuccessfulCall {
- call: SwapCall
- gasEstimate: BigNumber
-}
-
-interface FailedCall {
- call: SwapCall
- error: Error
-}
-
-type EstimatedSwapCall = SuccessfulCall | FailedCall
-
-/**
- * Returns the swap calls that can be used to make the trade
- * @param trade trade to execute
- * @param allowedSlippage user allowed slippage
- * @param recipientAddressOrName
- */
-function useSwapCallArguments(
- trade: Trade | undefined, // trade to execute, required
- allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips
- recipientAddressOrName: string | null // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
-): SwapCall[] {
- const { account, chainId, library } = useActiveWeb3React()
-
- const { address: recipientAddress } = useENS(recipientAddressOrName)
- const recipient = recipientAddressOrName === null ? account : recipientAddress
- const deadline = useTransactionDeadline()
-
- const v1Exchange = useV1ExchangeContract(useV1TradeExchangeAddress(trade), true)
-
- return useMemo(() => {
- const tradeVersion = getTradeVersion(trade)
- if (!trade || !recipient || !library || !account || !tradeVersion || !chainId || !deadline) return []
-
- const contract: Contract | null =
- tradeVersion === Version.v2 ? getRouterContract(chainId, library, account) : v1Exchange
- if (!contract) {
- return []
- }
-
- const swapMethods = []
-
- switch (tradeVersion) {
- case Version.v2:
- swapMethods.push(
- Router.swapCallParameters(trade, {
- feeOnTransfer: false,
- allowedSlippage: new Percent(JSBI.BigInt(allowedSlippage), BIPS_BASE),
- recipient,
- deadline: deadline.toNumber(),
- })
- )
-
- if (trade.tradeType === TradeType.EXACT_INPUT) {
- swapMethods.push(
- Router.swapCallParameters(trade, {
- feeOnTransfer: true,
- allowedSlippage: new Percent(JSBI.BigInt(allowedSlippage), BIPS_BASE),
- recipient,
- deadline: deadline.toNumber(),
- })
- )
- }
- break
- case Version.v1:
- swapMethods.push(
- v1SwapArguments(trade, {
- allowedSlippage: new Percent(JSBI.BigInt(allowedSlippage), BIPS_BASE),
- recipient,
- deadline: deadline.toNumber(),
- })
- )
- break
- }
- return swapMethods.map((parameters) => ({ parameters, contract }))
- }, [account, allowedSlippage, chainId, deadline, library, recipient, trade, v1Exchange])
-}
-
-// returns a function that will execute a swap, if the parameters are all valid
-// and the user has approved the slippage adjusted input amount for the trade
-export function useSwapCallback(
- trade: Trade | undefined, // trade to execute, required
- allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips
- recipientAddressOrName: string | null // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
-): { state: SwapCallbackState; callback: null | (() => Promise<string>); error: string | null } {
- const { account, chainId, library } = useActiveWeb3React()
-
- const swapCalls = useSwapCallArguments(trade, allowedSlippage, recipientAddressOrName)
-
- const addTransaction = useTransactionAdder()
-
- const { address: recipientAddress } = useENS(recipientAddressOrName)
- const recipient = recipientAddressOrName === null ? account : recipientAddress
-
- return useMemo(() => {
- if (!trade || !library || !account || !chainId) {
- return { state: SwapCallbackState.INVALID, callback: null, error: 'Missing dependencies' }
- }
- if (!recipient) {
- if (recipientAddressOrName !== null) {
- return { state: SwapCallbackState.INVALID, callback: null, error: 'Invalid recipient' }
- } else {
- return { state: SwapCallbackState.LOADING, callback: null, error: null }
- }
- }
-
- const tradeVersion = getTradeVersion(trade)
-
- return {
- state: SwapCallbackState.VALID,
- callback: async function onSwap(): Promise<string> {
- const estimatedCalls: EstimatedSwapCall[] = await Promise.all(
- swapCalls.map((call) => {
- const {
- parameters: { methodName, args, value },
- contract,
- } = call
- const options = !value || isZero(value) ? {} : { value }
-
- return contract.estimateGas[methodName](...args, options)
- .then((gasEstimate) => {
- return {
- call,
- gasEstimate,
- }
- })
- .catch((gasError) => {
- console.debug('Gas estimate failed, trying eth_call to extract error', call)
-
- return contract.callStatic[methodName](...args, options)
- .then((result) => {
- console.debug('Unexpected successful call after failed estimate gas', call, gasError, result)
- return { call, error: new Error('Unexpected issue with estimating the gas. Please try again.') }
- })
- .catch((callError) => {
- console.debug('Call threw error', call, callError)
- let errorMessage: string
- switch (callError.reason) {
- case 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT':
- case 'UniswapV2Router: EXCESSIVE_INPUT_AMOUNT':
- errorMessage =
- 'This transaction will not succeed either due to price movement or fee on transfer. Try increasing your slippage tolerance.'
- break
- default:
- errorMessage = `The transaction cannot succeed due to error: ${callError.reason}. This is probably an issue with one of the tokens you are swapping.`
- }
- return { call, error: new Error(errorMessage) }
- })
- })
- })
- )
-
- // a successful estimation is a bignumber gas estimate and the next call is also a bignumber gas estimate
- const successfulEstimation = estimatedCalls.find(
- (el, ix, list): el is SuccessfulCall =>
- 'gasEstimate' in el && (ix === list.length - 1 || 'gasEstimate' in list[ix + 1])
- )
-
- if (!successfulEstimation) {
- const errorCalls = estimatedCalls.filter((call): call is FailedCall => 'error' in call)
- if (errorCalls.length > 0) throw errorCalls[errorCalls.length - 1].error
- throw new Error('Unexpected error. Please contact support: none of the calls threw an error')
- }
-
- const {
- call: {
- contract,
- parameters: { methodName, args, value },
- },
- gasEstimate,
- } = successfulEstimation
-
- return contract[methodName](...args, {
- gasLimit: calculateGasMargin(gasEstimate),
- ...(value && !isZero(value) ? { value, from: account } : { from: account }),
- })
- .then((response: any) => {
- const inputSymbol = trade.inputAmount.currency.symbol
- const outputSymbol = trade.outputAmount.currency.symbol
- const inputAmount = trade.inputAmount.toSignificant(3)
- const outputAmount = trade.outputAmount.toSignificant(3)
-
- const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}`
- const withRecipient =
- recipient === account
- ? base
- : `${base} to ${
- recipientAddressOrName && isAddress(recipientAddressOrName)
- ? shortenAddress(recipientAddressOrName)
- : recipientAddressOrName
- }`
-
- const withVersion =
- tradeVersion === Version.v2 ? withRecipient : `${withRecipient} on ${(tradeVersion as any).toUpperCase()}`
-
- addTransaction(response, {
- summary: withVersion,
- })
-
- return response.hash
- })
- .catch((error: any) => {
- // if the user rejected the tx, pass this along
- if (error?.code === 4001) {
- throw new Error('Transaction rejected.')
- } else {
- // otherwise, the error was unexpected and we need to convey that
- console.error(`Swap failed`, error, methodName, args, value)
- throw new Error(`Swap failed: ${error.message}`)
- }
- })
- },
- error: null,
- }
- }, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction])
-}
diff --git a/src/hooks/useTransactionDeadline.ts b/src/hooks/useTransactionDeadline.ts
deleted file mode 100644
index 1e36990..0000000
--- a/src/hooks/useTransactionDeadline.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { BigNumber } from 'ethers'
-import { useMemo } from 'react'
-import { useSelector } from 'react-redux'
-import { AppState } from '../state'
-import useCurrentBlockTimestamp from './useCurrentBlockTimestamp'
-
-// 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 = useSelector<AppState, number>((state) => state.user.userDeadline)
- const blockTimestamp = useCurrentBlockTimestamp()
- return useMemo(() => {
- if (blockTimestamp && ttl) return blockTimestamp.add(ttl)
- return undefined
- }, [blockTimestamp, ttl])
-}
diff --git a/src/hooks/useWrapCallback.ts b/src/hooks/useWrapCallback.ts
deleted file mode 100644
index 5e7b228..0000000
--- a/src/hooks/useWrapCallback.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { Currency, currencyEquals, ETHER, WETH } from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { tryParseAmount } from '../state/swap/hooks'
-import { useTransactionAdder } from '../state/transactions/hooks'
-import { useCurrencyBalance } from '../state/wallet/hooks'
-import { useActiveWeb3React } from './index'
-import { useWETHContract } from './useContract'
-
-export enum WrapType {
- NOT_APPLICABLE,
- WRAP,
- UNWRAP,
-}
-
-const NOT_APPLICABLE = { wrapType: WrapType.NOT_APPLICABLE }
-/**
- * Given the selected input and output currency, return a wrap callback
- * @param inputCurrency the selected input currency
- * @param outputCurrency the selected output currency
- * @param typedValue the user input value
- */
-export default function useWrapCallback(
- inputCurrency: Currency | undefined,
- outputCurrency: Currency | undefined,
- typedValue: string | undefined
-): { wrapType: WrapType; execute?: undefined | (() => Promise<void>); inputError?: string } {
- const { chainId, account } = useActiveWeb3React()
- const wethContract = useWETHContract()
- const balance = useCurrencyBalance(account ?? undefined, inputCurrency)
- // we can always parse the amount typed as the input currency, since wrapping is 1:1
- const inputAmount = useMemo(() => tryParseAmount(typedValue, inputCurrency), [inputCurrency, typedValue])
- const addTransaction = useTransactionAdder()
-
- return useMemo(() => {
- if (!wethContract || !chainId || !inputCurrency || !outputCurrency) return NOT_APPLICABLE
-
- const sufficientBalance = inputAmount && balance && !balance.lessThan(inputAmount)
-
- if (inputCurrency === ETHER && currencyEquals(WETH[chainId], outputCurrency)) {
- return {
- wrapType: WrapType.WRAP,
- execute:
- sufficientBalance && inputAmount
- ? async () => {
- try {
- const txReceipt = await wethContract.deposit({ value: `0x${inputAmount.raw.toString(16)}` })
- addTransaction(txReceipt, { summary: `Wrap ${inputAmount.toSignificant(6)} ETH to WETH` })
- } catch (error) {
- console.error('Could not deposit', error)
- }
- }
- : undefined,
- inputError: sufficientBalance ? undefined : 'Insufficient ETH balance',
- }
- } else if (currencyEquals(WETH[chainId], inputCurrency) && outputCurrency === ETHER) {
- return {
- wrapType: WrapType.UNWRAP,
- execute:
- sufficientBalance && inputAmount
- ? async () => {
- try {
- const txReceipt = await wethContract.withdraw(`0x${inputAmount.raw.toString(16)}`)
- addTransaction(txReceipt, { summary: `Unwrap ${inputAmount.toSignificant(6)} WETH to ETH` })
- } catch (error) {
- console.error('Could not withdraw', error)
- }
- }
- : undefined,
- inputError: sufficientBalance ? undefined : 'Insufficient WETH balance',
- }
- } else {
- return NOT_APPLICABLE
- }
- }, [wethContract, chainId, inputCurrency, outputCurrency, inputAmount, balance, addTransaction])
-}
diff --git a/src/index.tsx b/src/index.tsx
index f4d9ca8..d5c1dbf 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -14,7 +14,6 @@ import store from './state'
import ApplicationUpdater from './state/application/updater'
import ListsUpdater from './state/lists/updater'
import MulticallUpdater from './state/multicall/updater'
-import TransactionUpdater from './state/transactions/updater'
import UserUpdater from './state/user/updater'
import ThemeProvider, { FixedGlobalStyle, ThemedGlobalStyle } from './theme'
import getLibrary from './utils/getLibrary'
@@ -52,7 +51,6 @@ function Updaters() {
<ListsUpdater />
<UserUpdater />
<ApplicationUpdater />
- <TransactionUpdater />
<MulticallUpdater />
</>
)
diff --git a/src/pages/App.tsx b/src/pages/App.tsx
index 3e96230..9dd594b 100644
--- a/src/pages/App.tsx
+++ b/src/pages/App.tsx
@@ -1,122 +1,82 @@
-import React, { Suspense } from 'react'
-import { Route, Switch } from 'react-router-dom'
-import styled from 'styled-components'
-import GoogleAnalyticsReporter from '../components/analytics/GoogleAnalyticsReporter'
-import AddressClaimModal from '../components/claim/AddressClaimModal'
-import Header from '../components/Header'
-import Polling from '../components/Header/Polling'
-import URLWarning from '../components/Header/URLWarning'
-import Popups from '../components/Popups'
-import Web3ReactManager from '../components/Web3ReactManager'
-import { ApplicationModal } from '../state/application/actions'
-import { useModalOpen, useToggleModal } from '../state/application/hooks'
-import DarkModeQueryParamReader from '../theme/DarkModeQueryParamReader'
-import AddLiquidity from './AddLiquidity'
-import {
- RedirectDuplicateTokenIds,
- RedirectOldAddLiquidityPathStructure,
- RedirectToAddLiquidity,
-} from './AddLiquidity/redirects'
-import Earn from './Earn'
-import Manage from './Earn/Manage'
-import MigrateV1 from './MigrateV1'
-import MigrateV1Exchange from './MigrateV1/MigrateV1Exchange'
-import RemoveV1Exchange from './MigrateV1/RemoveV1Exchange'
-import Pool from './Pool'
-import PoolFinder from './PoolFinder'
-import RemoveLiquidity from './RemoveLiquidity'
-import { RedirectOldRemoveLiquidityPathStructure } from './RemoveLiquidity/redirects'
-import Swap from './Swap'
-import { OpenClaimAddressModalAndRedirectToSwap, RedirectPathToSwapOnly, RedirectToSwap } from './Swap/redirects'
-import Vote from './Vote'
-import VotePage from './Vote/VotePage'
-
-const AppWrapper = styled.div`
- display: flex;
- flex-flow: column;
- align-items: flex-start;
- overflow-x: hidden;
-`
-
-const HeaderWrapper = styled.div`
- ${({ theme }) => theme.flexRowNoWrap}
- width: 100%;
- justify-content: space-between;
-`
-
-const BodyWrapper = styled.div`
- display: flex;
- flex-direction: column;
- width: 100%;
- padding-top: 100px;
- align-items: center;
- flex: 1;
- overflow-y: auto;
- overflow-x: hidden;
- z-index: 10;
-
- ${({ theme }) => theme.mediaWidth.upToSmall`
- padding: 16px;
- padding-top: 2rem;
- `};
-
- z-index: 1;
-`
-
-const Marginer = styled.div`
- margin-top: 5rem;
-`
-
-function TopLevelModals() {
- const open = useModalOpen(ApplicationModal.ADDRESS_CLAIM)
- const toggle = useToggleModal(ApplicationModal.ADDRESS_CLAIM)
- return <AddressClaimModal isOpen={open} onDismiss={toggle} />
-}
-
-export default function App() {
- return (
- <Suspense fallback={null}>
- <Route component={GoogleAnalyticsReporter} />
- <Route component={DarkModeQueryParamReader} />
- <AppWrapper>
- <URLWarning />
- <HeaderWrapper>
- <Header />
- </HeaderWrapper>
- <BodyWrapper>
- <Popups />
- <Polling />
- <TopLevelModals />
- <Web3ReactManager>
- <Switch>
- <Route exact strict path="/swap" component={Swap} />
- <Route exact strict path="/claim" component={OpenClaimAddressModalAndRedirectToSwap} />
- <Route exact strict path="/swap/:outputCurrency" component={RedirectToSwap} />
- <Route exact strict path="/send" component={RedirectPathToSwapOnly} />
- <Route exact strict path="/find" component={PoolFinder} />
- <Route exact strict path="/pool" component={Pool} />
- <Route exact strict path="/uni" component={Earn} />
- <Route exact strict path="/vote" component={Vote} />
- <Route exact strict path="/create" component={RedirectToAddLiquidity} />
- <Route exact path="/add" component={AddLiquidity} />
- <Route exact path="/add/:currencyIdA" component={RedirectOldAddLiquidityPathStructure} />
- <Route exact path="/add/:currencyIdA/:currencyIdB" component={RedirectDuplicateTokenIds} />
- <Route exact path="/create" component={AddLiquidity} />
- <Route exact path="/create/:currencyIdA" component={RedirectOldAddLiquidityPathStructure} />
- <Route exact path="/create/:currencyIdA/:currencyIdB" component={RedirectDuplicateTokenIds} />
- <Route exact strict path="/remove/v1/:address" component={RemoveV1Exchange} />
- <Route exact strict path="/remove/:tokens" component={RedirectOldRemoveLiquidityPathStructure} />
- <Route exact strict path="/remove/:currencyIdA/:currencyIdB" component={RemoveLiquidity} />
- <Route exact strict path="/migrate/v1" component={MigrateV1} />
- <Route exact strict path="/migrate/v1/:address" component={MigrateV1Exchange} />
- <Route exact strict path="/uni/:currencyIdA/:currencyIdB" component={Manage} />
- <Route exact strict path="/vote/:id" component={VotePage} />
- <Route component={RedirectPathToSwapOnly} />
- </Switch>
- </Web3ReactManager>
- <Marginer />
- </BodyWrapper>
- </AppWrapper>
- </Suspense>
- )
-}
+import React, { Suspense } from 'react'
+import { Route, Switch } from 'react-router-dom'
+import styled from 'styled-components'
+import GoogleAnalyticsReporter from '../components/analytics/GoogleAnalyticsReporter'
+import Header from '../components/Header'
+import Polling from '../components/Header/Polling'
+import URLWarning from '../components/Header/URLWarning'
+import Popups from '../components/Popups'
+import Web3ReactManager from '../components/Web3ReactManager'
+import DarkModeQueryParamReader from '../theme/DarkModeQueryParamReader'
+
+import Home from './Home'
+import Protocol from './Protocol'
+import PoolssOverview from './Pool/PoolsOverview'
+import TokensOverview from './Token/TokensOverview'
+import Wallets from './Wallets'
+
+const AppWrapper = styled.div`
+ display: flex;
+ flex-flow: column;
+ align-items: flex-start;
+ overflow-x: hidden;
+`
+
+const HeaderWrapper = styled.div`
+ ${({ theme }) => theme.flexRowNoWrap}
+ width: 100%;
+ justify-content: space-between;
+`
+
+const BodyWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ padding-top: 100px;
+ align-items: center;
+ flex: 1;
+ overflow-y: auto;
+ overflow-x: hidden;
+ z-index: 10;
+
+ ${({ theme }) => theme.mediaWidth.upToSmall`
+ padding: 16px;
+ padding-top: 2rem;
+ `};
+
+ z-index: 1;
+`
+
+const Marginer = styled.div`
+ margin-top: 5rem;
+`
+
+export default function App() {
+ return (
+ <Suspense fallback={null}>
+ <Route component={GoogleAnalyticsReporter} />
+ <Route component={DarkModeQueryParamReader} />
+ <AppWrapper>
+ <URLWarning />
+ <HeaderWrapper>
+ <Header />
+ </HeaderWrapper>
+ <BodyWrapper>
+ <Popups />
+ <Polling />
+ <Web3ReactManager>
+ <Switch>
+ <Route exact strict path="/" component={Home} />
+ <Route exact strict path="/protocol" component={Protocol} />
+ <Route exact strict path="/pools" component={PoolssOverview} />
+ <Route exact strict path="/tokens" component={TokensOverview} />
+ <Route exact strict path="/wallet" component={Wallets} />
+ </Switch>
+ </Web3ReactManager>
+ <Marginer />
+ </BodyWrapper>
+ </AppWrapper>
+ </Suspense>
+ )
+}
diff --git a/src/pages/AppBody.tsx b/src/pages/AppBody.tsx
deleted file mode 100644
index b9f42e8..0000000
--- a/src/pages/AppBody.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react'
-import styled from 'styled-components'
-
-export const BodyWrapper = styled.div`
- position: relative;
- max-width: 460px;
- width: 100%;
- background: ${({ theme }) => theme.bg0};
- box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
- 0px 24px 32px rgba(0, 0, 0, 0.01);
- border-radius: 30px;
-`
-
-/**
- * The styled container element that wraps the content of most pages and the tabs.
- */
-export default function AppBody({ children }: { children: React.ReactNode }) {
- return <BodyWrapper>{children}</BodyWrapper>
-}
diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx
new file mode 100644
index 0000000..d36f326
--- /dev/null
+++ b/src/pages/Home/index.tsx
@@ -0,0 +1,4 @@
+import React from 'react'
+export default function Home() {
+ return <div>hey</div>
+}
diff --git a/src/pages/Pool/PoolPage.tsx b/src/pages/Pool/PoolPage.tsx
new file mode 100644
index 0000000..3257974
--- /dev/null
+++ b/src/pages/Pool/PoolPage.tsx
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default function PoolPage() {
+ return <div>hey</div>
+}
diff --git a/src/pages/Pool/PoolsOverview.tsx b/src/pages/Pool/PoolsOverview.tsx
new file mode 100644
index 0000000..5b1ce4c
--- /dev/null
+++ b/src/pages/Pool/PoolsOverview.tsx
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default function PoolssOverview() {
+ return <div>hey</div>
+}
diff --git a/src/pages/Protocol/index.tsx b/src/pages/Protocol/index.tsx
new file mode 100644
index 0000000..243eb52
--- /dev/null
+++ b/src/pages/Protocol/index.tsx
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default function Protocol() {
+ return <div>hey</div>
+}
diff --git a/src/pages/Token/TokenPage.tsx b/src/pages/Token/TokenPage.tsx
new file mode 100644
index 0000000..c303f32
--- /dev/null
+++ b/src/pages/Token/TokenPage.tsx
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default function TokenPage() {
+ return <div>hey</div>
+}
diff --git a/src/pages/Token/TokensOverview.tsx b/src/pages/Token/TokensOverview.tsx
new file mode 100644
index 0000000..a5930d0
--- /dev/null
+++ b/src/pages/Token/TokensOverview.tsx
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default function TokensOverview() {
+ return <div>hey</div>
+}
diff --git a/src/pages/Wallets/index.tsx b/src/pages/Wallets/index.tsx
new file mode 100644
index 0000000..5e0ff1f
--- /dev/null
+++ b/src/pages/Wallets/index.tsx
@@ -0,0 +1,5 @@
+import React from 'react'
+
+export default function Wallets() {
+ return <div>hey</div>
+}
diff --git a/src/state/application/actions.ts b/src/state/application/actions.ts
index dbed730..9aa81bb 100644
--- a/src/state/application/actions.ts
+++ b/src/state/application/actions.ts
@@ -1,32 +1,19 @@
import { createAction } from '@reduxjs/toolkit'
import { TokenList } from '@uniswap/token-lists'
-export type PopupContent =
- | {
- txn: {
- hash: string
- success: boolean
- summary?: string
- }
- }
- | {
- listUpdate: {
- listUrl: string
- oldList: TokenList
- newList: TokenList
- auto: boolean
- }
- }
+export type PopupContent = {
+ listUpdate: {
+ listUrl: string
+ oldList: TokenList
+ newList: TokenList
+ auto: boolean
+ }
+}
export enum ApplicationModal {
WALLET,
SETTINGS,
- SELF_CLAIM,
- ADDRESS_CLAIM,
- CLAIM_POPUP,
MENU,
- DELEGATE,
- VOTE,
}
export const updateBlockNumber = createAction<{ chainId: number; blockNumber: number }>('application/updateBlockNumber')
diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts
index 51f1b7c..c9d8611 100644
--- a/src/state/application/hooks.ts
+++ b/src/state/application/hooks.ts
@@ -39,26 +39,6 @@ export function useToggleSettingsMenu(): () => void {
return useToggleModal(ApplicationModal.SETTINGS)
}
-export function useShowClaimPopup(): boolean {
- return useModalOpen(ApplicationModal.CLAIM_POPUP)
-}
-
-export function useToggleShowClaimPopup(): () => void {
- return useToggleModal(ApplicationModal.CLAIM_POPUP)
-}
-
-export function useToggleSelfClaimModal(): () => void {
- return useToggleModal(ApplicationModal.SELF_CLAIM)
-}
-
-export function useToggleDelegateModal(): () => void {
- return useToggleModal(ApplicationModal.DELEGATE)
-}
-
-export function useToggleVoteModal(): () => void {
- return useToggleModal(ApplicationModal.VOTE)
-}
-
// returns a function that allows adding a popup
export function useAddPopup(): (content: PopupContent, key?: string) => void {
const dispatch = useDispatch()
diff --git a/src/state/application/reducer.test.ts b/src/state/application/reducer.test.ts
index df2b99b..65201b6 100644
--- a/src/state/application/reducer.test.ts
+++ b/src/state/application/reducer.test.ts
@@ -1,6 +1,6 @@
import { ChainId } from '@uniswap/sdk'
import { createStore, Store } from 'redux'
-import { addPopup, ApplicationModal, removePopup, setOpenModal, updateBlockNumber } from './actions'
+import { ApplicationModal, setOpenModal, updateBlockNumber } from './actions'
import reducer, { ApplicationState } from './reducer'
describe('application reducer', () => {
@@ -16,37 +16,12 @@ describe('application reducer', () => {
})
})
- describe('addPopup', () => {
- it('adds the popup to list with a generated id', () => {
- store.dispatch(addPopup({ content: { txn: { hash: 'abc', summary: 'test', success: true } } }))
- const list = store.getState().popupList
- expect(list).toHaveLength(1)
- expect(typeof list[0].key).toEqual('string')
- expect(list[0].show).toEqual(true)
- expect(list[0].content).toEqual({ txn: { hash: 'abc', summary: 'test', success: true } })
- expect(list[0].removeAfterMs).toEqual(15000)
- })
-
- it('replaces any existing popups with the same key', () => {
- store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc', summary: 'test', success: true } } }))
- store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'def', summary: 'test2', success: false } } }))
- const list = store.getState().popupList
- expect(list).toHaveLength(1)
- expect(list[0].key).toEqual('abc')
- expect(list[0].show).toEqual(true)
- expect(list[0].content).toEqual({ txn: { hash: 'def', summary: 'test2', success: false } })
- expect(list[0].removeAfterMs).toEqual(15000)
- })
- })
-
describe('setOpenModal', () => {
it('set wallet modal', () => {
store.dispatch(setOpenModal(ApplicationModal.WALLET))
expect(store.getState().openModal).toEqual(ApplicationModal.WALLET)
store.dispatch(setOpenModal(ApplicationModal.WALLET))
expect(store.getState().openModal).toEqual(ApplicationModal.WALLET)
- store.dispatch(setOpenModal(ApplicationModal.CLAIM_POPUP))
- expect(store.getState().openModal).toEqual(ApplicationModal.CLAIM_POPUP)
store.dispatch(setOpenModal(null))
expect(store.getState().openModal).toEqual(null)
})
@@ -69,16 +44,4 @@ describe('application reducer', () => {
})
})
})
-
- describe('removePopup', () => {
- beforeEach(() => {
- store.dispatch(addPopup({ key: 'abc', content: { txn: { hash: 'abc', summary: 'test', success: true } } }))
- })
- it('hides the popup', () => {
- expect(store.getState().popupList[0].show).toBe(true)
- store.dispatch(removePopup({ key: 'abc' }))
- expect(store.getState().popupList).toHaveLength(1)
- expect(store.getState().popupList[0].show).toBe(false)
- })
- })
})
diff --git a/src/state/burn/actions.ts b/src/state/burn/actions.ts
deleted file mode 100644
index e746699..0000000
--- a/src/state/burn/actions.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { createAction } from '@reduxjs/toolkit'
-
-export enum Field {
- LIQUIDITY_PERCENT = 'LIQUIDITY_PERCENT',
- LIQUIDITY = 'LIQUIDITY',
- CURRENCY_A = 'CURRENCY_A',
- CURRENCY_B = 'CURRENCY_B',
-}
-
-export const typeInput = createAction<{ field: Field; typedValue: string }>('burn/typeInputBurn')
diff --git a/src/state/burn/hooks.ts b/src/state/burn/hooks.ts
deleted file mode 100644
index d2989dd..0000000
--- a/src/state/burn/hooks.ts
+++ /dev/null
@@ -1,147 +0,0 @@
-import { Currency, CurrencyAmount, JSBI, Pair, Percent, TokenAmount } from '@uniswap/sdk'
-import { useCallback } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { usePair } from '../../data/Reserves'
-import { useTotalSupply } from '../../data/TotalSupply'
-
-import { useActiveWeb3React } from '../../hooks'
-import { wrappedCurrency } from '../../utils/wrappedCurrency'
-import { AppDispatch, AppState } from '../index'
-import { tryParseAmount } from '../swap/hooks'
-import { useTokenBalances } from '../wallet/hooks'
-import { Field, typeInput } from './actions'
-
-export function useBurnState(): AppState['burn'] {
- return useSelector<AppState, AppState['burn']>((state) => state.burn)
-}
-
-export function useDerivedBurnInfo(
- currencyA: Currency | undefined,
- currencyB: Currency | undefined
-): {
- pair?: Pair | null
- parsedAmounts: {
- [Field.LIQUIDITY_PERCENT]: Percent
- [Field.LIQUIDITY]?: TokenAmount
- [Field.CURRENCY_A]?: CurrencyAmount
- [Field.CURRENCY_B]?: CurrencyAmount
- }
- error?: string
-} {
- const { account, chainId } = useActiveWeb3React()
-
- const { independentField, typedValue } = useBurnState()
-
- // pair + totalsupply
- const [, pair] = usePair(currencyA, currencyB)
-
- // balances
- const relevantTokenBalances = useTokenBalances(account ?? undefined, [pair?.liquidityToken])
- const userLiquidity: undefined | TokenAmount = relevantTokenBalances?.[pair?.liquidityToken?.address ?? '']
-
- const [tokenA, tokenB] = [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
- const tokens = {
- [Field.CURRENCY_A]: tokenA,
- [Field.CURRENCY_B]: tokenB,
- [Field.LIQUIDITY]: pair?.liquidityToken,
- }
-
- // liquidity values
- const totalSupply = useTotalSupply(pair?.liquidityToken)
- const liquidityValueA =
- pair &&
- totalSupply &&
- userLiquidity &&
- tokenA &&
- // this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
- JSBI.greaterThanOrEqual(totalSupply.raw, userLiquidity.raw)
- ? new TokenAmount(tokenA, pair.getLiquidityValue(tokenA, totalSupply, userLiquidity, false).raw)
- : undefined
- const liquidityValueB =
- pair &&
- totalSupply &&
- userLiquidity &&
- tokenB &&
- // this condition is a short-circuit in the case where useTokenBalance updates sooner than useTotalSupply
- JSBI.greaterThanOrEqual(totalSupply.raw, userLiquidity.raw)
- ? new TokenAmount(tokenB, pair.getLiquidityValue(tokenB, totalSupply, userLiquidity, false).raw)
- : undefined
- const liquidityValues: { [Field.CURRENCY_A]?: TokenAmount; [Field.CURRENCY_B]?: TokenAmount } = {
- [Field.CURRENCY_A]: liquidityValueA,
- [Field.CURRENCY_B]: liquidityValueB,
- }
-
- let percentToRemove: Percent = new Percent('0', '100')
- // user specified a %
- if (independentField === Field.LIQUIDITY_PERCENT) {
- percentToRemove = new Percent(typedValue, '100')
- }
- // user specified a specific amount of liquidity tokens
- else if (independentField === Field.LIQUIDITY) {
- if (pair?.liquidityToken) {
- const independentAmount = tryParseAmount(typedValue, pair.liquidityToken)
- if (independentAmount && userLiquidity && !independentAmount.greaterThan(userLiquidity)) {
- percentToRemove = new Percent(independentAmount.raw, userLiquidity.raw)
- }
- }
- }
- // user specified a specific amount of token a or b
- else {
- if (tokens[independentField]) {
- const independentAmount = tryParseAmount(typedValue, tokens[independentField])
- const liquidityValue = liquidityValues[independentField]
- if (independentAmount && liquidityValue && !independentAmount.greaterThan(liquidityValue)) {
- percentToRemove = new Percent(independentAmount.raw, liquidityValue.raw)
- }
- }
- }
-
- const parsedAmounts: {
- [Field.LIQUIDITY_PERCENT]: Percent
- [Field.LIQUIDITY]?: TokenAmount
- [Field.CURRENCY_A]?: TokenAmount
- [Field.CURRENCY_B]?: TokenAmount
- } = {
- [Field.LIQUIDITY_PERCENT]: percentToRemove,
- [Field.LIQUIDITY]:
- userLiquidity && percentToRemove && percentToRemove.greaterThan('0')
- ? new TokenAmount(userLiquidity.token, percentToRemove.multiply(userLiquidity.raw).quotient)
- : undefined,
- [Field.CURRENCY_A]:
- tokenA && percentToRemove && percentToRemove.greaterThan('0') && liquidityValueA
- ? new TokenAmount(tokenA, percentToRemove.multiply(liquidityValueA.raw).quotient)
- : undefined,
- [Field.CURRENCY_B]:
- tokenB && percentToRemove && percentToRemove.greaterThan('0') && liquidityValueB
- ? new TokenAmount(tokenB, percentToRemove.multiply(liquidityValueB.raw).quotient)
- : undefined,
- }
-
- let error: string | undefined
- if (!account) {
- error = 'Connect Wallet'
- }
-
- if (!parsedAmounts[Field.LIQUIDITY] || !parsedAmounts[Field.CURRENCY_A] || !parsedAmounts[Field.CURRENCY_B]) {
- error = error ?? 'Enter an amount'
- }
-
- return { pair, parsedAmounts, error }
-}
-
-export function useBurnActionHandlers(): {
- onUserInput: (field: Field, typedValue: string) => void
-} {
- const dispatch = useDispatch<AppDispatch>()
-
- const onUserInput = useCallback(
- (field: Field, typedValue: string) => {
- dispatch(typeInput({ field, typedValue }))
- },
- [dispatch]
- )
-
- return {
- onUserInput,
- }
-}
diff --git a/src/state/burn/reducer.ts b/src/state/burn/reducer.ts
deleted file mode 100644
index b7c1e34..0000000
--- a/src/state/burn/reducer.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { createReducer } from '@reduxjs/toolkit'
-import { Field, typeInput } from './actions'
-
-export interface BurnState {
- readonly independentField: Field
- readonly typedValue: string
-}
-
-const initialState: BurnState = {
- independentField: Field.LIQUIDITY_PERCENT,
- typedValue: '0',
-}
-
-export default createReducer<BurnState>(initialState, (builder) =>
- builder.addCase(typeInput, (state, { payload: { field, typedValue } }) => {
- return {
- ...state,
- independentField: field,
- typedValue,
- }
- })
-)
diff --git a/src/state/claim/hooks.ts b/src/state/claim/hooks.ts
deleted file mode 100644
index 050ee7d..0000000
--- a/src/state/claim/hooks.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import { UNI } from './../../constants/index'
-import { TokenAmount, JSBI, ChainId } from '@uniswap/sdk'
-import { TransactionResponse } from '@ethersproject/providers'
-import { useEffect, useState } from 'react'
-import { useActiveWeb3React } from '../../hooks'
-import { useMerkleDistributorContract } from '../../hooks/useContract'
-import { useSingleCallResult } from '../multicall/hooks'
-import { calculateGasMargin, isAddress } from '../../utils'
-import { useTransactionAdder } from '../transactions/hooks'
-
-interface UserClaimData {
- index: number
- amount: string
- proof: string[]
- flags?: {
- isSOCKS: boolean
- isLP: boolean
- isUser: boolean
- }
-}
-
-const CLAIM_PROMISES: { [key: string]: Promise<UserClaimData | null> } = {}
-
-// returns the claim for the given address, or null if not valid
-function fetchClaim(account: string, chainId: ChainId): Promise<UserClaimData | null> {
- const formatted = isAddress(account)
- if (!formatted) return Promise.reject(new Error('Invalid address'))
- const key = `${chainId}:${account}`
-
- return (CLAIM_PROMISES[key] =
- CLAIM_PROMISES[key] ??
- fetch(`https://gentle-frost-9e74.uniswap.workers.dev/${chainId}/${formatted}`)
- .then((res) => {
- if (res.status === 200) {
- return res.json()
- } else {
- console.debug(`No claim for account ${formatted} on chain ID ${chainId}`)
- return null
- }
- })
- .catch((error) => {
- console.error('Failed to get claim data', error)
- }))
-}
-
-// parse distributorContract blob and detect if user has claim data
-// null means we know it does not
-export function useUserClaimData(account: string | null | undefined): UserClaimData | null | undefined {
- const { chainId } = useActiveWeb3React()
-
- const key = `${chainId}:${account}`
- const [claimInfo, setClaimInfo] = useState<{ [key: string]: UserClaimData | null }>({})
-
- useEffect(() => {
- if (!account || !chainId) return
- fetchClaim(account, chainId).then((accountClaimInfo) =>
- setClaimInfo((claimInfo) => {
- return {
- ...claimInfo,
- [key]: accountClaimInfo,
- }
- })
- )
- }, [account, chainId, key])
-
- return account && chainId ? claimInfo[key] : undefined
-}
-
-// check if user is in blob and has not yet claimed UNI
-export function useUserHasAvailableClaim(account: string | null | undefined): boolean {
- const userClaimData = useUserClaimData(account)
- const distributorContract = useMerkleDistributorContract()
- const isClaimedResult = useSingleCallResult(distributorContract, 'isClaimed', [userClaimData?.index])
- // user is in blob and contract marks as unclaimed
- return Boolean(userClaimData && !isClaimedResult.loading && isClaimedResult.result?.[0] === false)
-}
-
-export function useUserUnclaimedAmount(account: string | null | undefined): TokenAmount | undefined {
- const { chainId } = useActiveWeb3React()
- const userClaimData = useUserClaimData(account)
- const canClaim = useUserHasAvailableClaim(account)
-
- const uni = chainId ? UNI[chainId] : undefined
- if (!uni) return undefined
- if (!canClaim || !userClaimData) {
- return new TokenAmount(uni, JSBI.BigInt(0))
- }
- return new TokenAmount(uni, JSBI.BigInt(userClaimData.amount))
-}
-
-export function useClaimCallback(
- account: string | null | undefined
-): {
- claimCallback: () => Promise<string>
-} {
- // get claim data for this account
- const { library, chainId } = useActiveWeb3React()
- const claimData = useUserClaimData(account)
-
- // used for popup summary
- const unClaimedAmount: TokenAmount | undefined = useUserUnclaimedAmount(account)
- const addTransaction = useTransactionAdder()
- const distributorContract = useMerkleDistributorContract()
-
- const claimCallback = async function () {
- if (!claimData || !account || !library || !chainId || !distributorContract) return
-
- const args = [claimData.index, account, claimData.amount, claimData.proof]
-
- return distributorContract.estimateGas['claim'](...args, {}).then((estimatedGasLimit) => {
- return distributorContract
- .claim(...args, { value: null, gasLimit: calculateGasMargin(estimatedGasLimit) })
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: `Claimed ${unClaimedAmount?.toSignificant(4)} UNI`,
- claim: { recipient: account },
- })
- return response.hash
- })
- })
- }
-
- return { claimCallback }
-}
diff --git a/src/state/governance/hooks.ts b/src/state/governance/hooks.ts
deleted file mode 100644
index 7a5b38b..0000000
--- a/src/state/governance/hooks.ts
+++ /dev/null
@@ -1,232 +0,0 @@
-import { UNI, PRELOADED_PROPOSALS } from './../../constants/index'
-import { TokenAmount } from '@uniswap/sdk'
-import { isAddress } from 'ethers/lib/utils'
-import { useGovernanceContract, useUniContract } from '../../hooks/useContract'
-import { useSingleCallResult, useSingleContractMultipleData } from '../multicall/hooks'
-import { useActiveWeb3React } from '../../hooks'
-import { ethers, utils } from 'ethers'
-import { calculateGasMargin } from '../../utils'
-import { TransactionResponse } from '@ethersproject/providers'
-import { useTransactionAdder } from '../transactions/hooks'
-import { useState, useEffect, useCallback } from 'react'
-import { abi as GOV_ABI } from '@uniswap/governance/build/GovernorAlpha.json'
-
-interface ProposalDetail {
- target: string
- functionSig: string
- callData: string
-}
-
-export interface ProposalData {
- id: string
- title: string
- description: string
- proposer: string
- status: string
- forCount: number
- againstCount: number
- startBlock: number
- endBlock: number
- details: ProposalDetail[]
-}
-
-const enumerateProposalState = (state: number) => {
- const proposalStates = ['pending', 'active', 'canceled', 'defeated', 'succeeded', 'queued', 'expired', 'executed']
- return proposalStates[state]
-}
-
-// get count of all proposals made
-export function useProposalCount(): number | undefined {
- const gov = useGovernanceContract()
- const res = useSingleCallResult(gov, 'proposalCount')
- if (res.result && !res.loading) {
- return parseInt(res.result[0])
- }
- return undefined
-}
-
-/**
- * Need proposal events to get description data emitted from
- * new proposal event.
- */
-export function useDataFromEventLogs() {
- const { library } = useActiveWeb3React()
- const [formattedEvents, setFormattedEvents] = useState<any>()
- const govContract = useGovernanceContract()
-
- // create filter for these specific events
- const filter = { ...govContract?.filters?.['ProposalCreated'](), fromBlock: 0, toBlock: 'latest' }
- const eventParser = new ethers.utils.Interface(GOV_ABI)
-
- useEffect(() => {
- async function fetchData() {
- const pastEvents = await library?.getLogs(filter)
- // reverse events to get them from newest to odlest
- const formattedEventData = pastEvents
- ?.map((event) => {
- const eventParsed = eventParser.parseLog(event).args
- return {
- description: eventParsed.description,
- details: eventParsed.targets.map((target: string, i: number) => {
- const signature = eventParsed.signatures[i]
- const [name, types] = signature.substr(0, signature.length - 1).split('(')
-
- const calldata = eventParsed.calldatas[i]
- const decoded = utils.defaultAbiCoder.decode(types.split(','), calldata)
-
- return {
- target,
- functionSig: name,
- callData: decoded.join(', '),
- }
- }),
- }
- })
- .reverse()
- setFormattedEvents(formattedEventData)
- }
- if (!formattedEvents) {
- fetchData()
- }
- }, [eventParser, filter, library, formattedEvents])
-
- return formattedEvents
-}
-
-// get data for all past and active proposals
-export function useAllProposalData() {
- const proposalCount = useProposalCount()
- const govContract = useGovernanceContract()
-
- const proposalIndexes = []
- for (let i = 1; i <= (proposalCount ?? 0); i++) {
- proposalIndexes.push([i])
- }
-
- // get metadata from past events
- const formattedEvents = useDataFromEventLogs()
-
- // get all proposal entities
- const allProposals = useSingleContractMultipleData(govContract, 'proposals', proposalIndexes)
-
- // get all proposal states
- const allProposalStates = useSingleContractMultipleData(govContract, 'state', proposalIndexes)
-
- if (formattedEvents && allProposals && allProposalStates) {
- allProposals.reverse()
- allProposalStates.reverse()
-
- return allProposals
- .filter((p, i) => {
- return Boolean(p.result) && Boolean(allProposalStates[i]?.result) && Boolean(formattedEvents[i])
- })
- .map((p, i) => {
- const description = PRELOADED_PROPOSALS.get(allProposals.length - i - 1) || formattedEvents[i].description
- const formattedProposal: ProposalData = {
- id: allProposals[i]?.result?.id.toString(),
- title: description?.split(/# |\n/g)[1] || 'Untitled',
- description: description || 'No description.',
- proposer: allProposals[i]?.result?.proposer,
- status: enumerateProposalState(allProposalStates[i]?.result?.[0]) ?? 'Undetermined',
- forCount: parseFloat(ethers.utils.formatUnits(allProposals[i]?.result?.forVotes.toString(), 18)),
- againstCount: parseFloat(ethers.utils.formatUnits(allProposals[i]?.result?.againstVotes.toString(), 18)),
- startBlock: parseInt(allProposals[i]?.result?.startBlock?.toString()),
- endBlock: parseInt(allProposals[i]?.result?.endBlock?.toString()),
- details: formattedEvents[i].details,
- }
- return formattedProposal
- })
- } else {
- return []
- }
-}
-
-export function useProposalData(id: string): ProposalData | undefined {
- const allProposalData = useAllProposalData()
- return allProposalData?.find((p) => p.id === id)
-}
-
-// get the users delegatee if it exists
-export function useUserDelegatee(): string {
- const { account } = useActiveWeb3React()
- const uniContract = useUniContract()
- const { result } = useSingleCallResult(uniContract, 'delegates', [account ?? undefined])
- return result?.[0] ?? undefined
-}
-
-// gets the users current votes
-export function useUserVotes(): TokenAmount | undefined {
- const { account, chainId } = useActiveWeb3React()
- const uniContract = useUniContract()
-
- // check for available votes
- const uni = chainId ? UNI[chainId] : undefined
- const votes = useSingleCallResult(uniContract, 'getCurrentVotes', [account ?? undefined])?.result?.[0]
- return votes && uni ? new TokenAmount(uni, votes) : undefined
-}
-
-// fetch available votes as of block (usually proposal start block)
-export function useUserVotesAsOfBlock(block: number | undefined): TokenAmount | undefined {
- const { account, chainId } = useActiveWeb3React()
- const uniContract = useUniContract()
-
- // check for available votes
- const uni = chainId ? UNI[chainId] : undefined
- const votes = useSingleCallResult(uniContract, 'getPriorVotes', [account ?? undefined, block ?? undefined])
- ?.result?.[0]
- return votes && uni ? new TokenAmount(uni, votes) : undefined
-}
-
-export function useDelegateCallback(): (delegatee: string | undefined) => undefined | Promise<string> {
- const { account, chainId, library } = useActiveWeb3React()
- const addTransaction = useTransactionAdder()
-
- const uniContract = useUniContract()
-
- return useCallback(
- (delegatee: string | undefined) => {
- if (!library || !chainId || !account || !isAddress(delegatee ?? '')) return undefined
- const args = [delegatee]
- if (!uniContract) throw new Error('No UNI Contract!')
- return uniContract.estimateGas.delegate(...args, {}).then((estimatedGasLimit) => {
- return uniContract
- .delegate(...args, { value: null, gasLimit: calculateGasMargin(estimatedGasLimit) })
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: `Delegated votes`,
- })
- return response.hash
- })
- })
- },
- [account, addTransaction, chainId, library, uniContract]
- )
-}
-
-export function useVoteCallback(): {
- voteCallback: (proposalId: string | undefined, support: boolean) => undefined | Promise<string>
-} {
- const { account } = useActiveWeb3React()
-
- const govContract = useGovernanceContract()
- const addTransaction = useTransactionAdder()
-
- const voteCallback = useCallback(
- (proposalId: string | undefined, support: boolean) => {
- if (!account || !govContract || !proposalId) return
- const args = [proposalId, support]
- return govContract.estimateGas.castVote(...args, {}).then((estimatedGasLimit) => {
- return govContract
- .castVote(...args, { value: null, gasLimit: calculateGasMargin(estimatedGasLimit) })
- .then((response: TransactionResponse) => {
- addTransaction(response, {
- summary: `Voted ${support ? 'for ' : 'against'} proposal ${proposalId}`,
- })
- return response.hash
- })
- })
- },
- [account, addTransaction, govContract]
- )
- return { voteCallback }
-}
diff --git a/src/state/index.ts b/src/state/index.ts
index f88ab03..a393e82 100644
--- a/src/state/index.ts
+++ b/src/state/index.ts
@@ -4,11 +4,7 @@ import { save, load } from 'redux-localstorage-simple'
import application from './application/reducer'
import { updateVersion } from './global/actions'
import user from './user/reducer'
-import transactions from './transactions/reducer'
-import swap from './swap/reducer'
-import mint from './mint/reducer'
import lists from './lists/reducer'
-import burn from './burn/reducer'
import multicall from './multicall/reducer'
const PERSISTED_KEYS: string[] = ['user', 'transactions', 'lists']
@@ -17,10 +13,6 @@ const store = configureStore({
reducer: {
application,
user,
- transactions,
- swap,
- mint,
- burn,
multicall,
lists,
},
diff --git a/src/state/mint/actions.ts b/src/state/mint/actions.ts
deleted file mode 100644
index 7849f53..0000000
--- a/src/state/mint/actions.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { createAction } from '@reduxjs/toolkit'
-
-export enum Field {
- CURRENCY_A = 'CURRENCY_A',
- CURRENCY_B = 'CURRENCY_B',
-}
-
-export enum Bound {
- CURRENT = 'CURRENT',
- LOWER = 'LOWER',
- UPPER = 'UPPER',
-}
-
-export enum RangeType {
- PERCENT = 'PERCENT',
- RATE = 'RATE',
-}
-
-export const typeInput = createAction<{ field: Field; typedValue: string; noLiquidity: boolean }>('mint/typeInputMint')
-export const typeLowerRangeInput = createAction<{ typedValue: string }>('mint/typeLowerRangeInput')
-export const typeUpperRangeInput = createAction<{ typedValue: string }>('mint/typeUpperRangeInput')
-export const updateRangeType = createAction<{ rangeType: RangeType }>('mint/updateRangeType')
-export const resetMintState = createAction<void>('mint/resetMintState')
diff --git a/src/state/mint/hooks.ts b/src/state/mint/hooks.ts
deleted file mode 100644
index 3f57124..0000000
--- a/src/state/mint/hooks.ts
+++ /dev/null
@@ -1,250 +0,0 @@
-import { Currency, CurrencyAmount, ETHER, JSBI, Pair, Percent, Price, TokenAmount } from '@uniswap/sdk'
-import { useCallback, useMemo } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { PairState, usePair } from '../../data/Reserves'
-import { useTotalSupply } from '../../data/TotalSupply'
-
-import { useActiveWeb3React } from '../../hooks'
-import { wrappedCurrency, wrappedCurrencyAmount } from '../../utils/wrappedCurrency'
-import { AppDispatch, AppState } from '../index'
-import { tryParseAmount } from '../swap/hooks'
-import { useCurrencyBalances } from '../wallet/hooks'
-import {
- Field,
- Bound,
- typeInput,
- typeLowerRangeInput,
- typeUpperRangeInput,
- RangeType,
- updateRangeType as updateRangeTypeAction,
-} from './actions'
-import { tryParseTick } from './utils'
-
-const ZERO = JSBI.BigInt(0)
-
-export function useMintState(): AppState['mint'] {
- return useSelector<AppState, AppState['mint']>((state) => state.mint)
-}
-
-export function useMintActionHandlers(
- noLiquidity: boolean | undefined
-): {
- onFieldAInput: (typedValue: string) => void
- onFieldBInput: (typedValue: string) => void
- onLowerRangeInput: (typedValue: string) => void
- onUpperRangeInput: (typedValue: string) => void
- updateRangeType: (rangetype: RangeType) => void
-} {
- const dispatch = useDispatch<AppDispatch>()
-
- const onFieldAInput = useCallback(
- (typedValue: string) => {
- dispatch(typeInput({ field: Field.CURRENCY_A, typedValue, noLiquidity: noLiquidity === true }))
- },
- [dispatch, noLiquidity]
- )
-
- const onFieldBInput = useCallback(
- (typedValue: string) => {
- dispatch(typeInput({ field: Field.CURRENCY_B, typedValue, noLiquidity: noLiquidity === true }))
- },
- [dispatch, noLiquidity]
- )
-
- const onLowerRangeInput = useCallback(
- (typedValue: string) => {
- dispatch(typeLowerRangeInput({ typedValue }))
- },
- [dispatch]
- )
-
- const onUpperRangeInput = useCallback(
- (typedValue: string) => {
- dispatch(typeUpperRangeInput({ typedValue }))
- },
- [dispatch]
- )
-
- const updateRangeType = useCallback(
- (rangeType: RangeType) => {
- dispatch(updateRangeTypeAction({ rangeType }))
- },
- [dispatch]
- )
-
- return {
- onFieldAInput,
- onFieldBInput,
- onLowerRangeInput,
- onUpperRangeInput,
- updateRangeType,
- }
-}
-
-// dummy entity
-export interface Tick {
- rate: number
-}
-
-export function useDerivedMintInfo(
- currencyA: Currency | undefined,
- currencyB: Currency | undefined
-): {
- dependentField: Field
- currencies: { [field in Field]?: Currency }
- pair?: Pair | null
- pairState: PairState
- currencyBalances: { [field in Field]?: CurrencyAmount }
- parsedAmounts: { [field in Field]?: CurrencyAmount }
- ticks: { [bound in Bound]?: Tick }
- price?: Price
- noLiquidity?: boolean
- liquidityMinted?: TokenAmount
- poolTokenPercentage?: Percent
- error?: string
-} {
- const { account, chainId } = useActiveWeb3React()
-
- const { independentField, typedValue, otherTypedValue, lowerRangeTypedValue, upperRangeTypedValue } = useMintState()
-
- const dependentField = independentField === Field.CURRENCY_A ? Field.CURRENCY_B : Field.CURRENCY_A
-
- // tokens
- const currencies: { [field in Field]?: Currency } = useMemo(
- () => ({
- [Field.CURRENCY_A]: currencyA ?? undefined,
- [Field.CURRENCY_B]: currencyB ?? undefined,
- }),
- [currencyA, currencyB]
- )
-
- // pair
- const [pairState, pair] = usePair(currencies[Field.CURRENCY_A], currencies[Field.CURRENCY_B])
- const totalSupply = useTotalSupply(pair?.liquidityToken)
-
- const noLiquidity: boolean =
- pairState === PairState.NOT_EXISTS || Boolean(totalSupply && JSBI.equal(totalSupply.raw, ZERO))
-
- // balances
- const balances = useCurrencyBalances(account ?? undefined, [
- currencies[Field.CURRENCY_A],
- currencies[Field.CURRENCY_B],
- ])
- const currencyBalances: { [field in Field]?: CurrencyAmount } = {
- [Field.CURRENCY_A]: balances[0],
- [Field.CURRENCY_B]: balances[1],
- }
-
- // amounts
- const independentAmount: CurrencyAmount | undefined = tryParseAmount(typedValue, currencies[independentField])
- const dependentAmount: CurrencyAmount | undefined = useMemo(() => {
- if (noLiquidity) {
- if (otherTypedValue && currencies[dependentField]) {
- return tryParseAmount(otherTypedValue, currencies[dependentField])
- }
- return undefined
- } else if (independentAmount) {
- // we wrap the currencies just to get the price in terms of the other token
- const wrappedIndependentAmount = wrappedCurrencyAmount(independentAmount, chainId)
- const [tokenA, tokenB] = [wrappedCurrency(currencyA, chainId), wrappedCurrency(currencyB, chainId)]
- if (tokenA && tokenB && wrappedIndependentAmount && pair) {
- const dependentCurrency = dependentField === Field.CURRENCY_B ? currencyB : currencyA
- const dependentTokenAmount =
- dependentField === Field.CURRENCY_B
- ? pair.priceOf(tokenA).quote(wrappedIndependentAmount)
- : pair.priceOf(tokenB).quote(wrappedIndependentAmount)
- return dependentCurrency === ETHER ? CurrencyAmount.ether(dependentTokenAmount.raw) : dependentTokenAmount
- }
- return undefined
- } else {
- return undefined
- }
- }, [noLiquidity, otherTypedValue, currencies, dependentField, independentAmount, currencyA, chainId, currencyB, pair])
-
- const parsedAmounts: { [field in Field]: CurrencyAmount | undefined } = useMemo(() => {
- return {
- [Field.CURRENCY_A]: independentField === Field.CURRENCY_A ? independentAmount : dependentAmount,
- [Field.CURRENCY_B]: independentField === Field.CURRENCY_A ? dependentAmount : independentAmount,
- }
- }, [dependentAmount, independentAmount, independentField])
-
- const price = useMemo(() => {
- if (noLiquidity) {
- const { [Field.CURRENCY_A]: currencyAAmount, [Field.CURRENCY_B]: currencyBAmount } = parsedAmounts
- if (currencyAAmount && currencyBAmount) {
- return new Price(currencyAAmount.currency, currencyBAmount.currency, currencyAAmount.raw, currencyBAmount.raw)
- }
- return undefined
- } else {
- const wrappedCurrencyA = wrappedCurrency(currencyA, chainId)
- return pair && wrappedCurrencyA ? pair.priceOf(wrappedCurrencyA) : undefined
- }
- }, [chainId, currencyA, noLiquidity, pair, parsedAmounts])
-
- // parse typed range values and determine closest ticks, dummy rn
- const ticks = {
- [Bound.CURRENT]: { rate: parseFloat(price?.toFixed(6) ?? '0') },
- [Bound.LOWER]: tryParseTick(lowerRangeTypedValue),
- [Bound.UPPER]: tryParseTick(upperRangeTypedValue),
- }
-
- // liquidity minted
- const liquidityMinted = useMemo(() => {
- const { [Field.CURRENCY_A]: currencyAAmount, [Field.CURRENCY_B]: currencyBAmount } = parsedAmounts
- const [tokenAmountA, tokenAmountB] = [
- wrappedCurrencyAmount(currencyAAmount, chainId),
- wrappedCurrencyAmount(currencyBAmount, chainId),
- ]
- if (pair && totalSupply && tokenAmountA && tokenAmountB) {
- return pair.getLiquidityMinted(totalSupply, tokenAmountA, tokenAmountB)
- } else {
- return undefined
- }
- }, [parsedAmounts, chainId, pair, totalSupply])
-
- const poolTokenPercentage = useMemo(() => {
- if (liquidityMinted && totalSupply) {
- return new Percent(liquidityMinted.raw, totalSupply.add(liquidityMinted).raw)
- } else {
- return undefined
- }
- }, [liquidityMinted, totalSupply])
-
- let error: string | undefined
- if (!account) {
- error = 'Connect Wallet'
- }
-
- if (pairState === PairState.INVALID) {
- error = error ?? 'Invalid pair'
- }
-
- if (!parsedAmounts[Field.CURRENCY_A] || !parsedAmounts[Field.CURRENCY_B]) {
- error = error ?? 'Enter an amount'
- }
-
- const { [Field.CURRENCY_A]: currencyAAmount, [Field.CURRENCY_B]: currencyBAmount } = parsedAmounts
-
- if (currencyAAmount && currencyBalances?.[Field.CURRENCY_A]?.lessThan(currencyAAmount)) {
- error = 'Insufficient ' + currencies[Field.CURRENCY_A]?.symbol + ' balance'
- }
-
- if (currencyBAmount && currencyBalances?.[Field.CURRENCY_B]?.lessThan(currencyBAmount)) {
- error = 'Insufficient ' + currencies[Field.CURRENCY_B]?.symbol + ' balance'
- }
-
- return {
- dependentField,
- currencies,
- pair,
- pairState,
- currencyBalances,
- parsedAmounts,
- ticks,
- price,
- noLiquidity,
- liquidityMinted,
- poolTokenPercentage,
- error,
- }
-}
diff --git a/src/state/mint/reducer.test.ts b/src/state/mint/reducer.test.ts
deleted file mode 100644
index 92abd42..0000000
--- a/src/state/mint/reducer.test.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { createStore, Store } from 'redux'
-
-import { Field, typeInput } from './actions'
-import reducer, { MintState } from './reducer'
-
-describe('mint reducer', () => {
- let store: Store<MintState>
-
- beforeEach(() => {
- store = createStore(reducer, {
- independentField: Field.CURRENCY_A,
- typedValue: '',
- otherTypedValue: '',
- })
- })
-
- describe('typeInput', () => {
- it('sets typed value', () => {
- store.dispatch(typeInput({ field: Field.CURRENCY_A, typedValue: '1.0', noLiquidity: false }))
- expect(store.getState()).toEqual({ independentField: Field.CURRENCY_A, typedValue: '1.0', otherTypedValue: '' })
- })
- it('clears other value', () => {
- store.dispatch(typeInput({ field: Field.CURRENCY_A, typedValue: '1.0', noLiquidity: false }))
- store.dispatch(typeInput({ field: Field.CURRENCY_B, typedValue: '1.0', noLiquidity: false }))
- expect(store.getState()).toEqual({ independentField: Field.CURRENCY_B, typedValue: '1.0', otherTypedValue: '' })
- })
- })
-})
diff --git a/src/state/mint/reducer.ts b/src/state/mint/reducer.ts
deleted file mode 100644
index 5e1bf67..0000000
--- a/src/state/mint/reducer.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { createReducer } from '@reduxjs/toolkit'
-import {
- Field,
- resetMintState,
- typeInput,
- typeLowerRangeInput,
- typeUpperRangeInput,
- RangeType,
- updateRangeType,
-} from './actions'
-
-export interface MintState {
- readonly independentField: Field
- readonly typedValue: string
- readonly otherTypedValue: string // for the case when there's no liquidity
- readonly lowerRangeTypedValue: string
- readonly upperRangeTypedValue: string
- readonly rangeType: RangeType
-}
-
-const initialState: MintState = {
- independentField: Field.CURRENCY_A,
- typedValue: '',
- otherTypedValue: '',
- lowerRangeTypedValue: '',
- upperRangeTypedValue: '',
- rangeType: RangeType.PERCENT,
-}
-
-export default createReducer<MintState>(initialState, (builder) =>
- builder
- .addCase(resetMintState, () => initialState)
- .addCase(updateRangeType, (state, { payload: { rangeType } }) => {
- return {
- ...state,
- rangeType,
- }
- })
- .addCase(typeLowerRangeInput, (state, { payload: { typedValue } }) => {
- return {
- ...state,
- lowerRangeTypedValue: typedValue,
- }
- })
- .addCase(typeUpperRangeInput, (state, { payload: { typedValue } }) => {
- return {
- ...state,
- upperRangeTypedValue: typedValue,
- }
- })
- .addCase(typeInput, (state, { payload: { field, typedValue, noLiquidity } }) => {
- if (noLiquidity) {
- // they're typing into the field they've last typed in
- if (field === state.independentField) {
- return {
- ...state,
- independentField: field,
- typedValue,
- }
- }
- // they're typing into a new field, store the other value
- else {
- return {
- ...state,
- independentField: field,
- typedValue,
- otherTypedValue: state.typedValue,
- }
- }
- } else {
- return {
- ...state,
- independentField: field,
- typedValue,
- otherTypedValue: '',
- }
- }
- })
-)
diff --git a/src/state/mint/utils.ts b/src/state/mint/utils.ts
deleted file mode 100644
index 71de0c1..0000000
--- a/src/state/mint/utils.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { Tick } from './hooks'
-/**
- * @todo
- * udpate to actually parse input and calculate next tick
- */
-export function tryParseTick(value?: string): Tick | undefined {
- if (!value) {
- return undefined
- }
-
- try {
- return { rate: parseFloat(value) * 0.999 }
- } catch (error) {
- console.debug(`Failed to parse range amount: "${value}"`, error)
- }
-
- return undefined
-}
diff --git a/src/state/stake/hooks.ts b/src/state/stake/hooks.ts
deleted file mode 100644
index 2c8e03e..0000000
--- a/src/state/stake/hooks.ts
+++ /dev/null
@@ -1,289 +0,0 @@
-import { ChainId, CurrencyAmount, JSBI, Token, TokenAmount, WETH, Pair } from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { DAI, UNI, USDC, USDT, WBTC } from '../../constants'
-import { STAKING_REWARDS_INTERFACE } from '../../constants/abis/staking-rewards'
-import { useActiveWeb3React } from '../../hooks'
-import { NEVER_RELOAD, useMultipleContractSingleData } from '../multicall/hooks'
-import { tryParseAmount } from '../swap/hooks'
-import useCurrentBlockTimestamp from 'hooks/useCurrentBlockTimestamp'
-
-export const STAKING_GENESIS = 1600387200
-
-export const REWARDS_DURATION_DAYS = 60
-
-// TODO add staking rewards addresses here
-export const STAKING_REWARDS_INFO: {
- [chainId in ChainId]?: {
- tokens: [Token, Token]
- stakingRewardAddress: string
- }[]
-} = {
- [ChainId.MAINNET]: [
- {
- tokens: [WETH[ChainId.MAINNET], DAI],
- stakingRewardAddress: '0xa1484C3aa22a66C62b77E0AE78E15258bd0cB711',
- },
- {
- tokens: [WETH[ChainId.MAINNET], USDC],
- stakingRewardAddress: '0x7FBa4B8Dc5E7616e59622806932DBea72537A56b',
- },
- {
- tokens: [WETH[ChainId.MAINNET], USDT],
- stakingRewardAddress: '0x6C3e4cb2E96B01F4b866965A91ed4437839A121a',
- },
- {
- tokens: [WETH[ChainId.MAINNET], WBTC],
- stakingRewardAddress: '0xCA35e32e7926b96A9988f61d510E038108d8068e',
- },
- ],
-}
-
-export interface StakingInfo {
- // the address of the reward contract
- stakingRewardAddress: string
- // the tokens involved in this pair
- tokens: [Token, Token]
- // the amount of token currently staked, or undefined if no account
- stakedAmount: TokenAmount
- // the amount of reward token earned by the active account, or undefined if no account
- earnedAmount: TokenAmount
- // the total amount of token staked in the contract
- totalStakedAmount: TokenAmount
- // the amount of token distributed per second to all LPs, constant
- totalRewardRate: TokenAmount
- // the current amount of token distributed to the active account per second.
- // equivalent to percent of total supply * reward rate
- rewardRate: TokenAmount
- // when the period ends
- periodFinish: Date | undefined
- // if pool is active
- active: boolean
- // calculates a hypothetical amount of token distributed to the active account per second.
- getHypotheticalRewardRate: (
- stakedAmount: TokenAmount,
- totalStakedAmount: TokenAmount,
- totalRewardRate: TokenAmount
- ) => TokenAmount
-}
-
-// gets the staking info from the network for the active chain id
-export function useStakingInfo(pairToFilterBy?: Pair | null): StakingInfo[] {
- const { chainId, account } = useActiveWeb3React()
-
- // detect if staking is ended
- const currentBlockTimestamp = useCurrentBlockTimestamp()
-
- const info = useMemo(
- () =>
- chainId
- ? STAKING_REWARDS_INFO[chainId]?.filter((stakingRewardInfo) =>
- pairToFilterBy === undefined
- ? true
- : pairToFilterBy === null
- ? false
- : pairToFilterBy.involvesToken(stakingRewardInfo.tokens[0]) &&
- pairToFilterBy.involvesToken(stakingRewardInfo.tokens[1])
- ) ?? []
- : [],
- [chainId, pairToFilterBy]
- )
-
- const uni = chainId ? UNI[chainId] : undefined
-
- const rewardsAddresses = useMemo(() => info.map(({ stakingRewardAddress }) => stakingRewardAddress), [info])
-
- const accountArg = useMemo(() => [account ?? undefined], [account])
-
- // get all the info from the staking rewards contracts
- const balances = useMultipleContractSingleData(rewardsAddresses, STAKING_REWARDS_INTERFACE, 'balanceOf', accountArg)
- const earnedAmounts = useMultipleContractSingleData(rewardsAddresses, STAKING_REWARDS_INTERFACE, 'earned', accountArg)
- const totalSupplies = useMultipleContractSingleData(rewardsAddresses, STAKING_REWARDS_INTERFACE, 'totalSupply')
-
- // tokens per second, constants
- const rewardRates = useMultipleContractSingleData(
- rewardsAddresses,
- STAKING_REWARDS_INTERFACE,
- 'rewardRate',
- undefined,
- NEVER_RELOAD
- )
- const periodFinishes = useMultipleContractSingleData(
- rewardsAddresses,
- STAKING_REWARDS_INTERFACE,
- 'periodFinish',
- undefined,
- NEVER_RELOAD
- )
-
- return useMemo(() => {
- if (!chainId || !uni) return []
-
- return rewardsAddresses.reduce<StakingInfo[]>((memo, rewardsAddress, index) => {
- // these two are dependent on account
- const balanceState = balances[index]
- const earnedAmountState = earnedAmounts[index]
-
- // these get fetched regardless of account
- const totalSupplyState = totalSupplies[index]
- const rewardRateState = rewardRates[index]
- const periodFinishState = periodFinishes[index]
-
- if (
- // these may be undefined if not logged in
- !balanceState?.loading &&
- !earnedAmountState?.loading &&
- // always need these
- totalSupplyState &&
- !totalSupplyState.loading &&
- rewardRateState &&
- !rewardRateState.loading &&
- periodFinishState &&
- !periodFinishState.loading
- ) {
- if (
- balanceState?.error ||
- earnedAmountState?.error ||
- totalSupplyState.error ||
- rewardRateState.error ||
- periodFinishState.error
- ) {
- console.error('Failed to load staking rewards info')
- return memo
- }
-
- // get the LP token
- const tokens = info[index].tokens
- const dummyPair = new Pair(new TokenAmount(tokens[0], '0'), new TokenAmount(tokens[1], '0'))
-
- // check for account, if no account set to 0
-
- const stakedAmount = new TokenAmount(dummyPair.liquidityToken, JSBI.BigInt(balanceState?.result?.[0] ?? 0))
- const totalStakedAmount = new TokenAmount(dummyPair.liquidityToken, JSBI.BigInt(totalSupplyState.result?.[0]))
- const totalRewardRate = new TokenAmount(uni, JSBI.BigInt(rewardRateState.result?.[0]))
-
- const getHypotheticalRewardRate = (
- stakedAmount: TokenAmount,
- totalStakedAmount: TokenAmount,
- totalRewardRate: TokenAmount
- ): TokenAmount => {
- return new TokenAmount(
- uni,
- JSBI.greaterThan(totalStakedAmount.raw, JSBI.BigInt(0))
- ? JSBI.divide(JSBI.multiply(totalRewardRate.raw, stakedAmount.raw), totalStakedAmount.raw)
- : JSBI.BigInt(0)
- )
- }
-
- const individualRewardRate = getHypotheticalRewardRate(stakedAmount, totalStakedAmount, totalRewardRate)
-
- const periodFinishSeconds = periodFinishState.result?.[0]?.toNumber()
- const periodFinishMs = periodFinishSeconds * 1000
-
- // compare period end timestamp vs current block timestamp (in seconds)
- const active =
- periodFinishSeconds && currentBlockTimestamp ? periodFinishSeconds > currentBlockTimestamp.toNumber() : true
-
- memo.push({
- stakingRewardAddress: rewardsAddress,
- tokens: info[index].tokens,
- periodFinish: periodFinishMs > 0 ? new Date(periodFinishMs) : undefined,
- earnedAmount: new TokenAmount(uni, JSBI.BigInt(earnedAmountState?.result?.[0] ?? 0)),
- rewardRate: individualRewardRate,
- totalRewardRate: totalRewardRate,
- stakedAmount: stakedAmount,
- totalStakedAmount: totalStakedAmount,
- getHypotheticalRewardRate,
- active,
- })
- }
- return memo
- }, [])
- }, [
- balances,
- chainId,
- currentBlockTimestamp,
- earnedAmounts,
- info,
- periodFinishes,
- rewardRates,
- rewardsAddresses,
- totalSupplies,
- uni,
- ])
-}
-
-export function useTotalUniEarned(): TokenAmount | undefined {
- const { chainId } = useActiveWeb3React()
- const uni = chainId ? UNI[chainId] : undefined
- const stakingInfos = useStakingInfo()
-
- return useMemo(() => {
- if (!uni) return undefined
- return (
- stakingInfos?.reduce(
- (accumulator, stakingInfo) => accumulator.add(stakingInfo.earnedAmount),
- new TokenAmount(uni, '0')
- ) ?? new TokenAmount(uni, '0')
- )
- }, [stakingInfos, uni])
-}
-
-// based on typed value
-export function useDerivedStakeInfo(
- typedValue: string,
- stakingToken: Token,
- userLiquidityUnstaked: TokenAmount | undefined
-): {
- parsedAmount?: CurrencyAmount
- error?: string
-} {
- const { account } = useActiveWeb3React()
-
- const parsedInput: CurrencyAmount | undefined = tryParseAmount(typedValue, stakingToken)
-
- const parsedAmount =
- parsedInput && userLiquidityUnstaked && JSBI.lessThanOrEqual(parsedInput.raw, userLiquidityUnstaked.raw)
- ? parsedInput
- : undefined
-
- let error: string | undefined
- if (!account) {
- error = 'Connect Wallet'
- }
- if (!parsedAmount) {
- error = error ?? 'Enter an amount'
- }
-
- return {
- parsedAmount,
- error,
- }
-}
-
-// based on typed value
-export function useDerivedUnstakeInfo(
- typedValue: string,
- stakingAmount: TokenAmount
-): {
- parsedAmount?: CurrencyAmount
- error?: string
-} {
- const { account } = useActiveWeb3React()
-
- const parsedInput: CurrencyAmount | undefined = tryParseAmount(typedValue, stakingAmount.token)
-
- const parsedAmount = parsedInput && JSBI.lessThanOrEqual(parsedInput.raw, stakingAmount.raw) ? parsedInput : undefined
-
- let error: string | undefined
- if (!account) {
- error = 'Connect Wallet'
- }
- if (!parsedAmount) {
- error = error ?? 'Enter an amount'
- }
-
- return {
- parsedAmount,
- error,
- }
-}
diff --git a/src/state/swap/actions.ts b/src/state/swap/actions.ts
deleted file mode 100644
index 19d0fdc..0000000
--- a/src/state/swap/actions.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { createAction } from '@reduxjs/toolkit'
-
-export enum Field {
- INPUT = 'INPUT',
- OUTPUT = 'OUTPUT',
-}
-
-export const selectCurrency = createAction<{ field: Field; currencyId: string }>('swap/selectCurrency')
-export const switchCurrencies = createAction<void>('swap/switchCurrencies')
-export const typeInput = createAction<{ field: Field; typedValue: string }>('swap/typeInput')
-export const replaceSwapState = createAction<{
- field: Field
- typedValue: string
- inputCurrencyId?: string
- outputCurrencyId?: string
- recipient: string | null
-}>('swap/replaceSwapState')
-export const setRecipient = createAction<{ recipient: string | null }>('swap/setRecipient')
diff --git a/src/state/swap/hooks.test.ts b/src/state/swap/hooks.test.ts
deleted file mode 100644
index 056627d..0000000
--- a/src/state/swap/hooks.test.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import { parse } from 'qs'
-import { Field } from './actions'
-import { queryParametersToSwapState } from './hooks'
-
-describe('hooks', () => {
- describe('#queryParametersToSwapState', () => {
- test('ETH to DAI', () => {
- expect(
- queryParametersToSwapState(
- parse(
- '?inputCurrency=ETH&outputCurrency=0x6b175474e89094c44da98b954eedeac495271d0f&exactAmount=20.5&exactField=outPUT',
- { parseArrays: false, ignoreQueryPrefix: true }
- )
- )
- ).toEqual({
- [Field.OUTPUT]: { currencyId: '0x6B175474E89094C44Da98b954EedeAC495271d0F' },
- [Field.INPUT]: { currencyId: 'ETH' },
- typedValue: '20.5',
- independentField: Field.OUTPUT,
- recipient: null,
- })
- })
-
- test('does not duplicate eth for invalid output token', () => {
- expect(
- queryParametersToSwapState(parse('?outputCurrency=invalid', { parseArrays: false, ignoreQueryPrefix: true }))
- ).toEqual({
- [Field.INPUT]: { currencyId: '' },
- [Field.OUTPUT]: { currencyId: 'ETH' },
- typedValue: '',
- independentField: Field.INPUT,
- recipient: null,
- })
- })
-
- test('output ETH only', () => {
- expect(
- queryParametersToSwapState(
- parse('?outputCurrency=eth&exactAmount=20.5', { parseArrays: false, ignoreQueryPrefix: true })
- )
- ).toEqual({
- [Field.OUTPUT]: { currencyId: 'ETH' },
- [Field.INPUT]: { currencyId: '' },
- typedValue: '20.5',
- independentField: Field.INPUT,
- recipient: null,
- })
- })
-
- test('invalid recipient', () => {
- expect(
- queryParametersToSwapState(
- parse('?outputCurrency=eth&exactAmount=20.5&recipient=abc', { parseArrays: false, ignoreQueryPrefix: true })
- )
- ).toEqual({
- [Field.OUTPUT]: { currencyId: 'ETH' },
- [Field.INPUT]: { currencyId: '' },
- typedValue: '20.5',
- independentField: Field.INPUT,
- recipient: null,
- })
- })
-
- test('valid recipient', () => {
- expect(
- queryParametersToSwapState(
- parse('?outputCurrency=eth&exactAmount=20.5&recipient=0x0fF2D1eFd7A57B7562b2bf27F3f37899dB27F4a5', {
- parseArrays: false,
- ignoreQueryPrefix: true,
- })
- )
- ).toEqual({
- [Field.OUTPUT]: { currencyId: 'ETH' },
- [Field.INPUT]: { currencyId: '' },
- typedValue: '20.5',
- independentField: Field.INPUT,
- recipient: '0x0fF2D1eFd7A57B7562b2bf27F3f37899dB27F4a5',
- })
- })
- test('accepts any recipient', () => {
- expect(
- queryParametersToSwapState(
- parse('?outputCurrency=eth&exactAmount=20.5&recipient=bob.argent.xyz', {
- parseArrays: false,
- ignoreQueryPrefix: true,
- })
- )
- ).toEqual({
- [Field.OUTPUT]: { currencyId: 'ETH' },
- [Field.INPUT]: { currencyId: '' },
- typedValue: '20.5',
- independentField: Field.INPUT,
- recipient: 'bob.argent.xyz',
- })
- })
- })
-})
diff --git a/src/state/swap/hooks.ts b/src/state/swap/hooks.ts
deleted file mode 100644
index 86f593c..0000000
--- a/src/state/swap/hooks.ts
+++ /dev/null
@@ -1,305 +0,0 @@
-import useENS from '../../hooks/useENS'
-import { Version } from '../../hooks/useToggledVersion'
-import { parseUnits } from '@ethersproject/units'
-import { Currency, CurrencyAmount, ETHER, JSBI, Token, TokenAmount, Trade } from '@uniswap/sdk'
-import { ParsedQs } from 'qs'
-import { useCallback, useEffect, useState } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { useV1Trade } from '../../data/V1'
-import { useActiveWeb3React } from '../../hooks'
-import { useCurrency } from '../../hooks/Tokens'
-import { useTradeExactIn, useTradeExactOut } from '../../hooks/Trades'
-import useParsedQueryString from '../../hooks/useParsedQueryString'
-import { isAddress } from '../../utils'
-import { AppDispatch, AppState } from '../index'
-import { useCurrencyBalances } from '../wallet/hooks'
-import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions'
-import { SwapState } from './reducer'
-import useToggledVersion from '../../hooks/useToggledVersion'
-import { useUserSlippageTolerance } from '../user/hooks'
-import { computeSlippageAdjustedAmounts } from '../../utils/prices'
-
-export function useSwapState(): AppState['swap'] {
- return useSelector<AppState, AppState['swap']>((state) => state.swap)
-}
-
-export function useSwapActionHandlers(): {
- onCurrencySelection: (field: Field, currency: Currency) => void
- onSwitchTokens: () => void
- onUserInput: (field: Field, typedValue: string) => void
- onChangeRecipient: (recipient: string | null) => void
-} {
- const dispatch = useDispatch<AppDispatch>()
- const onCurrencySelection = useCallback(
- (field: Field, currency: Currency) => {
- dispatch(
- selectCurrency({
- field,
- currencyId: currency instanceof Token ? currency.address : currency === ETHER ? 'ETH' : '',
- })
- )
- },
- [dispatch]
- )
-
- const onSwitchTokens = useCallback(() => {
- dispatch(switchCurrencies())
- }, [dispatch])
-
- const onUserInput = useCallback(
- (field: Field, typedValue: string) => {
- dispatch(typeInput({ field, typedValue }))
- },
- [dispatch]
- )
-
- const onChangeRecipient = useCallback(
- (recipient: string | null) => {
- dispatch(setRecipient({ recipient }))
- },
- [dispatch]
- )
-
- return {
- onSwitchTokens,
- onCurrencySelection,
- onUserInput,
- onChangeRecipient,
- }
-}
-
-// try to parse a user entered amount for a given token
-export function tryParseAmount(value?: string, currency?: Currency): CurrencyAmount | undefined {
- if (!value || !currency) {
- return undefined
- }
- try {
- const typedValueParsed = parseUnits(value, currency.decimals).toString()
- if (typedValueParsed !== '0') {
- return currency instanceof Token
- ? new TokenAmount(currency, JSBI.BigInt(typedValueParsed))
- : CurrencyAmount.ether(JSBI.BigInt(typedValueParsed))
- }
- } catch (error) {
- // should fail if the user specifies too many decimal places of precision (or maybe exceed max uint?)
- console.debug(`Failed to parse input amount: "${value}"`, error)
- }
- // necessary for all paths to return a value
- return undefined
-}
-
-const BAD_RECIPIENT_ADDRESSES: string[] = [
- '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f', // v2 factory
- '0xf164fC0Ec4E93095b804a4795bBe1e041497b92a', // v2 router 01
- '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', // v2 router 02
-]
-
-/**
- * Returns true if any of the pairs or tokens in a trade have the given checksummed address
- * @param trade to check for the given address
- * @param checksummedAddress address to check in the pairs and tokens
- */
-function involvesAddress(trade: Trade, checksummedAddress: string): boolean {
- return (
- trade.route.path.some((token) => token.address === checksummedAddress) ||
- trade.route.pairs.some((pair) => pair.liquidityToken.address === checksummedAddress)
- )
-}
-
-// from the current swap inputs, compute the best trade and return it.
-export function useDerivedSwapInfo(): {
- currencies: { [field in Field]?: Currency }
- currencyBalances: { [field in Field]?: CurrencyAmount }
- parsedAmount: CurrencyAmount | undefined
- v2Trade: Trade | undefined
- inputError?: string
- v1Trade: Trade | undefined
-} {
- const { account } = useActiveWeb3React()
-
- const toggledVersion = useToggledVersion()
-
- const {
- independentField,
- typedValue,
- [Field.INPUT]: { currencyId: inputCurrencyId },
- [Field.OUTPUT]: { currencyId: outputCurrencyId },
- recipient,
- } = useSwapState()
-
- const inputCurrency = useCurrency(inputCurrencyId)
- const outputCurrency = useCurrency(outputCurrencyId)
- const recipientLookup = useENS(recipient ?? undefined)
- const to: string | null = (recipient === null ? account : recipientLookup.address) ?? null
-
- const relevantTokenBalances = useCurrencyBalances(account ?? undefined, [
- inputCurrency ?? undefined,
- outputCurrency ?? undefined,
- ])
-
- const isExactIn: boolean = independentField === Field.INPUT
- const parsedAmount = tryParseAmount(typedValue, (isExactIn ? inputCurrency : outputCurrency) ?? undefined)
-
- const bestTradeExactIn = useTradeExactIn(isExactIn ? parsedAmount : undefined, outputCurrency ?? undefined)
- const bestTradeExactOut = useTradeExactOut(inputCurrency ?? undefined, !isExactIn ? parsedAmount : undefined)
-
- const v2Trade = isExactIn ? bestTradeExactIn : bestTradeExactOut
-
- const currencyBalances = {
- [Field.INPUT]: relevantTokenBalances[0],
- [Field.OUTPUT]: relevantTokenBalances[1],
- }
-
- const currencies: { [field in Field]?: Currency } = {
- [Field.INPUT]: inputCurrency ?? undefined,
- [Field.OUTPUT]: outputCurrency ?? undefined,
- }
-
- // get link to trade on v1, if a better rate exists
- const v1Trade = useV1Trade(isExactIn, currencies[Field.INPUT], currencies[Field.OUTPUT], parsedAmount)
-
- let inputError: string | undefined
- if (!account) {
- inputError = 'Connect Wallet'
- }
-
- if (!parsedAmount) {
- inputError = inputError ?? 'Enter an amount'
- }
-
- if (!currencies[Field.INPUT] || !currencies[Field.OUTPUT]) {
- inputError = inputError ?? 'Select a token'
- }
-
- const formattedTo = isAddress(to)
- if (!to || !formattedTo) {
- inputError = inputError ?? 'Enter a recipient'
- } else {
- if (
- BAD_RECIPIENT_ADDRESSES.indexOf(formattedTo) !== -1 ||
- (bestTradeExactIn && involvesAddress(bestTradeExactIn, formattedTo)) ||
- (bestTradeExactOut && involvesAddress(bestTradeExactOut, formattedTo))
- ) {
- inputError = inputError ?? 'Invalid recipient'
- }
- }
-
- const [allowedSlippage] = useUserSlippageTolerance()
-
- const slippageAdjustedAmounts = v2Trade && allowedSlippage && computeSlippageAdjustedAmounts(v2Trade, allowedSlippage)
-
- const slippageAdjustedAmountsV1 =
- v1Trade && allowedSlippage && computeSlippageAdjustedAmounts(v1Trade, allowedSlippage)
-
- // compare input balance to max input based on version
- const [balanceIn, amountIn] = [
- currencyBalances[Field.INPUT],
- toggledVersion === Version.v1
- ? slippageAdjustedAmountsV1
- ? slippageAdjustedAmountsV1[Field.INPUT]
- : null
- : slippageAdjustedAmounts
- ? slippageAdjustedAmounts[Field.INPUT]
- : null,
- ]
-
- if (balanceIn && amountIn && balanceIn.lessThan(amountIn)) {
- inputError = 'Insufficient ' + amountIn.currency.symbol + ' balance'
- }
-
- return {
- currencies,
- currencyBalances,
- parsedAmount,
- v2Trade: v2Trade ?? undefined,
- inputError,
- v1Trade,
- }
-}
-
-function parseCurrencyFromURLParameter(urlParam: any): string {
- if (typeof urlParam === 'string') {
- const valid = isAddress(urlParam)
- if (valid) return valid
- if (urlParam.toUpperCase() === 'ETH') return 'ETH'
- if (valid === false) return 'ETH'
- }
- return 'ETH' ?? ''
-}
-
-function parseTokenAmountURLParameter(urlParam: any): string {
- return typeof urlParam === 'string' && !isNaN(parseFloat(urlParam)) ? urlParam : ''
-}
-
-function parseIndependentFieldURLParameter(urlParam: any): Field {
- return typeof urlParam === 'string' && urlParam.toLowerCase() === 'output' ? Field.OUTPUT : Field.INPUT
-}
-
-const ENS_NAME_REGEX = /^[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)?$/
-const ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/
-function validatedRecipient(recipient: any): string | null {
- if (typeof recipient !== 'string') return null
- const address = isAddress(recipient)
- if (address) return address
- if (ENS_NAME_REGEX.test(recipient)) return recipient
- if (ADDRESS_REGEX.test(recipient)) return recipient
- return null
-}
-
-export function queryParametersToSwapState(parsedQs: ParsedQs): SwapState {
- let inputCurrency = parseCurrencyFromURLParameter(parsedQs.inputCurrency)
- let outputCurrency = parseCurrencyFromURLParameter(parsedQs.outputCurrency)
- if (inputCurrency === outputCurrency) {
- if (typeof parsedQs.outputCurrency === 'string') {
- inputCurrency = ''
- } else {
- outputCurrency = ''
- }
- }
-
- const recipient = validatedRecipient(parsedQs.recipient)
-
- return {
- [Field.INPUT]: {
- currencyId: inputCurrency,
- },
- [Field.OUTPUT]: {
- currencyId: outputCurrency,
- },
- typedValue: parseTokenAmountURLParameter(parsedQs.exactAmount),
- independentField: parseIndependentFieldURLParameter(parsedQs.exactField),
- recipient,
- }
-}
-
-// updates the swap state to use the defaults for a given network
-export function useDefaultsFromURLSearch():
- | { inputCurrencyId: string | undefined; outputCurrencyId: string | undefined }
- | undefined {
- const { chainId } = useActiveWeb3React()
- const dispatch = useDispatch<AppDispatch>()
- const parsedQs = useParsedQueryString()
- const [result, setResult] = useState<
- { inputCurrencyId: string | undefined; outputCurrencyId: string | undefined } | undefined
- >()
-
- useEffect(() => {
- if (!chainId) return
- const parsed = queryParametersToSwapState(parsedQs)
-
- dispatch(
- replaceSwapState({
- typedValue: parsed.typedValue,
- field: parsed.independentField,
- inputCurrencyId: parsed[Field.INPUT].currencyId,
- outputCurrencyId: parsed[Field.OUTPUT].currencyId,
- recipient: parsed.recipient,
- })
- )
-
- setResult({ inputCurrencyId: parsed[Field.INPUT].currencyId, outputCurrencyId: parsed[Field.OUTPUT].currencyId })
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [dispatch, chainId])
-
- return result
-}
diff --git a/src/state/swap/reducer.test.ts b/src/state/swap/reducer.test.ts
deleted file mode 100644
index 56e5a7b..0000000
--- a/src/state/swap/reducer.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { createStore, Store } from 'redux'
-import { Field, selectCurrency } from './actions'
-import reducer, { SwapState } from './reducer'
-
-describe('swap reducer', () => {
- let store: Store<SwapState>
-
- beforeEach(() => {
- store = createStore(reducer, {
- [Field.OUTPUT]: { currencyId: '' },
- [Field.INPUT]: { currencyId: '' },
- typedValue: '',
- independentField: Field.INPUT,
- recipient: null,
- })
- })
-
- describe('selectToken', () => {
- it('changes token', () => {
- store.dispatch(
- selectCurrency({
- field: Field.OUTPUT,
- currencyId: '0x0000',
- })
- )
-
- expect(store.getState()).toEqual({
- [Field.OUTPUT]: { currencyId: '0x0000' },
- [Field.INPUT]: { currencyId: '' },
- typedValue: '',
- independentField: Field.INPUT,
- recipient: null,
- })
- })
- })
-})
diff --git a/src/state/swap/reducer.ts b/src/state/swap/reducer.ts
deleted file mode 100644
index 19fb304..0000000
--- a/src/state/swap/reducer.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-import { createReducer } from '@reduxjs/toolkit'
-import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions'
-
-export interface SwapState {
- readonly independentField: Field
- readonly typedValue: string
- readonly [Field.INPUT]: {
- readonly currencyId: string | undefined
- }
- readonly [Field.OUTPUT]: {
- readonly currencyId: string | undefined
- }
- // the typed recipient address or ENS name, or null if swap should go to sender
- readonly recipient: string | null
-}
-
-const initialState: SwapState = {
- independentField: Field.INPUT,
- typedValue: '',
- [Field.INPUT]: {
- currencyId: '',
- },
- [Field.OUTPUT]: {
- currencyId: '',
- },
- recipient: null,
-}
-
-export default createReducer<SwapState>(initialState, (builder) =>
- builder
- .addCase(
- replaceSwapState,
- (state, { payload: { typedValue, recipient, field, inputCurrencyId, outputCurrencyId } }) => {
- return {
- [Field.INPUT]: {
- currencyId: inputCurrencyId,
- },
- [Field.OUTPUT]: {
- currencyId: outputCurrencyId,
- },
- independentField: field,
- typedValue: typedValue,
- recipient,
- }
- }
- )
- .addCase(selectCurrency, (state, { payload: { currencyId, field } }) => {
- const otherField = field === Field.INPUT ? Field.OUTPUT : Field.INPUT
- if (currencyId === state[otherField].currencyId) {
- // the case where we have to swap the order
- return {
- ...state,
- independentField: state.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT,
- [field]: { currencyId: currencyId },
- [otherField]: { currencyId: state[field].currencyId },
- }
- } else {
- // the normal case
- return {
- ...state,
- [field]: { currencyId: currencyId },
- }
- }
- })
- .addCase(switchCurrencies, (state) => {
- return {
- ...state,
- independentField: state.independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT,
- [Field.INPUT]: { currencyId: state[Field.OUTPUT].currencyId },
- [Field.OUTPUT]: { currencyId: state[Field.INPUT].currencyId },
- }
- })
- .addCase(typeInput, (state, { payload: { field, typedValue } }) => {
- return {
- ...state,
- independentField: field,
- typedValue,
- }
- })
- .addCase(setRecipient, (state, { payload: { recipient } }) => {
- state.recipient = recipient
- })
-)
diff --git a/src/state/transactions/actions.ts b/src/state/transactions/actions.ts
deleted file mode 100644
index 86a8c6a..0000000
--- a/src/state/transactions/actions.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { createAction } from '@reduxjs/toolkit'
-import { ChainId } from '@uniswap/sdk'
-
-export interface SerializableTransactionReceipt {
- to: string
- from: string
- contractAddress: string
- transactionIndex: number
- blockHash: string
- transactionHash: string
- blockNumber: number
- status?: number
-}
-
-export const addTransaction = createAction<{
- chainId: ChainId
- hash: string
- from: string
- approval?: { tokenAddress: string; spender: string }
- claim?: { recipient: string }
- summary?: string
-}>('transactions/addTransaction')
-export const clearAllTransactions = createAction<{ chainId: ChainId }>('transactions/clearAllTransactions')
-export const finalizeTransaction = createAction<{
- chainId: ChainId
- hash: string
- receipt: SerializableTransactionReceipt
-}>('transactions/finalizeTransaction')
-export const checkedTransaction = createAction<{
- chainId: ChainId
- hash: string
- blockNumber: number
-}>('transactions/checkedTransaction')
diff --git a/src/state/transactions/hooks.tsx b/src/state/transactions/hooks.tsx
deleted file mode 100644
index c971609..0000000
--- a/src/state/transactions/hooks.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { TransactionResponse } from '@ethersproject/providers'
-import { useCallback, useMemo } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-
-import { useActiveWeb3React } from '../../hooks'
-import { AppDispatch, AppState } from '../index'
-import { addTransaction } from './actions'
-import { TransactionDetails } from './reducer'
-
-// helper that can take a ethers library transaction response and add it to the list of transactions
-export function useTransactionAdder(): (
- response: TransactionResponse,
- customData?: { summary?: string; approval?: { tokenAddress: string; spender: string }; claim?: { recipient: string } }
-) => void {
- const { chainId, account } = useActiveWeb3React()
- const dispatch = useDispatch<AppDispatch>()
-
- return useCallback(
- (
- response: TransactionResponse,
- {
- summary,
- approval,
- claim,
- }: { summary?: string; claim?: { recipient: string }; approval?: { tokenAddress: string; spender: string } } = {}
- ) => {
- if (!account) return
- if (!chainId) return
-
- const { hash } = response
- if (!hash) {
- throw Error('No transaction hash found.')
- }
- dispatch(addTransaction({ hash, from: account, chainId, approval, summary, claim }))
- },
- [dispatch, chainId, account]
- )
-}
-
-// returns all the transactions for the current chain
-export function useAllTransactions(): { [txHash: string]: TransactionDetails } {
- const { chainId } = useActiveWeb3React()
-
- const state = useSelector<AppState, AppState['transactions']>((state) => state.transactions)
-
- return chainId ? state[chainId] ?? {} : {}
-}
-
-export function useIsTransactionPending(transactionHash?: string): boolean {
- const transactions = useAllTransactions()
-
- if (!transactionHash || !transactions[transactionHash]) return false
-
- return !transactions[transactionHash].receipt
-}
-
-/**
- * Returns whether a transaction happened in the last day (86400 seconds * 1000 milliseconds / second)
- * @param tx to check for recency
- */
-export function isTransactionRecent(tx: TransactionDetails): boolean {
- return new Date().getTime() - tx.addedTime < 86_400_000
-}
-
-// returns whether a token has a pending approval transaction
-export function useHasPendingApproval(tokenAddress: string | undefined, spender: string | undefined): boolean {
- const allTransactions = useAllTransactions()
- return useMemo(
- () =>
- typeof tokenAddress === 'string' &&
- typeof spender === 'string' &&
- Object.keys(allTransactions).some((hash) => {
- const tx = allTransactions[hash]
- if (!tx) return false
- if (tx.receipt) {
- return false
- } else {
- const approval = tx.approval
- if (!approval) return false
- return approval.spender === spender && approval.tokenAddress === tokenAddress && isTransactionRecent(tx)
- }
- }),
- [allTransactions, spender, tokenAddress]
- )
-}
-
-// watch for submissions to claim
-// return null if not done loading, return undefined if not found
-export function useUserHasSubmittedClaim(
- account?: string
-): { claimSubmitted: boolean; claimTxn: TransactionDetails | undefined } {
- const allTransactions = useAllTransactions()
-
- // get the txn if it has been submitted
- const claimTxn = useMemo(() => {
- const txnIndex = Object.keys(allTransactions).find((hash) => {
- const tx = allTransactions[hash]
- return tx.claim && tx.claim.recipient === account
- })
- return txnIndex && allTransactions[txnIndex] ? allTransactions[txnIndex] : undefined
- }, [account, allTransactions])
-
- return { claimSubmitted: Boolean(claimTxn), claimTxn }
-}
diff --git a/src/state/transactions/reducer.test.ts b/src/state/transactions/reducer.test.ts
deleted file mode 100644
index 35292b6..0000000
--- a/src/state/transactions/reducer.test.ts
+++ /dev/null
@@ -1,192 +0,0 @@
-import { ChainId } from '@uniswap/sdk'
-import { createStore, Store } from 'redux'
-import { addTransaction, checkedTransaction, clearAllTransactions, finalizeTransaction } from './actions'
-import reducer, { initialState, TransactionState } from './reducer'
-
-describe('transaction reducer', () => {
- let store: Store<TransactionState>
-
- beforeEach(() => {
- store = createStore(reducer, initialState)
- })
-
- describe('addTransaction', () => {
- it('adds the transaction', () => {
- const beforeTime = new Date().getTime()
- store.dispatch(
- addTransaction({
- chainId: ChainId.MAINNET,
- summary: 'hello world',
- hash: '0x0',
- approval: { tokenAddress: 'abc', spender: 'def' },
- from: 'abc',
- })
- )
- const txs = store.getState()
- expect(txs[ChainId.MAINNET]).toBeTruthy()
- expect(txs[ChainId.MAINNET]?.['0x0']).toBeTruthy()
- const tx = txs[ChainId.MAINNET]?.['0x0']
- expect(tx).toBeTruthy()
- expect(tx?.hash).toEqual('0x0')
- expect(tx?.summary).toEqual('hello world')
- expect(tx?.approval).toEqual({ tokenAddress: 'abc', spender: 'def' })
- expect(tx?.from).toEqual('abc')
- expect(tx?.addedTime).toBeGreaterThanOrEqual(beforeTime)
- })
- })
-
- describe('finalizeTransaction', () => {
- it('no op if not valid transaction', () => {
- store.dispatch(
- finalizeTransaction({
- chainId: ChainId.RINKEBY,
- hash: '0x0',
- receipt: {
- status: 1,
- transactionIndex: 1,
- transactionHash: '0x0',
- to: '0x0',
- from: '0x0',
- contractAddress: '0x0',
- blockHash: '0x0',
- blockNumber: 1,
- },
- })
- )
- expect(store.getState()).toEqual({})
- })
- it('sets receipt', () => {
- store.dispatch(
- addTransaction({
- hash: '0x0',
- chainId: ChainId.RINKEBY,
- approval: { spender: '0x0', tokenAddress: '0x0' },
- summary: 'hello world',
- from: '0x0',
- })
- )
- const beforeTime = new Date().getTime()
- store.dispatch(
- finalizeTransaction({
- chainId: ChainId.RINKEBY,
- hash: '0x0',
- receipt: {
- status: 1,
- transactionIndex: 1,
- transactionHash: '0x0',
- to: '0x0',
- from: '0x0',
- contractAddress: '0x0',
- blockHash: '0x0',
- blockNumber: 1,
- },
- })
- )
- const tx = store.getState()[ChainId.RINKEBY]?.['0x0']
- expect(tx?.summary).toEqual('hello world')
- expect(tx?.confirmedTime).toBeGreaterThanOrEqual(beforeTime)
- expect(tx?.receipt).toEqual({
- status: 1,
- transactionIndex: 1,
- transactionHash: '0x0',
- to: '0x0',
- from: '0x0',
- contractAddress: '0x0',
- blockHash: '0x0',
- blockNumber: 1,
- })
- })
- })
-
- describe('checkedTransaction', () => {
- it('no op if not valid transaction', () => {
- store.dispatch(
- checkedTransaction({
- chainId: ChainId.RINKEBY,
- hash: '0x0',
- blockNumber: 1,
- })
- )
- expect(store.getState()).toEqual({})
- })
- it('sets lastCheckedBlockNumber', () => {
- store.dispatch(
- addTransaction({
- hash: '0x0',
- chainId: ChainId.RINKEBY,
- approval: { spender: '0x0', tokenAddress: '0x0' },
- summary: 'hello world',
- from: '0x0',
- })
- )
- store.dispatch(
- checkedTransaction({
- chainId: ChainId.RINKEBY,
- hash: '0x0',
- blockNumber: 1,
- })
- )
- const tx = store.getState()[ChainId.RINKEBY]?.['0x0']
- expect(tx?.lastCheckedBlockNumber).toEqual(1)
- })
- it('never decreases', () => {
- store.dispatch(
- addTransaction({
- hash: '0x0',
- chainId: ChainId.RINKEBY,
- approval: { spender: '0x0', tokenAddress: '0x0' },
- summary: 'hello world',
- from: '0x0',
- })
- )
- store.dispatch(
- checkedTransaction({
- chainId: ChainId.RINKEBY,
- hash: '0x0',
- blockNumber: 3,
- })
- )
- store.dispatch(
- checkedTransaction({
- chainId: ChainId.RINKEBY,
- hash: '0x0',
- blockNumber: 1,
- })
- )
- const tx = store.getState()[ChainId.RINKEBY]?.['0x0']
- expect(tx?.lastCheckedBlockNumber).toEqual(3)
- })
- })
-
- describe('clearAllTransactions', () => {
- it('removes all transactions for the chain', () => {
- store.dispatch(
- addTransaction({
- chainId: ChainId.MAINNET,
- summary: 'hello world',
- hash: '0x0',
- approval: { tokenAddress: 'abc', spender: 'def' },
- from: 'abc',
- })
- )
- store.dispatch(
- addTransaction({
- chainId: ChainId.RINKEBY,
- summary: 'hello world',
- hash: '0x1',
- approval: { tokenAddress: 'abc', spender: 'def' },
- from: 'abc',
- })
- )
- expect(Object.keys(store.getState())).toHaveLength(2)
- expect(Object.keys(store.getState())).toEqual([String(ChainId.MAINNET), String(ChainId.RINKEBY)])
- expect(Object.keys(store.getState()[ChainId.MAINNET] ?? {})).toEqual(['0x0'])
- expect(Object.keys(store.getState()[ChainId.RINKEBY] ?? {})).toEqual(['0x1'])
- store.dispatch(clearAllTransactions({ chainId: ChainId.MAINNET }))
- expect(Object.keys(store.getState())).toHaveLength(2)
- expect(Object.keys(store.getState())).toEqual([String(ChainId.MAINNET), String(ChainId.RINKEBY)])
- expect(Object.keys(store.getState()[ChainId.MAINNET] ?? {})).toEqual([])
- expect(Object.keys(store.getState()[ChainId.RINKEBY] ?? {})).toEqual(['0x1'])
- })
- })
-})
diff --git a/src/state/transactions/reducer.ts b/src/state/transactions/reducer.ts
deleted file mode 100644
index 3553567..0000000
--- a/src/state/transactions/reducer.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import { createReducer } from '@reduxjs/toolkit'
-import {
- addTransaction,
- checkedTransaction,
- clearAllTransactions,
- finalizeTransaction,
- SerializableTransactionReceipt,
-} from './actions'
-
-const now = () => new Date().getTime()
-
-export interface TransactionDetails {
- hash: string
- approval?: { tokenAddress: string; spender: string }
- summary?: string
- claim?: { recipient: string }
- receipt?: SerializableTransactionReceipt
- lastCheckedBlockNumber?: number
- addedTime: number
- confirmedTime?: number
- from: string
-}
-
-export interface TransactionState {
- [chainId: number]: {
- [txHash: string]: TransactionDetails
- }
-}
-
-export const initialState: TransactionState = {}
-
-export default createReducer(initialState, (builder) =>
- builder
- .addCase(addTransaction, (transactions, { payload: { chainId, from, hash, approval, summary, claim } }) => {
- if (transactions[chainId]?.[hash]) {
- throw Error('Attempted to add existing transaction.')
- }
- const txs = transactions[chainId] ?? {}
- txs[hash] = { hash, approval, summary, claim, from, addedTime: now() }
- transactions[chainId] = txs
- })
- .addCase(clearAllTransactions, (transactions, { payload: { chainId } }) => {
- if (!transactions[chainId]) return
- transactions[chainId] = {}
- })
- .addCase(checkedTransaction, (transactions, { payload: { chainId, hash, blockNumber } }) => {
- const tx = transactions[chainId]?.[hash]
- if (!tx) {
- return
- }
- if (!tx.lastCheckedBlockNumber) {
- tx.lastCheckedBlockNumber = blockNumber
- } else {
- tx.lastCheckedBlockNumber = Math.max(blockNumber, tx.lastCheckedBlockNumber)
- }
- })
- .addCase(finalizeTransaction, (transactions, { payload: { hash, chainId, receipt } }) => {
- const tx = transactions[chainId]?.[hash]
- if (!tx) {
- return
- }
- tx.receipt = receipt
- tx.confirmedTime = now()
- })
-)
diff --git a/src/state/transactions/updater.test.ts b/src/state/transactions/updater.test.ts
deleted file mode 100644
index 45f5d46..0000000
--- a/src/state/transactions/updater.test.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { shouldCheck } from './updater'
-
-describe('transactions updater', () => {
- describe('shouldCheck', () => {
- it('returns true if no receipt and never checked', () => {
- expect(shouldCheck(10, { addedTime: 100 })).toEqual(true)
- })
- it('returns false if has receipt and never checked', () => {
- expect(shouldCheck(10, { addedTime: 100, receipt: {} })).toEqual(false)
- })
- it('returns true if has not been checked in 1 blocks', () => {
- expect(shouldCheck(10, { addedTime: new Date().getTime(), lastCheckedBlockNumber: 9 })).toEqual(true)
- })
- it('returns false if checked in last 3 blocks and greater than 20 minutes old', () => {
- expect(shouldCheck(10, { addedTime: new Date().getTime() - 21 * 60 * 1000, lastCheckedBlockNumber: 8 })).toEqual(
- false
- )
- })
- it('returns true if not checked in last 5 blocks and greater than 20 minutes old', () => {
- expect(shouldCheck(10, { addedTime: new Date().getTime() - 21 * 60 * 1000, lastCheckedBlockNumber: 5 })).toEqual(
- true
- )
- })
- it('returns false if checked in last 10 blocks and greater than 60 minutes old', () => {
- expect(shouldCheck(20, { addedTime: new Date().getTime() - 61 * 60 * 1000, lastCheckedBlockNumber: 11 })).toEqual(
- false
- )
- })
- it('returns true if checked in last 3 blocks and greater than 20 minutes old', () => {
- expect(shouldCheck(20, { addedTime: new Date().getTime() - 61 * 60 * 1000, lastCheckedBlockNumber: 10 })).toEqual(
- true
- )
- })
- })
-})
diff --git a/src/state/transactions/updater.tsx b/src/state/transactions/updater.tsx
deleted file mode 100644
index b57df76..0000000
--- a/src/state/transactions/updater.tsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import { useEffect } from 'react'
-import { useDispatch, useSelector } from 'react-redux'
-import { useActiveWeb3React } from '../../hooks'
-import { useAddPopup, useBlockNumber } from '../application/hooks'
-import { AppDispatch, AppState } from '../index'
-import { checkedTransaction, finalizeTransaction } from './actions'
-
-interface TxInterface {
- addedTime: number
- receipt?: Record<string, any>
- lastCheckedBlockNumber?: number
-}
-
-export function shouldCheck(lastBlockNumber: number, tx: TxInterface): boolean {
- if (tx.receipt) return false
- if (!tx.lastCheckedBlockNumber) return true
- const blocksSinceCheck = lastBlockNumber - tx.lastCheckedBlockNumber
- if (blocksSinceCheck < 1) return false
- const minutesPending = (new Date().getTime() - tx.addedTime) / 1000 / 60
- if (minutesPending > 60) {
- // every 10 blocks if pending for longer than an hour
- return blocksSinceCheck > 9
- } else if (minutesPending > 5) {
- // every 3 blocks if pending more than 5 minutes
- return blocksSinceCheck > 2
- } else {
- // otherwise every block
- return true
- }
-}
-
-export default function Updater(): null {
- const { chainId, library } = useActiveWeb3React()
-
- const lastBlockNumber = useBlockNumber()
-
- const dispatch = useDispatch<AppDispatch>()
- const state = useSelector<AppState, AppState['transactions']>((state) => state.transactions)
-
- const transactions = chainId ? state[chainId] ?? {} : {}
-
- // show popup on confirm
- const addPopup = useAddPopup()
-
- useEffect(() => {
- if (!chainId || !library || !lastBlockNumber) return
-
- Object.keys(transactions)
- .filter((hash) => shouldCheck(lastBlockNumber, transactions[hash]))
- .forEach((hash) => {
- library
- .getTransactionReceipt(hash)
- .then((receipt) => {
- if (receipt) {
- dispatch(
- finalizeTransaction({
- chainId,
- hash,
- receipt: {
- blockHash: receipt.blockHash,
- blockNumber: receipt.blockNumber,
- contractAddress: receipt.contractAddress,
- from: receipt.from,
- status: receipt.status,
- to: receipt.to,
- transactionHash: receipt.transactionHash,
- transactionIndex: receipt.transactionIndex,
- },
- })
- )
-
- addPopup(
- {
- txn: {
- hash,
- success: receipt.status === 1,
- summary: transactions[hash]?.summary,
- },
- },
- hash
- )
- } else {
- dispatch(checkedTransaction({ chainId, hash, blockNumber: lastBlockNumber }))
- }
- })
- .catch((error) => {
- console.error(`failed to check transaction hash: ${hash}`, error)
- })
- })
- }, [chainId, library, transactions, lastBlockNumber, dispatch, addPopup])
-
- return null
-}
diff --git a/src/state/user/actions.ts b/src/state/user/actions.ts
index f6701c3..5b546c0 100644
--- a/src/state/user/actions.ts
+++ b/src/state/user/actions.ts
@@ -15,12 +15,6 @@ export interface SerializedPair {
export const updateMatchesDarkMode = createAction<{ matchesDarkMode: boolean }>('user/updateMatchesDarkMode')
export const updateUserDarkMode = createAction<{ userDarkMode: boolean }>('user/updateUserDarkMode')
-export const updateUserExpertMode = createAction<{ userExpertMode: boolean }>('user/updateUserExpertMode')
-export const updateUserSingleHopOnly = createAction<{ userSingleHopOnly: boolean }>('user/updateUserSingleHopOnly')
-export const updateUserSlippageTolerance = createAction<{ userSlippageTolerance: number }>(
- 'user/updateUserSlippageTolerance'
-)
-export const updateUserDeadline = createAction<{ userDeadline: number }>('user/updateUserDeadline')
export const addSerializedToken = createAction<{ serializedToken: SerializedToken }>('user/addSerializedToken')
export const removeSerializedToken = createAction<{ chainId: number; address: string }>('user/removeSerializedToken')
export const addSerializedPair = createAction<{ serializedPair: SerializedPair }>('user/addSerializedPair')
diff --git a/src/state/user/hooks.tsx b/src/state/user/hooks.tsx
index 592f07b..5baab41 100644
--- a/src/state/user/hooks.tsx
+++ b/src/state/user/hooks.tsx
@@ -1,12 +1,8 @@
import { ChainId, Pair, Token } from '@uniswap/sdk'
-import flatMap from 'lodash.flatmap'
-import ReactGA from 'react-ga'
import { useCallback, useMemo } from 'react'
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
-import { BASES_TO_TRACK_LIQUIDITY_FOR, PINNED_PAIRS } from '../../constants'
import { useActiveWeb3React } from '../../hooks'
-import { useAllTokens } from '../../hooks/Tokens'
import { AppDispatch, AppState } from '../index'
import {
addSerializedPair,
@@ -15,11 +11,7 @@ import {
SerializedPair,
SerializedToken,
updateUserDarkMode,
- updateUserDeadline,
- updateUserExpertMode,
- updateUserSlippageTolerance,
toggleURLWarning,
- updateUserSingleHopOnly,
} from './actions'
function serializeToken(token: Token): SerializedToken {
@@ -68,74 +60,6 @@ export function useDarkModeManager(): [boolean, () => void] {
return [darkMode, toggleSetDarkMode]
}
-export function useIsExpertMode(): boolean {
- return useSelector<AppState, AppState['user']['userExpertMode']>((state) => state.user.userExpertMode)
-}
-
-export function useExpertModeManager(): [boolean, () => void] {
- const dispatch = useDispatch<AppDispatch>()
- const expertMode = useIsExpertMode()
-
- const toggleSetExpertMode = useCallback(() => {
- dispatch(updateUserExpertMode({ userExpertMode: !expertMode }))
- }, [expertMode, dispatch])
-
- return [expertMode, toggleSetExpertMode]
-}
-
-export function useUserSingleHopOnly(): [boolean, (newSingleHopOnly: boolean) => void] {
- const dispatch = useDispatch<AppDispatch>()
-
- const singleHopOnly = useSelector<AppState, AppState['user']['userSingleHopOnly']>(
- (state) => state.user.userSingleHopOnly
- )
-
- const setSingleHopOnly = useCallback(
- (newSingleHopOnly: boolean) => {
- ReactGA.event({
- category: 'Routing',
- action: newSingleHopOnly ? 'enable single hop' : 'disable single hop',
- })
- dispatch(updateUserSingleHopOnly({ userSingleHopOnly: newSingleHopOnly }))
- },
- [dispatch]
- )
-
- return [singleHopOnly, setSingleHopOnly]
-}
-
-export function useUserSlippageTolerance(): [number, (slippage: number) => void] {
- const dispatch = useDispatch<AppDispatch>()
- const userSlippageTolerance = useSelector<AppState, AppState['user']['userSlippageTolerance']>((state) => {
- return state.user.userSlippageTolerance
- })
-
- const setUserSlippageTolerance = useCallback(
- (userSlippageTolerance: number) => {
- dispatch(updateUserSlippageTolerance({ userSlippageTolerance }))
- },
- [dispatch]
- )
-
- return [userSlippageTolerance, setUserSlippageTolerance]
-}
-
-export function useUserTransactionTTL(): [number, (slippage: number) => void] {
- const dispatch = useDispatch<AppDispatch>()
- const userDeadline = useSelector<AppState, AppState['user']['userDeadline']>((state) => {
- return state.user.userDeadline
- })
-
- const setUserDeadline = useCallback(
- (userDeadline: number) => {
- dispatch(updateUserDeadline({ userDeadline }))
- },
- [dispatch]
- )
-
- return [userDeadline, setUserDeadline]
-}
-
export function useAddUserToken(): (token: Token) => void {
const dispatch = useDispatch<AppDispatch>()
return useCallback(
@@ -192,80 +116,3 @@ export function useURLWarningToggle(): () => void {
const dispatch = useDispatch()
return useCallback(() => dispatch(toggleURLWarning()), [dispatch])
}
-
-/**
- * Given two tokens return the liquidity token that represents its liquidity shares
- * @param tokenA one of the two tokens
- * @param tokenB the other token
- */
-export function toV2LiquidityToken([tokenA, tokenB]: [Token, Token]): Token {
- return new Token(tokenA.chainId, Pair.getAddress(tokenA, tokenB), 18, 'UNI-V2', 'Uniswap V2')
-}
-
-/**
- * Returns all the pairs of tokens that are tracked by the user for the current chain ID.
- */
-export function useTrackedTokenPairs(): [Token, Token][] {
- const { chainId } = useActiveWeb3React()
- const tokens = useAllTokens()
-
- // pinned pairs
- const pinnedPairs = useMemo(() => (chainId ? PINNED_PAIRS[chainId] ?? [] : []), [chainId])
-
- // pairs for every token against every base
- const generatedPairs: [Token, Token][] = useMemo(
- () =>
- chainId
- ? flatMap(Object.keys(tokens), (tokenAddress) => {
- const token = tokens[tokenAddress]
- // for each token on the current chain,
- return (
- // loop though all bases on the current chain
- (BASES_TO_TRACK_LIQUIDITY_FOR[chainId] ?? [])
- // to construct pairs of the given token with each base
- .map((base) => {
- if (base.address === token.address) {
- return null
- } else {
- return [base, token]
- }
- })
- .filter((p): p is [Token, Token] => p !== null)
- )
- })
- : [],
- [tokens, chainId]
- )
-
- // pairs saved by users
- const savedSerializedPairs = useSelector<AppState, AppState['user']['pairs']>(({ user: { pairs } }) => pairs)
-
- const userPairs: [Token, Token][] = useMemo(() => {
- if (!chainId || !savedSerializedPairs) return []
- const forChain = savedSerializedPairs[chainId]
- if (!forChain) return []
-
- return Object.keys(forChain).map((pairId) => {
- return [deserializeToken(forChain[pairId].token0), deserializeToken(forChain[pairId].token1)]
- })
- }, [savedSerializedPairs, chainId])
-
- const combinedList = useMemo(() => userPairs.concat(generatedPairs).concat(pinnedPairs), [
- generatedPairs,
- pinnedPairs,
- userPairs,
- ])
-
- return useMemo(() => {
- // dedupes pairs of tokens in the combined list
- const keyed = combinedList.reduce<{ [key: string]: [Token, Token] }>((memo, [tokenA, tokenB]) => {
- const sorted = tokenA.sortsBefore(tokenB)
- const key = sorted ? `${tokenA.address}:${tokenB.address}` : `${tokenB.address}:${tokenA.address}`
- if (memo[key]) return memo
- memo[key] = sorted ? [tokenA, tokenB] : [tokenB, tokenA]
- return memo
- }, {})
-
- return Object.keys(keyed).map((key) => keyed[key])
- }, [combinedList])
-}
diff --git a/src/state/user/reducer.test.ts b/src/state/user/reducer.test.ts
index 535c42b..650e783 100644
--- a/src/state/user/reducer.test.ts
+++ b/src/state/user/reducer.test.ts
@@ -1,5 +1,4 @@
import { createStore, Store } from 'redux'
-import { DEFAULT_DEADLINE_FROM_NOW, INITIAL_ALLOWED_SLIPPAGE } from '../../constants'
import { updateVersion } from '../global/actions'
import reducer, { initialState, UserState } from './reducer'
@@ -19,15 +18,5 @@ describe('swap reducer', () => {
store.dispatch(updateVersion())
expect(store.getState().lastUpdateVersionTimestamp).toBeGreaterThanOrEqual(time)
})
- it('sets allowed slippage and deadline', () => {
- store = createStore(reducer, {
- ...initialState,
- userDeadline: undefined,
- userSlippageTolerance: undefined,
- } as any)
- store.dispatch(updateVersion())
- expect(store.getState().userDeadline).toEqual(DEFAULT_DEADLINE_FROM_NOW)
- expect(store.getState().userSlippageTolerance).toEqual(INITIAL_ALLOWED_SLIPPAGE)
- })
})
})
diff --git a/src/state/user/reducer.ts b/src/state/user/reducer.ts
index 7b1f675..fe5a5bd 100644
--- a/src/state/user/reducer.ts
+++ b/src/state/user/reducer.ts
@@ -1,4 +1,3 @@
-import { INITIAL_ALLOWED_SLIPPAGE, DEFAULT_DEADLINE_FROM_NOW } from '../../constants'
import { createReducer } from '@reduxjs/toolkit'
import { updateVersion } from '../global/actions'
import {
@@ -10,11 +9,7 @@ import {
SerializedToken,
updateMatchesDarkMode,
updateUserDarkMode,
- updateUserExpertMode,
- updateUserSlippageTolerance,
- updateUserDeadline,
toggleURLWarning,
- updateUserSingleHopOnly,
} from './actions'
const currentTimestamp = () => new Date().getTime()
@@ -26,16 +21,6 @@ export interface UserState {
userDarkMode: boolean | null // the user's choice for dark mode or light mode
matchesDarkMode: boolean // whether the dark mode media query matches
- userExpertMode: boolean
-
- userSingleHopOnly: boolean // only allow swaps on direct pairs
-
- // user defined slippage tolerance in bips, used in all txns
- userSlippageTolerance: number
-
- // deadline set by user in minutes, used in all txns
- userDeadline: number
-
tokens: {
[chainId: number]: {
[address: string]: SerializedToken
@@ -60,10 +45,6 @@ function pairKey(token0Address: string, token1Address: string) {
export const initialState: UserState = {
userDarkMode: null,
matchesDarkMode: false,
- userExpertMode: false,
- userSingleHopOnly: false,
- userSlippageTolerance: INITIAL_ALLOWED_SLIPPAGE,
- userDeadline: DEFAULT_DEADLINE_FROM_NOW,
tokens: {},
pairs: {},
timestamp: currentTimestamp(),
@@ -73,18 +54,6 @@ export const initialState: UserState = {
export default createReducer(initialState, (builder) =>
builder
.addCase(updateVersion, (state) => {
- // slippage isnt being tracked in local storage, reset to default
- // noinspection SuspiciousTypeOfGuard
- if (typeof state.userSlippageTolerance !== 'number') {
- state.userSlippageTolerance = INITIAL_ALLOWED_SLIPPAGE
- }
-
- // deadline isnt being tracked in local storage, reset to default
- // noinspection SuspiciousTypeOfGuard
- if (typeof state.userDeadline !== 'number') {
- state.userDeadline = DEFAULT_DEADLINE_FROM_NOW
- }
-
state.lastUpdateVersionTimestamp = currentTimestamp()
})
.addCase(updateUserDarkMode, (state, action) => {
@@ -95,21 +64,6 @@ export default createReducer(initialState, (builder) =>
state.matchesDarkMode = action.payload.matchesDarkMode
state.timestamp = currentTimestamp()
})
- .addCase(updateUserExpertMode, (state, action) => {
- state.userExpertMode = action.payload.userExpertMode
- state.timestamp = currentTimestamp()
- })
- .addCase(updateUserSlippageTolerance, (state, action) => {
- state.userSlippageTolerance = action.payload.userSlippageTolerance
- state.timestamp = currentTimestamp()
- })
- .addCase(updateUserDeadline, (state, action) => {
- state.userDeadline = action.payload.userDeadline
- state.timestamp = currentTimestamp()
- })
- .addCase(updateUserSingleHopOnly, (state, action) => {
- state.userSingleHopOnly = action.payload.userSingleHopOnly
- })
.addCase(addSerializedToken, (state, { payload: { serializedToken } }) => {
state.tokens[serializedToken.chainId] = state.tokens[serializedToken.chainId] || {}
state.tokens[serializedToken.chainId][serializedToken.address] = serializedToken
diff --git a/src/state/wallet/hooks.ts b/src/state/wallet/hooks.ts
index e19409c..a83aab0 100644
--- a/src/state/wallet/hooks.ts
+++ b/src/state/wallet/hooks.ts
@@ -7,8 +7,6 @@ import { useActiveWeb3React } from '../../hooks'
import { useMulticallContract } from '../../hooks/useContract'
import { isAddress } from '../../utils'
import { useSingleContractMultipleData, useMultipleContractSingleData } from '../multicall/hooks'
-import { useUserUnclaimedAmount } from '../claim/hooks'
-import { useTotalUniEarned } from '../stake/hooks'
/**
* Returns a map of the given addresses to their eventually consistent ETH balances.
@@ -141,16 +139,8 @@ export function useAggregateUniBalance(): TokenAmount | undefined {
const uni = chainId ? UNI[chainId] : undefined
const uniBalance: TokenAmount | undefined = useTokenBalance(account ?? undefined, uni)
- const uniUnclaimed: TokenAmount | undefined = useUserUnclaimedAmount(account)
- const uniUnHarvested: TokenAmount | undefined = useTotalUniEarned()
if (!uni) return undefined
- return new TokenAmount(
- uni,
- JSBI.add(
- JSBI.add(uniBalance?.raw ?? JSBI.BigInt(0), uniUnclaimed?.raw ?? JSBI.BigInt(0)),
- uniUnHarvested?.raw ?? JSBI.BigInt(0)
- )
- )
+ return uniBalance
}
diff --git a/src/utils/computeUniCirculation.ts b/src/utils/computeUniCirculation.ts
index 93ed784..3206985 100644
--- a/src/utils/computeUniCirculation.ts
+++ b/src/utils/computeUniCirculation.ts
@@ -1,6 +1,7 @@
import { JSBI, Token, TokenAmount } from '@uniswap/sdk'
import { BigNumber } from 'ethers'
-import { STAKING_GENESIS } from '../state/stake/hooks'
+
+export const STAKING_GENESIS = 1600387200
const STAKING_END = STAKING_GENESIS + 60 * 60 * 24 * 60
diff --git a/src/utils/maxAmountSpend.ts b/src/utils/maxAmountSpend.ts
deleted file mode 100644
index 3d982c9..0000000
--- a/src/utils/maxAmountSpend.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { CurrencyAmount, ETHER, JSBI } from '@uniswap/sdk'
-import { MIN_ETH } from '../constants'
-
-/**
- * Given some token amount, return the max that can be spent of it
- * @param currencyAmount to return max of
- */
-export function maxAmountSpend(currencyAmount?: CurrencyAmount): CurrencyAmount | undefined {
- if (!currencyAmount) return undefined
- if (currencyAmount.currency === ETHER) {
- if (JSBI.greaterThan(currencyAmount.raw, MIN_ETH)) {
- return CurrencyAmount.ether(JSBI.subtract(currencyAmount.raw, MIN_ETH))
- } else {
- return CurrencyAmount.ether(JSBI.BigInt(0))
- }
- }
- return currencyAmount
-}
diff --git a/src/utils/prices.test.ts b/src/utils/prices.test.ts
deleted file mode 100644
index 9e8cbac..0000000
--- a/src/utils/prices.test.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import { ChainId, JSBI, Pair, Route, Token, TokenAmount, Trade, TradeType } from '@uniswap/sdk'
-import { computeTradePriceBreakdown } from './prices'
-
-describe('prices', () => {
- const token1 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000001', 18)
- const token2 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000002', 18)
- const token3 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000003', 18)
-
- const pair12 = new Pair(new TokenAmount(token1, JSBI.BigInt(10000)), new TokenAmount(token2, JSBI.BigInt(20000)))
- const pair23 = new Pair(new TokenAmount(token2, JSBI.BigInt(20000)), new TokenAmount(token3, JSBI.BigInt(30000)))
-
- describe('computeTradePriceBreakdown', () => {
- it('returns undefined for undefined', () => {
- expect(computeTradePriceBreakdown(undefined)).toEqual({
- priceImpactWithoutFee: undefined,
- realizedLPFee: undefined,
- })
- })
-
- it('correct realized lp fee for single hop', () => {
- expect(
- computeTradePriceBreakdown(
- new Trade(new Route([pair12], token1), new TokenAmount(token1, JSBI.BigInt(1000)), TradeType.EXACT_INPUT)
- ).realizedLPFee
- ).toEqual(new TokenAmount(token1, JSBI.BigInt(3)))
- })
-
- it('correct realized lp fee for double hop', () => {
- expect(
- computeTradePriceBreakdown(
- new Trade(
- new Route([pair12, pair23], token1),
- new TokenAmount(token1, JSBI.BigInt(1000)),
- TradeType.EXACT_INPUT
- )
- ).realizedLPFee
- ).toEqual(new TokenAmount(token1, JSBI.BigInt(5)))
- })
- })
-})
diff --git a/src/utils/prices.ts b/src/utils/prices.ts
deleted file mode 100644
index 16e5eb7..0000000
--- a/src/utils/prices.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { BLOCKED_PRICE_IMPACT_NON_EXPERT } from '../constants'
-import { CurrencyAmount, Fraction, JSBI, Percent, TokenAmount, Trade } from '@uniswap/sdk'
-import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM } from '../constants'
-import { Field } from '../state/swap/actions'
-import { basisPointsToPercent } from './index'
-
-const BASE_FEE = new Percent(JSBI.BigInt(30), JSBI.BigInt(10000))
-const ONE_HUNDRED_PERCENT = new Percent(JSBI.BigInt(10000), JSBI.BigInt(10000))
-const INPUT_FRACTION_AFTER_FEE = ONE_HUNDRED_PERCENT.subtract(BASE_FEE)
-
-// computes price breakdown for the trade
-export function computeTradePriceBreakdown(
- trade?: Trade | null
-): { priceImpactWithoutFee: Percent | undefined; realizedLPFee: CurrencyAmount | undefined | null } {
- // for each hop in our trade, take away the x*y=k price impact from 0.3% fees
- // e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03))
- const realizedLPFee = !trade
- ? undefined
- : ONE_HUNDRED_PERCENT.subtract(
- trade.route.pairs.reduce<Fraction>(
- (currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
- ONE_HUNDRED_PERCENT
- )
- )
-
- // remove lp fees from price impact
- const priceImpactWithoutFeeFraction = trade && realizedLPFee ? trade.priceImpact.subtract(realizedLPFee) : undefined
-
- // the x*y=k impact
- const priceImpactWithoutFeePercent = priceImpactWithoutFeeFraction
- ? new Percent(priceImpactWithoutFeeFraction?.numerator, priceImpactWithoutFeeFraction?.denominator)
- : undefined
-
- // the amount of the input that accrues to LPs
- const realizedLPFeeAmount =
- realizedLPFee &&
- trade &&
- (trade.inputAmount instanceof TokenAmount
- ? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient)
- : CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient))
-
- return { priceImpactWithoutFee: priceImpactWithoutFeePercent, realizedLPFee: realizedLPFeeAmount }
-}
-
-// computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips
-export function computeSlippageAdjustedAmounts(
- trade: Trade | undefined,
- allowedSlippage: number
-): { [field in Field]?: CurrencyAmount } {
- const pct = basisPointsToPercent(allowedSlippage)
- return {
- [Field.INPUT]: trade?.maximumAmountIn(pct),
- [Field.OUTPUT]: trade?.minimumAmountOut(pct),
- }
-}
-
-export function warningSeverity(priceImpact: Percent | undefined): 0 | 1 | 2 | 3 | 4 {
- if (!priceImpact?.lessThan(BLOCKED_PRICE_IMPACT_NON_EXPERT)) return 4
- if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_HIGH)) return 3
- if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_MEDIUM)) return 2
- if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_LOW)) return 1
- return 0
-}
-
-export function formatExecutionPrice(trade?: Trade, inverted?: boolean): string {
- if (!trade) {
- return ''
- }
- return inverted
- ? `${trade.executionPrice.invert().toSignificant(6)} ${trade.inputAmount.currency.symbol} / ${
- trade.outputAmount.currency.symbol
- }`
- : `${trade.executionPrice.toSignificant(6)} ${trade.outputAmount.currency.symbol} / ${
- trade.inputAmount.currency.symbol
- }`
-}
diff --git a/src/utils/useUSDCPrice.ts b/src/utils/useUSDCPrice.ts
deleted file mode 100644
index 745ac42..0000000
--- a/src/utils/useUSDCPrice.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import { ChainId, Currency, currencyEquals, JSBI, Price, WETH } from '@uniswap/sdk'
-import { useMemo } from 'react'
-import { USDC } from '../constants'
-import { PairState, usePairs } from '../data/Reserves'
-import { useActiveWeb3React } from '../hooks'
-import { wrappedCurrency } from './wrappedCurrency'
-
-/**
- * Returns the price in USDC of the input currency
- * @param currency currency to compute the USDC price of
- */
-export default function useUSDCPrice(currency?: Currency): Price | undefined {
- const { chainId } = useActiveWeb3React()
- const wrapped = wrappedCurrency(currency, chainId)
- const tokenPairs: [Currency | undefined, Currency | undefined][] = useMemo(
- () => [
- [
- chainId && wrapped && currencyEquals(WETH[chainId], wrapped) ? undefined : currency,
- chainId ? WETH[chainId] : undefined,
- ],
- [wrapped?.equals(USDC) ? undefined : wrapped, chainId === ChainId.MAINNET ? USDC : undefined],
- [chainId ? WETH[chainId] : undefined, chainId === ChainId.MAINNET ? USDC : undefined],
- ],
- [chainId, currency, wrapped]
- )
- const [[ethPairState, ethPair], [usdcPairState, usdcPair], [usdcEthPairState, usdcEthPair]] = usePairs(tokenPairs)
-
- return useMemo(() => {
- if (!currency || !wrapped || !chainId) {
- return undefined
- }
- // handle weth/eth
- if (wrapped.equals(WETH[chainId])) {
- if (usdcPair) {
- const price = usdcPair.priceOf(WETH[chainId])
- return new Price(currency, USDC, price.denominator, price.numerator)
- } else {
- return undefined
- }
- }
- // handle usdc
- if (wrapped.equals(USDC)) {
- return new Price(USDC, USDC, '1', '1')
- }
-
- const ethPairETHAmount = ethPair?.reserveOf(WETH[chainId])
- const ethPairETHUSDCValue: JSBI =
- ethPairETHAmount && usdcEthPair ? usdcEthPair.priceOf(WETH[chainId]).quote(ethPairETHAmount).raw : JSBI.BigInt(0)
-
- // all other tokens
- // first try the usdc pair
- if (usdcPairState === PairState.EXISTS && usdcPair && usdcPair.reserveOf(USDC).greaterThan(ethPairETHUSDCValue)) {
- const price = usdcPair.priceOf(wrapped)
- return new Price(currency, USDC, price.denominator, price.numerator)
- }
- if (ethPairState === PairState.EXISTS && ethPair && usdcEthPairState === PairState.EXISTS && usdcEthPair) {
- if (usdcEthPair.reserveOf(USDC).greaterThan('0') && ethPair.reserveOf(WETH[chainId]).greaterThan('0')) {
- const ethUsdcPrice = usdcEthPair.priceOf(USDC)
- const currencyEthPrice = ethPair.priceOf(WETH[chainId])
- const usdcPrice = ethUsdcPrice.multiply(currencyEthPrice).invert()
- return new Price(currency, USDC, usdcPrice.denominator, usdcPrice.numerator)
- }
- }
- return undefined
- }, [chainId, currency, ethPair, ethPairState, usdcEthPair, usdcEthPairState, usdcPair, usdcPairState, wrapped])
-}
diff --git a/src/utils/v1SwapArgument.test.ts b/src/utils/v1SwapArgument.test.ts
deleted file mode 100644
index eeef9df..0000000
--- a/src/utils/v1SwapArgument.test.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import { CurrencyAmount, ETHER, Percent, Route, TokenAmount, Trade } from '@uniswap/sdk'
-import { DAI, USDC } from '../constants'
-import { MockV1Pair } from '../data/V1'
-import v1SwapArguments from './v1SwapArguments'
-
-describe('v1SwapArguments', () => {
- const USDC_WETH = new MockV1Pair('1000000', new TokenAmount(USDC, '1000000'))
- const DAI_WETH = new MockV1Pair('1000000', new TokenAmount(DAI, '1000000'))
-
- // just some random address
- const TEST_RECIPIENT_ADDRESS = USDC_WETH.liquidityToken.address
-
- it('exact eth to token', () => {
- const trade = Trade.exactIn(new Route([USDC_WETH], ETHER), CurrencyAmount.ether('100'))
- const result = v1SwapArguments(trade, {
- recipient: TEST_RECIPIENT_ADDRESS,
- allowedSlippage: new Percent('1', '100'),
- deadline: 20 * 60,
- })
- expect(result.methodName).toEqual('ethToTokenTransferInput')
- expect(result.args).toEqual(['0x62', '0x4b0', TEST_RECIPIENT_ADDRESS])
- expect(result.value).toEqual('0x64')
- })
- it('exact token to eth', () => {
- const trade = Trade.exactIn(new Route([USDC_WETH], USDC, ETHER), new TokenAmount(USDC, '100'))
- const result = v1SwapArguments(trade, {
- recipient: TEST_RECIPIENT_ADDRESS,
- allowedSlippage: new Percent('1', '100'),
- deadline: 40 * 60,
- })
- expect(result.methodName).toEqual('tokenToEthTransferInput')
- expect(result.args[0]).toEqual('0x64')
- expect(result.args[1]).toEqual('0x62')
- expect(result.args[2]).toEqual('0x960')
- expect(result.args[3]).toEqual(TEST_RECIPIENT_ADDRESS)
- expect(result.value).toEqual('0x0')
- })
- it('exact token to token', () => {
- const trade = Trade.exactIn(new Route([USDC_WETH, DAI_WETH], USDC), new TokenAmount(USDC, '100'))
- const result = v1SwapArguments(trade, {
- recipient: TEST_RECIPIENT_ADDRESS,
- allowedSlippage: new Percent('1', '100'),
- deadline: 20 * 60,
- })
- expect(result.methodName).toEqual('tokenToTokenTransferInput')
- expect(result.args[0]).toEqual('0x64')
- expect(result.args[1]).toEqual('0x61')
- expect(result.args[2]).toEqual('0x1')
- expect(result.args[3]).toEqual('0x4b0')
- expect(result.args[4]).toEqual(TEST_RECIPIENT_ADDRESS)
- expect(result.args[5]).toEqual(DAI.address)
- expect(result.value).toEqual('0x0')
- })
- it('eth to exact token', () => {
- const trade = Trade.exactOut(new Route([USDC_WETH], ETHER), new TokenAmount(USDC, '100'))
- const result = v1SwapArguments(trade, {
- recipient: TEST_RECIPIENT_ADDRESS,
- allowedSlippage: new Percent('1', '100'),
- deadline: 20 * 60,
- })
- expect(result.methodName).toEqual('ethToTokenTransferOutput')
- expect(result.args[0]).toEqual('0x64')
- expect(result.args[1]).toEqual('0x4b0')
- expect(result.args[2]).toEqual(TEST_RECIPIENT_ADDRESS)
- expect(result.value).toEqual('0x66')
- })
- it('token to exact eth', () => {
- const trade = Trade.exactOut(new Route([USDC_WETH], USDC, ETHER), CurrencyAmount.ether('100'))
- const result = v1SwapArguments(trade, {
- recipient: TEST_RECIPIENT_ADDRESS,
- allowedSlippage: new Percent('1', '100'),
- deadline: 20 * 60,
- })
- expect(result.methodName).toEqual('tokenToEthTransferOutput')
- expect(result.args[0]).toEqual('0x64')
- expect(result.args[1]).toEqual('0x66')
- expect(result.args[2]).toEqual('0x4b0')
- expect(result.args[3]).toEqual(TEST_RECIPIENT_ADDRESS)
- expect(result.value).toEqual('0x0')
- })
- it('token to exact token', () => {
- const trade = Trade.exactOut(new Route([USDC_WETH, DAI_WETH], USDC), new TokenAmount(DAI, '100'))
- const result = v1SwapArguments(trade, {
- recipient: TEST_RECIPIENT_ADDRESS,
- allowedSlippage: new Percent('1', '100'),
- deadline: 20 * 60,
- })
- expect(result.methodName).toEqual('tokenToTokenTransferOutput')
- expect(result.args[0]).toEqual('0x64')
- expect(result.args[1]).toEqual('0x67')
- expect(result.args[2]).toEqual(`0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`)
- expect(result.args[3]).toEqual('0x4b0')
- expect(result.args[4]).toEqual(TEST_RECIPIENT_ADDRESS)
- expect(result.args[5]).toEqual(DAI.address)
- expect(result.value).toEqual('0x0')
- })
-})
diff --git a/src/utils/v1SwapArguments.ts b/src/utils/v1SwapArguments.ts
deleted file mode 100644
index 8bafa43..0000000
--- a/src/utils/v1SwapArguments.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { MaxUint256 } from '@ethersproject/constants'
-import { CurrencyAmount, ETHER, SwapParameters, Token, Trade, TradeOptionsDeadline, TradeType } from '@uniswap/sdk'
-import { getTradeVersion } from '../data/V1'
-import { Version } from '../hooks/useToggledVersion'
-
-function toHex(currencyAmount: CurrencyAmount): string {
- return `0x${currencyAmount.raw.toString(16)}`
-}
-
-/**
- * Get the arguments to make for a swap
- * @param trade trade to get v1 arguments for swapping
- * @param options options for swapping
- */
-export default function v1SwapArguments(
- trade: Trade,
- options: Omit<TradeOptionsDeadline, 'feeOnTransfer'>
-): SwapParameters {
- if (getTradeVersion(trade) !== Version.v1) {
- throw new Error('invalid trade version')
- }
- if (trade.route.pairs.length > 2) {
- throw new Error('too many pairs')
- }
- const isExactIn = trade.tradeType === TradeType.EXACT_INPUT
- const inputETH = trade.inputAmount.currency === ETHER
- const outputETH = trade.outputAmount.currency === ETHER
- if (inputETH && outputETH) throw new Error('ETHER to ETHER')
- const minimumAmountOut = toHex(trade.minimumAmountOut(options.allowedSlippage))
- const maximumAmountIn = toHex(trade.maximumAmountIn(options.allowedSlippage))
- const deadline = `0x${options.deadline.toString(16)}`
- if (isExactIn) {
- if (inputETH) {
- return {
- methodName: 'ethToTokenTransferInput',
- args: [minimumAmountOut, deadline, options.recipient],
- value: maximumAmountIn,
- }
- } else if (outputETH) {
- return {
- methodName: 'tokenToEthTransferInput',
- args: [maximumAmountIn, minimumAmountOut, deadline, options.recipient],
- value: '0x0',
- }
- } else {
- const outputToken = trade.outputAmount.currency
- // should never happen, needed for type check
- if (!(outputToken instanceof Token)) {
- throw new Error('token to token')
- }
- return {
- methodName: 'tokenToTokenTransferInput',
- args: [maximumAmountIn, minimumAmountOut, '0x1', deadline, options.recipient, outputToken.address],
- value: '0x0',
- }
- }
- } else {
- if (inputETH) {
- return {
- methodName: 'ethToTokenTransferOutput',
- args: [minimumAmountOut, deadline, options.recipient],
- value: maximumAmountIn,
- }
- } else if (outputETH) {
- return {
- methodName: 'tokenToEthTransferOutput',
- args: [minimumAmountOut, maximumAmountIn, deadline, options.recipient],
- value: '0x0',
- }
- } else {
- const output = trade.outputAmount.currency
- if (!(output instanceof Token)) {
- throw new Error('invalid output amount currency')
- }
-
- return {
- methodName: 'tokenToTokenTransferOutput',
- args: [
- minimumAmountOut,
- maximumAmountIn,
- MaxUint256.toHexString(),
- deadline,
- options.recipient,
- output.address,
- ],
- value: '0x0',
- }
- }
- }
-}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment