diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..4b550307b8 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,32 @@ +{ + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "ecmaFeatures": { + // Allows for the parsing of JSX + "jsx": true + } + }, + "ignorePatterns": [ + "node_modules/**/*" + ], + "settings": { + "react": { + "version": "detect" + } + }, + "extends": [ + "plugin:react/recommended", + "plugin:@typescript-eslint/recommended", + "prettier/@typescript-eslint", + "plugin:prettier/recommended" + ], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off", + "prettier/prettier": "error", + "react/prop-types": "off", + "@typescript-eslint/no-empty-function": "off", + "react/display-name": "off" + } +} \ No newline at end of file diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 7457d71efa..87a4b02366 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -31,4 +31,15 @@ jobs: - run: yarn - run: yarn test -# todo: add job for typescript linting + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: '12' + - run: yarn + - run: yarn lint + diff --git a/cypress/integration/no-connect.ts b/cypress/integration/no-connect.ts index 40e37e920d..963a1b842a 100644 --- a/cypress/integration/no-connect.ts +++ b/cypress/integration/no-connect.ts @@ -15,4 +15,4 @@ describe('Homepage', () => { it('can enter an amount into output', () => { cy.get('#swapOutputField').type('0.001') }) -}) \ No newline at end of file +}) diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js index 7fa14b97b6..00420d1601 100644 --- a/cypress/plugins/index.js +++ b/cypress/plugins/index.js @@ -15,7 +15,7 @@ /** * @type {Cypress.PluginConfig} */ -module.exports = (on, config) => { +module.exports = () => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config } diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 9760611b09..b017ed26f5 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -24,4 +24,4 @@ // -- This will overwrite an existing command -- // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) -// TODO(moodysalem): commands for connecting a mock ethereum provider. \ No newline at end of file +// TODO(moodysalem): commands for connecting a mock ethereum provider. diff --git a/package.json b/package.json index dcc4644bcd..d8387a9f7b 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,13 @@ "@types/react-dom": "^16.9.7", "@types/react-router-dom": "^5.0.0", "@types/styled-components": "^4.2.0", + "@typescript-eslint/eslint-plugin": "^2.31.0", + "@typescript-eslint/parser": "^2.31.0", "cypress": "^4.5.0", + "eslint": "^6.8.0", + "eslint-config-prettier": "^6.11.0", + "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-react": "^7.19.0", "prettier": "^1.17.0", "serve": "^11.3.0", "start-server-and-test": "^1.11.0", @@ -68,14 +74,8 @@ "build": "cross-env REACT_APP_GIT_COMMIT_HASH=$(git show -s --format=%H) react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject", - "lint:base": "yarn eslint './src/**/*.{js,jsx}'", - "format:base": "yarn prettier './src/**/*.{js,jsx,scss}'", - "fix:lint": "yarn lint:base --fix", - "fix:format": "yarn format:base --write", - "fix:all": "yarn fix:lint && yarn fix:format", - "check:lint": "yarn lint:base", - "check:format": "yarn format:base --check", - "check:all": "yarn check:lint && yarn check:format", + "lint": "eslint '**/*.{js,jsx,ts,tsx}'", + "lint:fix": "eslint '**/*.{js,jsx,ts,tsx}' --fix", "cy:run": "cypress run", "serve:build": "serve -s build -l 3000", "integration-test": "yarn build && start-server-and-test 'yarn run serve:build' http://localhost:3000 cy:run" diff --git a/src/components/AccountDetails/Copy.tsx b/src/components/AccountDetails/Copy.tsx index c40343928c..25d3e59a7b 100644 --- a/src/components/AccountDetails/Copy.tsx +++ b/src/components/AccountDetails/Copy.tsx @@ -33,12 +33,12 @@ export default function CopyHelper(props: { toCopy: string; children?: React.Rea {props.children} {isCopied ? ( - + Copied ) : ( - + )} diff --git a/src/components/AccountDetails/Transaction.tsx b/src/components/AccountDetails/Transaction.tsx index 4ff6d51908..95cd834841 100644 --- a/src/components/AccountDetails/Transaction.tsx +++ b/src/components/AccountDetails/Transaction.tsx @@ -43,7 +43,7 @@ const rotate = keyframes` } ` -const TransactionState = styled.div<{pending?: boolean;}>` +const TransactionState = styled.div<{ pending?: boolean }>` display: flex; background-color: ${({ pending, theme }) => pending ? transparentize(0.95, theme.blue1) : transparentize(0.95, theme.green1)}; @@ -64,13 +64,13 @@ const TransactionState = styled.div<{pending?: boolean;}>` pending ? transparentize(0, theme.blue1) : transparentize(0, theme.green1)}; } ` -const ButtonWrapper = styled.div<{pending: boolean}>` +const ButtonWrapper = styled.div<{ pending: boolean }>` a { color: ${({ pending, theme }) => (pending ? theme.blue1 : theme.green1)}; } ` -export default function Transaction({ hash, pending }) { +export default function Transaction({ hash, pending }: { hash: string; pending: boolean }) { const { chainId } = useWeb3React() const allTransactions = useAllTransactions() diff --git a/src/components/AccountDetails/index.tsx b/src/components/AccountDetails/index.tsx index 40b44612b5..bffdf3b524 100644 --- a/src/components/AccountDetails/index.tsx +++ b/src/components/AccountDetails/index.tsx @@ -129,7 +129,7 @@ const LowerSection = styled.div` } ` -const AccountControl = styled.div<{ hasENS: boolean; isENS: boolean; }>` +const AccountControl = styled.div<{ hasENS: boolean; isENS: boolean }>` ${({ theme }) => theme.flexRowNoWrap}; align-items: center; min-width: 0; @@ -156,7 +156,7 @@ const ConnectButtonRow = styled.div` margin: 10px 0; ` -const StyledLink = styled(Link) <{ hasENS: boolean; isENS: boolean; }>` +const StyledLink = styled(Link)<{ hasENS: boolean; isENS: boolean }>` color: ${({ hasENS, isENS, theme }) => (hasENS ? (isENS ? theme.blue1 : theme.text3) : theme.blue1)}; ` @@ -181,7 +181,7 @@ const WalletName = styled.div` width: initial; ` -const IconWrapper = styled.div<{size?: number}>` +const IconWrapper = styled.div<{ size?: number }>` ${({ theme }) => theme.flexColumnNoWrap}; align-items: center; justify-content: center; @@ -217,19 +217,27 @@ function renderTransactions(transactions, pending) { return ( {transactions.map((hash, i) => { - return + return })} ) } +interface AccountDetailsProps { + toggleWalletModal: () => void + pendingTransactions: any[] + confirmedTransactions: any[] + ENSName?: string + openOptions: () => void +} + export default function AccountDetails({ - toggleWalletModal, - pendingTransactions, - confirmedTransactions, - ENSName, - openOptions - }) { + toggleWalletModal, + pendingTransactions, + confirmedTransactions, + ENSName, + openOptions +}: AccountDetailsProps) { const { chainId, account, connector } = useWeb3React() const theme = useContext(ThemeContext) @@ -249,32 +257,32 @@ export default function AccountDetails({ if (connector === injected) { return ( - {formatConnectorName()} + {formatConnectorName()} ) } else if (connector === walletconnect) { return ( - {''}/ {formatConnectorName()} + {''} {formatConnectorName()} ) } else if (connector === walletlink) { return ( - {''}/ {formatConnectorName()} + {''} {formatConnectorName()} ) } else if (connector === fortmatic) { return ( - {''}/ {formatConnectorName()} + {''} {formatConnectorName()} ) } else if (connector === portis) { return ( <> - {''}/ {formatConnectorName()} + {''} {formatConnectorName()} { portis.portis.showPortis() @@ -292,7 +300,7 @@ export default function AccountDetails({ <> - + Account @@ -304,7 +312,7 @@ export default function AccountDetails({ {connector !== injected && connector !== walletlink && ( { - (connector as any).close() + ;(connector as any).close() }} > Disconnect @@ -312,7 +320,7 @@ export default function AccountDetails({ )} -
+
@@ -323,14 +331,14 @@ export default function AccountDetails({ {ENSName} ↗{' '} - + ) : ( {account} ↗{' '} - + )} diff --git a/src/components/AddressInputPanel/index.tsx b/src/components/AddressInputPanel/index.tsx index baec002672..1d84ff6b91 100644 --- a/src/components/AddressInputPanel/index.tsx +++ b/src/components/AddressInputPanel/index.tsx @@ -63,7 +63,15 @@ const Input = styled.input<{ error: boolean }>` // border-radius: 8px; // ` -export default function AddressInputPanel({ initialInput = '', onChange, onError }) { +export default function AddressInputPanel({ + initialInput = '', + onChange, + onError +}: { + initialInput?: string + onChange: (val: { address: string; name?: string }) => void + onError: (error: boolean, input: string) => void +}) { const { library } = useWeb3React() const [input, setInput] = useState(initialInput ? initialInput : '') diff --git a/src/components/AdvancedSettings/index.tsx b/src/components/AdvancedSettings/index.tsx index 11ac1479e0..8c4095026f 100644 --- a/src/components/AdvancedSettings/index.tsx +++ b/src/components/AdvancedSettings/index.tsx @@ -17,7 +17,7 @@ const InputWrapper = styled(RowBetween)` padding: 4px 8px; border: 1px solid transparent; border: ${({ active, error, theme }) => - error ? '1px solid ' + theme.red1 : active ? '1px solid ' + theme.blue1 : ''}; + error ? '1px solid ' + theme.red1 : active ? '1px solid ' + theme.blue1 : ''}; ` const SLIPPAGE_INDEX = { @@ -34,7 +34,12 @@ interface AdvancedSettingsProps { setAllowedSlippage: (number) => void } -export default function AdvancedSettings({ setIsOpen, setDeadline, allowedSlippage, setAllowedSlippage }: AdvancedSettingsProps) { +export default function AdvancedSettings({ + setIsOpen, + setDeadline, + allowedSlippage, + setAllowedSlippage +}: AdvancedSettingsProps) { // text translation const { t } = useTranslation() @@ -78,7 +83,7 @@ export default function AdvancedSettings({ setIsOpen, setDeadline, allowedSlippa setActiveIndex(3) } else { setActiveIndex(4) - setSlippageInput('' + (allowedSlippage / 100)) + setSlippageInput('' + allowedSlippage / 100) parseCustomInput(allowedSlippage) } }, [allowedSlippage, parseCustomInput]) @@ -94,7 +99,7 @@ export default function AdvancedSettings({ setIsOpen, setDeadline, allowedSlippa Front-running tolerance - + ` +export const AutoColumn = styled.div<{ + gap?: 'sm' | 'md' | 'lg' | string + justify?: 'stretch' | 'center' | 'start' | 'end' | 'flex-start' | 'flex-end' +}>` display: grid; grid-auto-rows: auto; grid-row-gap: ${({ gap }) => (gap === 'sm' && '8px') || (gap === 'md' && '12px') || (gap === 'lg' && '24px') || gap}; diff --git a/src/components/ConfirmationModal/index.tsx b/src/components/ConfirmationModal/index.tsx index 7d4759c36c..e7b1970a64 100644 --- a/src/components/ConfirmationModal/index.tsx +++ b/src/components/ConfirmationModal/index.tsx @@ -45,17 +45,17 @@ interface ConfirmationModalProps extends RouteComponentProps<{}> { } function ConfirmationModal({ - history, - isOpen, - onDismiss, - hash, - topContent, - bottomContent, - attemptingTxn, - pendingConfirmation, - pendingText, - title = '' - }: ConfirmationModalProps) { + history, + isOpen, + onDismiss, + hash, + topContent, + bottomContent, + attemptingTxn, + pendingConfirmation, + pendingText, + title = '' +}: ConfirmationModalProps) { const { chainId } = useWeb3React() const dismissAndReturn = useCallback(() => { @@ -74,7 +74,7 @@ function ConfirmationModal({ {title} - + {topContent()} @@ -84,14 +84,14 @@ function ConfirmationModal({
-
- +
+ {pendingConfirmation ? ( - + ) : ( - + )} diff --git a/src/components/CurrencyInputPanel/index.tsx b/src/components/CurrencyInputPanel/index.tsx index fbb7e1178f..01f137f640 100644 --- a/src/components/CurrencyInputPanel/index.tsx +++ b/src/components/CurrencyInputPanel/index.tsx @@ -139,41 +139,41 @@ interface CurrencyInputPanelProps { onUserInput: (field: number, val: string) => void onMax: () => void atMax: boolean - label?: string, + label?: string urlAddedTokens?: Token[] onTokenSelection?: (tokenAddress: string) => void - token?: Token | null, - disableTokenSelect?: boolean, - hideBalance?: boolean, - isExchange?: boolean, - pair?: Pair | null, - hideInput?: boolean, - showSendWithSwap?: boolean, - otherSelectedTokenAddress?: string | null, - advanced?: boolean, + token?: Token | null + disableTokenSelect?: boolean + hideBalance?: boolean + isExchange?: boolean + pair?: Pair | null + hideInput?: boolean + showSendWithSwap?: boolean + otherSelectedTokenAddress?: string | null + advanced?: boolean inputId: string } export default function CurrencyInputPanel({ - value, - field, - onUserInput, - onMax, - atMax, - label = 'Input', - urlAddedTokens = [], // used - onTokenSelection = null, - token = null, - disableTokenSelect = false, - hideBalance = false, - isExchange = false, - pair = null, // used for double token logo - hideInput = false, - showSendWithSwap = false, - otherSelectedTokenAddress = null, - advanced = false, - inputId, - }: CurrencyInputPanelProps) { + value, + field, + onUserInput, + onMax, + atMax, + label = 'Input', + urlAddedTokens = [], // used + onTokenSelection = null, + token = null, + disableTokenSelect = false, + hideBalance = false, + isExchange = false, + pair = null, // used for double token logo + hideInput = false, + showSendWithSwap = false, + otherSelectedTokenAddress = null, + advanced = false, + inputId +}: CurrencyInputPanelProps) { const { t } = useTranslation() const [modalOpen, setModalOpen] = useState(false) @@ -207,10 +207,7 @@ export default function CurrencyInputPanel({ )} - + {!hideInput && ( <> {isExchange ? ( - + ) : token?.address ? ( - + ) : null} {isExchange ? ( @@ -248,7 +245,7 @@ export default function CurrencyInputPanel({ {(token && token.symbol) || t('selectToken')} )} - {!disableTokenSelect && } + {!disableTokenSelect && } diff --git a/src/components/DoubleLogo/index.tsx b/src/components/DoubleLogo/index.tsx index 555a469a91..aae794a625 100644 --- a/src/components/DoubleLogo/index.tsx +++ b/src/components/DoubleLogo/index.tsx @@ -3,11 +3,11 @@ import styled from 'styled-components' import TokenLogo from '../TokenLogo' const TokenWrapper = styled.div<{ margin: boolean; sizeraw: number }>` - position: relative; - display: flex; - flex-direction: row; - margin-right: ${({ sizeraw, margin }) => margin && (sizeraw / 3 + 8).toString() + 'px'}; - ` + position: relative; + display: flex; + flex-direction: row; + margin-right: ${({ sizeraw, margin }) => margin && (sizeraw / 3 + 8).toString() + 'px'}; +` interface DoubleTokenLogoProps { margin?: boolean @@ -17,18 +17,18 @@ interface DoubleTokenLogoProps { } const HigherLogo = styled(TokenLogo)` - z-index: 2; - ` + z-index: 2; +` const CoveredLogo = styled(TokenLogo)<{ sizeraw: number }>` - position: absolute; - left: ${({ sizeraw }) => (sizeraw / 2).toString() + 'px'}; - ` + position: absolute; + left: ${({ sizeraw }) => (sizeraw / 2).toString() + 'px'}; +` export default function DoubleTokenLogo({ a0, a1, size = 16, margin = false }: DoubleTokenLogoProps) { return ( - - + + ) } diff --git a/src/components/ExchangePage/index.tsx b/src/components/ExchangePage/index.tsx index f2ce07e32c..d269d9f7d0 100644 --- a/src/components/ExchangePage/index.tsx +++ b/src/components/ExchangePage/index.tsx @@ -178,14 +178,22 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro } const pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT]) - let bestTradeExactIn = useTradeExactIn(tradeType === TradeType.EXACT_INPUT ? parsedAmounts[independentField] : null, tokens[Field.OUTPUT]) - let bestTradeExactOut = useTradeExactOut(tokens[Field.INPUT], tradeType === TradeType.EXACT_OUTPUT ? parsedAmounts[independentField] : null) + const bestTradeExactIn = useTradeExactIn( + tradeType === TradeType.EXACT_INPUT ? parsedAmounts[independentField] : null, + tokens[Field.OUTPUT] + ) + const bestTradeExactOut = useTradeExactOut( + tokens[Field.INPUT], + tradeType === TradeType.EXACT_OUTPUT ? parsedAmounts[independentField] : null + ) const trade = tradeType === TradeType.EXACT_INPUT ? bestTradeExactIn : bestTradeExactOut const route = trade?.route - const userHasSpecifiedInputOutput = !!parsedAmounts[independentField] && + const userHasSpecifiedInputOutput = + !!parsedAmounts[independentField] && parsedAmounts[independentField].greaterThan(JSBI.BigInt(0)) && - !!tokens[Field.INPUT] && !!tokens[Field.OUTPUT] + !!tokens[Field.INPUT] && + !!tokens[Field.OUTPUT] const noRoute = !route const slippageFromTrade: Percent = trade && trade.slippage @@ -213,12 +221,15 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro JSBI.multiply(slippageFromTrade.denominator, JSBI.BigInt('1000')) ) - const onTokenSelection = useCallback((field: Field, address: string) => { - dispatch({ - type: SwapAction.SELECT_TOKEN, - payload: { field, address } - }) - }, [dispatch]) + const onTokenSelection = useCallback( + (field: Field, address: string) => { + dispatch({ + type: SwapAction.SELECT_TOKEN, + payload: { field, address } + }) + }, + [dispatch] + ) const onSwapTokens = useCallback(() => { dispatch({ @@ -227,29 +238,38 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro }) }, [dispatch]) - const onUserInput = useCallback((field: Field, typedValue: string) => { - dispatch({ type: SwapAction.TYPE, payload: { field, typedValue } }) - }, [dispatch]) + const onUserInput = useCallback( + (field: Field, typedValue: string) => { + dispatch({ type: SwapAction.TYPE, payload: { field, typedValue } }) + }, + [dispatch] + ) - const onMaxInput = useCallback((typedValue: string) => { - dispatch({ - type: SwapAction.TYPE, - payload: { - field: Field.INPUT, - typedValue - } - }) - }, [dispatch]) + const onMaxInput = useCallback( + (typedValue: string) => { + dispatch({ + type: SwapAction.TYPE, + payload: { + field: Field.INPUT, + typedValue + } + }) + }, + [dispatch] + ) - const onMaxOutput = useCallback((typedValue: string) => { - dispatch({ - type: SwapAction.TYPE, - payload: { - field: Field.OUTPUT, - typedValue - } - }) - }, [dispatch]) + const onMaxOutput = useCallback( + (typedValue: string) => { + dispatch({ + type: SwapAction.TYPE, + payload: { + field: Field.OUTPUT, + typedValue + } + }) + }, + [dispatch] + ) // reset field if sending with with swap is cancled useEffect(() => { @@ -269,11 +289,10 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro WETH[chainId] && JSBI.greaterThan(userBalances[Field.INPUT].raw, isWETH(tokens[Field.INPUT]) ? MIN_ETHER.raw : JSBI.BigInt(0)) ? isWETH(tokens[Field.INPUT]) - ? userBalances[Field.INPUT].subtract(MIN_ETHER) - : userBalances[Field.INPUT] + ? userBalances[Field.INPUT].subtract(MIN_ETHER) + : userBalances[Field.INPUT] : undefined - } catch { - } + } catch {} const atMaxAmountInput: boolean = !!maxAmountInput && !!parsedAmounts[Field.INPUT] @@ -323,17 +342,28 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro Field.INPUT === independentField ? parsedAmounts[Field.INPUT] : calculateSlippageAmount(parsedAmounts[Field.INPUT])?.[0] && - new TokenAmount(tokens[Field.INPUT], calculateSlippageAmount(parsedAmounts[Field.INPUT])?.[1]), + new TokenAmount(tokens[Field.INPUT], calculateSlippageAmount(parsedAmounts[Field.INPUT])?.[1]), [Field.OUTPUT]: Field.OUTPUT === independentField ? parsedAmounts[Field.OUTPUT] : calculateSlippageAmount(parsedAmounts[Field.OUTPUT])?.[0] && - new TokenAmount(tokens[Field.INPUT], calculateSlippageAmount(parsedAmounts[Field.OUTPUT])?.[0]) + new TokenAmount(tokens[Field.INPUT], calculateSlippageAmount(parsedAmounts[Field.OUTPUT])?.[0]) } const showInputApprove: boolean = parsedAmounts[Field.INPUT] && inputApproval && JSBI.greaterThan(parsedAmounts[Field.INPUT].raw, inputApproval.raw) + // reset modal state when closed + function resetModal() { + // clear input if txn submitted + if (!pendingConfirmation) { + onUserInput(Field.INPUT, '') + } + setPendingConfirmation(true) + setAttemptingTxn(false) + setShowAdvanced(false) + } + // function for a pure send async function onSend() { setAttemptingTxn(true) @@ -349,11 +379,11 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro addTransaction( response, 'Send ' + - parsedAmounts[Field.INPUT]?.toSignificant(3) + - ' ' + - tokens[Field.INPUT]?.symbol + - ' to ' + - recipient + parsedAmounts[Field.INPUT]?.toSignificant(3) + + ' ' + + tokens[Field.INPUT]?.symbol + + ' to ' + + recipient ) setPendingConfirmation(false) }) @@ -376,11 +406,11 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro addTransaction( response, 'Send ' + - parsedAmounts[Field.INPUT]?.toSignificant(3) + - ' ' + - tokens[Field.INPUT]?.symbol + - ' to ' + - recipient + parsedAmounts[Field.INPUT]?.toSignificant(3) + + ' ' + + tokens[Field.INPUT]?.symbol + + ' to ' + + recipient ) setPendingConfirmation(false) }) @@ -487,13 +517,13 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro addTransaction( response, 'Swap ' + - slippageAdjustedAmounts?.[Field.INPUT]?.toSignificant(3) + - ' ' + - tokens[Field.INPUT]?.symbol + - ' for ' + - slippageAdjustedAmounts?.[Field.OUTPUT]?.toSignificant(3) + - ' ' + - tokens[Field.OUTPUT]?.symbol + slippageAdjustedAmounts?.[Field.INPUT]?.toSignificant(3) + + ' ' + + tokens[Field.INPUT]?.symbol + + ' for ' + + slippageAdjustedAmounts?.[Field.OUTPUT]?.toSignificant(3) + + ' ' + + tokens[Field.OUTPUT]?.symbol ) setPendingConfirmation(false) }) @@ -625,17 +655,6 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro const warningHigh: boolean = slippageFromTrade && parseFloat(slippageFromTrade.toFixed(4)) > ALLOWED_SLIPPAGE_HIGH / 100 - // reset modal state when closed - function resetModal() { - // clear input if txn submitted - if (!pendingConfirmation) { - onUserInput(Field.INPUT, '') - } - setPendingConfirmation(true) - setAttemptingTxn(false) - setShowAdvanced(false) - } - function modalHeader() { if (sending && !sendingWithSwap) { return ( @@ -644,7 +663,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {parsedAmounts[Field.INPUT]?.toSignificant(6)} {tokens[Field.INPUT]?.symbol} - + To {ENS ? ( @@ -656,7 +675,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {recipient?.slice(0, 8)}...{recipient?.slice(34, 42)}↗ - + ) : ( @@ -666,7 +685,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {recipient?.slice(0, 6)}...{recipient?.slice(36, 42)}↗ - + )} @@ -678,7 +697,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro - + {slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(4)} {tokens[Field.OUTPUT]?.symbol} @@ -706,14 +725,14 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {/* {!!slippageAdjustedAmounts[Field.INPUT] && slippageAdjustedAmounts[Field.INPUT].toSignificant(6)} */} - + {tokens[Field.INPUT]?.symbol || ''} - + @@ -722,7 +741,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {/* {!!slippageAdjustedAmounts[Field.OUTPUT] && slippageAdjustedAmounts[Field.OUTPUT].toSignificant(6)} */} - + {tokens[Field.OUTPUT]?.symbol || ''} @@ -782,17 +801,17 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro > {trade && showInverted ? (trade?.executionPrice?.invert()?.toSignificant(6) ?? '') + - ' ' + - tokens[Field.INPUT]?.symbol + - ' / ' + - tokens[Field.OUTPUT]?.symbol + ' ' + + tokens[Field.INPUT]?.symbol + + ' / ' + + tokens[Field.OUTPUT]?.symbol : (trade?.executionPrice?.toSignificant(6) ?? '') + - ' ' + - tokens[Field.OUTPUT]?.symbol + - ' / ' + - tokens[Field.INPUT]?.symbol} + ' ' + + tokens[Field.OUTPUT]?.symbol + + ' / ' + + tokens[Field.INPUT]?.symbol} setShowInverted(!showInverted)}> - + @@ -802,8 +821,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {independentField === Field.INPUT ? (sending ? 'Min sent' : 'Minimum received') : 'Maximum sold'} - + @@ -814,10 +832,10 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro : slippageAdjustedAmounts[Field.OUTPUT]?.toFixed(5) : '-' : slippageAdjustedAmounts[Field.INPUT] - ? slippageAdjustedAmounts[Field.INPUT]?.toFixed(5) === '0.00000' - ? '<0.00001' - : slippageAdjustedAmounts[Field.INPUT]?.toFixed(5) - : '-'} + ? slippageAdjustedAmounts[Field.INPUT]?.toFixed(5) === '0.00000' + ? '<0.00001' + : slippageAdjustedAmounts[Field.INPUT]?.toFixed(5) + : '-'} {parsedAmounts[Field.OUTPUT] && parsedAmounts[Field.INPUT] && ( @@ -833,7 +851,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro Price impact - + Liquidity Provider Fee - + {feeTimesInputFormatted @@ -877,7 +894,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro } } - const PriceBar = function () { + const PriceBar = function() { return ( @@ -924,7 +941,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro ? `Sending ${parsedAmounts[Field.OUTPUT]?.toSignificant(6)} ${tokens[Field.OUTPUT]?.symbol} to ${recipient}` : `Sending ${parsedAmounts[Field.INPUT]?.toSignificant(6)} ${tokens[Field.INPUT]?.symbol} to ${recipient}` : ` Swapping ${parsedAmounts[Field.INPUT]?.toSignificant(6)} ${tokens[Field.INPUT]?.symbol} for ${parsedAmounts[ - Field.OUTPUT + Field.OUTPUT ]?.toSignificant(6)} ${tokens[Field.OUTPUT]?.symbol}` function _onTokenSelect(address: string) { @@ -979,7 +996,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro Max )} - onUserInput(Field.INPUT, val)}/> + onUserInput(Field.INPUT, val)} /> - + setSendingWithSwap(false)} style={{ marginRight: '0px' }}> Remove Swap @@ -1063,7 +1080,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro /> {sendingWithSwap && ( - + )} @@ -1095,7 +1112,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {!noRoute && tokens[Field.OUTPUT] && tokens[Field.INPUT] && ( {advanced ? ( - + ) : ( {' '} @@ -1111,17 +1128,17 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro > {trade && showInverted ? (trade?.executionPrice?.invert()?.toSignificant(6) ?? '') + - ' ' + - tokens[Field.INPUT]?.symbol + - ' per ' + - tokens[Field.OUTPUT]?.symbol + ' ' + + tokens[Field.INPUT]?.symbol + + ' per ' + + tokens[Field.OUTPUT]?.symbol : (trade?.executionPrice?.toSignificant(6) ?? '') + - ' ' + - tokens[Field.OUTPUT]?.symbol + - ' per ' + - tokens[Field.INPUT]?.symbol} + ' ' + + tokens[Field.OUTPUT]?.symbol + + ' per ' + + tokens[Field.INPUT]?.symbol} setShowInverted(!showInverted)}> - + @@ -1141,8 +1158,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro : priceSlippage.toFixed(4) + '%' : '-'}{' '} - + )} @@ -1189,9 +1205,12 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {!account ? 'Connect Wallet' - : (generalError || inputError || outputError || recipientError || tradeError) || - (`${sending ? 'Send' : 'Swap'}${warningHigh ? ' Anyway' : ''}`) - } + : generalError || + inputError || + outputError || + recipientError || + tradeError || + `${sending ? 'Send' : 'Swap'}${warningHigh ? ' Anyway' : ''}`} )} @@ -1204,7 +1223,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro Show Advanced - + )} @@ -1215,10 +1234,10 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro Hide Advanced - + - + @@ -1233,8 +1252,8 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro text={ independentField === Field.INPUT ? sending - ? 'Price can change between when a transaction is submitted and when it is executed. This is the minimum amount you will send. A worse rate will cause your transaction to revert.' - : 'Price can change between when a transaction is submitted and when it is executed. This is the minimum amount you will receive. A worse rate will cause your transaction to revert.' + ? 'Price can change between when a transaction is submitted and when it is executed. This is the minimum amount you will send. A worse rate will cause your transaction to revert.' + : 'Price can change between when a transaction is submitted and when it is executed. This is the minimum amount you will receive. A worse rate will cause your transaction to revert.' : 'Price can change between when a transaction is submitted and when it is executed. This is the maximum amount you will pay. A worse rate will cause your transaction to revert.' } /> @@ -1244,18 +1263,18 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro {independentField === Field.INPUT ? slippageAdjustedAmounts[Field.OUTPUT] ? slippageAdjustedAmounts[Field.OUTPUT]?.lessThan( - new Fraction(JSBI.BigInt(1), JSBI.BigInt(10000)) - ) + new Fraction(JSBI.BigInt(1), JSBI.BigInt(10000)) + ) ? '<0.00001' : slippageAdjustedAmounts[Field.OUTPUT]?.toFixed(5) : '-' : slippageAdjustedAmounts[Field.INPUT] - ? slippageAdjustedAmounts[Field.INPUT]?.lessThan( + ? slippageAdjustedAmounts[Field.INPUT]?.lessThan( new Fraction(JSBI.BigInt(1), JSBI.BigInt(10000)) ) - ? '<0.00001' - : slippageAdjustedAmounts[Field.INPUT]?.toFixed(5) - : '-'} + ? '<0.00001' + : slippageAdjustedAmounts[Field.INPUT]?.toFixed(5) + : '-'} {parsedAmounts[Field.OUTPUT] && parsedAmounts[Field.INPUT] && ( @@ -1271,8 +1290,7 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro Price Impact - + Liquidity Provider Fee - + {feeTimesInputFormatted @@ -1303,13 +1320,12 @@ function ExchangePage({ sendingInput = false, history, params }: ExchangePagePro - + Set front running resistance - + - warningHigh ? theme.red1 : warningMedium ? theme.yellow2 : warningLow ? theme.green1 : theme.text1}; + warningHigh ? theme.red1 : warningMedium ? theme.yellow2 : warningLow ? theme.green1 : theme.text1}; ` export const InputGroup = styled(AutoColumn)` @@ -152,4 +152,4 @@ export const Dots = styled.span` content: '...'; } } -` \ No newline at end of file +` diff --git a/src/components/ExchangePage/swap-store.ts b/src/components/ExchangePage/swap-store.ts index 9395e9c649..0e7735421f 100644 --- a/src/components/ExchangePage/swap-store.ts +++ b/src/components/ExchangePage/swap-store.ts @@ -19,7 +19,12 @@ export interface SwapState { } } -export function initializeSwapState({ inputTokenAddress, outputTokenAddress, typedValue, independentField }): SwapState { +export function initializeSwapState({ + inputTokenAddress, + outputTokenAddress, + typedValue, + independentField +}): SwapState { return { independentField: independentField, typedValue: typedValue, @@ -110,21 +115,21 @@ export function useSwapStateReducer(params: QueryParams) { typedValue: params.inputTokenAddress && !params.outputTokenAddress ? params.inputTokenAmount - ? params.inputTokenAmount - : '' + ? params.inputTokenAmount + : '' : !params.inputTokenAddress && params.outputTokenAddress ? params.outputTokenAmount ? params.outputTokenAmount : '' : params.inputTokenAddress && params.outputTokenAddress + ? params.inputTokenAmount ? params.inputTokenAmount - ? params.inputTokenAmount - : '' : '' - ? '' - : '' - ? '' - : '' + : '' + ? '' + : '' + ? '' + : '' }, initializeSwapState ) diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx index bc033cfb49..5344315633 100644 --- a/src/components/Header/index.tsx +++ b/src/components/Header/index.tsx @@ -1,6 +1,5 @@ import React from 'react' import styled from 'styled-components' -import { withRouter } from 'react-router-dom' import Row from '../Row' import Menu from '../Menu' @@ -64,7 +63,7 @@ const TitleText = styled(Row)` `}; ` -const AccountElement = styled.div<{active: boolean;}>` +const AccountElement = styled.div<{ active: boolean }>` display: flex; display: flex; flex-direction: row; @@ -107,7 +106,7 @@ const Alpha = styled(GreyCard)` font-weight: 600; ` -const UniIcon = styled.div<{href: string}>` +const UniIcon = styled.div<{ href: string }>` transition: transform 0.3s ease; :hover { transform: rotate(-5deg); @@ -133,7 +132,7 @@ const MigrateBanner = styled(AutoColumn)` `}; ` -function Header({ history }) { +export default function Header() { const { account, chainId } = useWeb3React() const userEthBalance = useAddressBalance(account, WETH[chainId]) @@ -196,5 +195,3 @@ function Header({ history }) { ) } - -export default withRouter(Header) diff --git a/src/components/Identicon/index.tsx b/src/components/Identicon/index.tsx index a5573f51f1..deee37294b 100644 --- a/src/components/Identicon/index.tsx +++ b/src/components/Identicon/index.tsx @@ -24,5 +24,5 @@ export default function Identicon() { } }, [account]) - return + return } diff --git a/src/components/Loader/index.tsx b/src/components/Loader/index.tsx index 89567fb66f..bb2c5863f1 100644 --- a/src/components/Loader/index.tsx +++ b/src/components/Loader/index.tsx @@ -11,5 +11,5 @@ const SpinnerWrapper = styled(Spinner)<{ size: string }>` ` export default function Loader({ size }: { size: string }) { - return + return } diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index b3341327ae..24ddc4e55f 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -78,9 +78,9 @@ const MenuItem = styled(Link)` } ` -const CODE_LINK = !!process.env.REACT_APP_GIT_COMMIT_HASH ? - `https://github.com/Uniswap/uniswap-frontend/tree/${process.env.REACT_APP_GIT_COMMIT_HASH}`: - 'https://github.com/Uniswap/uniswap-frontend' +const CODE_LINK = !!process.env.REACT_APP_GIT_COMMIT_HASH + ? `https://github.com/Uniswap/uniswap-frontend/tree/${process.env.REACT_APP_GIT_COMMIT_HASH}` + : 'https://github.com/Uniswap/uniswap-frontend' export default function Menu() { const node = useRef() diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx index bec35170af..035d60eec1 100644 --- a/src/components/Modal/index.tsx +++ b/src/components/Modal/index.tsx @@ -22,8 +22,8 @@ const StyledDialogOverlay = styled(WrappedDialogOverlay).attrs({ background-color: ${({ theme }) => 'transparent'}; ${({ mobile }) => - mobile && - css` + mobile && + css` align-items: flex-end; `} @@ -56,13 +56,13 @@ const StyledDialogContent = styled(FilteredDialogContent)` max-width: 420px; ${({ maxHeight }) => - maxHeight && - css` + maxHeight && + css` max-height: ${maxHeight}vh; `} ${({ minHeight }) => - minHeight && - css` + minHeight && + css` min-height: ${minHeight}vh; `} display: flex; @@ -77,7 +77,7 @@ const StyledDialogContent = styled(FilteredDialogContent)` width: 85vw; max-height: 66vh; ${mobile && -css` + css` width: 100vw; border-radius: 20px; border-bottom-left-radius: 0; @@ -105,13 +105,13 @@ interface ModalProps { } export default function Modal({ - isOpen, - onDismiss, - minHeight = false, - maxHeight = 50, - initialFocusRef = null, - children - }: ModalProps) { + isOpen, + onDismiss, + minHeight = false, + maxHeight = 50, + initialFocusRef = null, + children +}: ModalProps) { const transitions = useTransition(isOpen, null, { config: { duration: 200 }, from: { opacity: 0 }, @@ -163,7 +163,9 @@ export default function Modal({ {props => ( `translate3d(${0}px,${y > 0 ? y : 0}px,0)`) }} + style={{ + transform: (xy as any).interpolate((x, y) => `translate3d(${0}px,${y > 0 ? y : 0}px,0)`) + }} > - + {children} @@ -203,7 +205,7 @@ export default function Modal({ isOpen={isOpen} mobile={isMobile} > - + {children} diff --git a/src/components/NavigationTabs/index.tsx b/src/components/NavigationTabs/index.tsx index e64948e694..b7b27c6503 100644 --- a/src/components/NavigationTabs/index.tsx +++ b/src/components/NavigationTabs/index.tsx @@ -1,15 +1,15 @@ -import React, { useCallback } from 'react'; -import styled from 'styled-components'; -import { darken } from 'polished'; -import { useTranslation } from 'react-i18next'; -import { withRouter, NavLink, Link as HistoryLink, RouteComponentProps } from 'react-router-dom'; +import React, { useCallback } from 'react' +import styled from 'styled-components' +import { darken } from 'polished' +import { useTranslation } from 'react-i18next' +import { withRouter, NavLink, Link as HistoryLink, RouteComponentProps } from 'react-router-dom' -import { Hover } from '../../theme'; -import { ArrowLeft } from 'react-feather'; -import { RowBetween } from '../Row'; -import QuestionHelper from '../Question'; +import { Hover } from '../../theme' +import { ArrowLeft } from 'react-feather' +import { RowBetween } from '../Row' +import QuestionHelper from '../Question' -import { useBodyKeyDown } from '../../hooks'; +import { useBodyKeyDown } from '../../hooks' const tabOrder = [ { @@ -27,16 +27,16 @@ const tabOrder = [ textKey: 'pool', regex: /\/pool/ } -]; +] const Tabs = styled.div` ${({ theme }) => theme.flexRowNoWrap} align-items: center; border-radius: 3rem; margin-bottom: 20px; -`; +` -const activeClassName = 'ACTIVE'; +const activeClassName = 'ACTIVE' const StyledNavLink = styled(NavLink).attrs({ activeClassName @@ -65,41 +65,41 @@ const StyledNavLink = styled(NavLink).attrs({ :focus { color: ${({ theme }) => darken(0.1, theme.text1)}; } -`; +` const ActiveText = styled.div` font-weight: 500; font-size: 20px; -`; +` const ArrowLink = styled(ArrowLeft)` color: ${({ theme }) => theme.text1}; -`; +` function NavigationTabs({ location: { pathname }, history }: RouteComponentProps<{}>) { - const { t } = useTranslation(); + const { t } = useTranslation() const navigate = useCallback( direction => { - const tabIndex = tabOrder.findIndex(({ regex }) => pathname.match(regex)); - history.push(tabOrder[ (tabIndex + tabOrder.length + direction) % tabOrder.length ].path); + const tabIndex = tabOrder.findIndex(({ regex }) => pathname.match(regex)) + history.push(tabOrder[(tabIndex + tabOrder.length + direction) % tabOrder.length].path) }, [pathname, history] - ); + ) const navigateRight = useCallback(() => { - navigate(1); - }, [navigate]); + navigate(1) + }, [navigate]) const navigateLeft = useCallback(() => { - navigate(-1); - }, [navigate]); + navigate(-1) + }, [navigate]) - useBodyKeyDown('ArrowRight', navigateRight); - useBodyKeyDown('ArrowLeft', navigateLeft); + useBodyKeyDown('ArrowRight', navigateRight) + useBodyKeyDown('ArrowLeft', navigateLeft) - const adding = pathname.match('/add'); - const removing = pathname.match('/remove'); - const finding = pathname.match('/find'); - const creating = pathname.match('/create'); + const adding = pathname.match('/add') + const removing = pathname.match('/remove') + const finding = pathname.match('/find') + const creating = pathname.match('/create') return ( <> @@ -107,7 +107,7 @@ function NavigationTabs({ location: { pathname }, history }: RouteComponentProps history.goBack()}> - + {adding ? 'Add' : 'Remove'} Liquidity - + Import Pool - + ) : creating ? ( - + Create Pool - + ) : ( @@ -149,7 +149,7 @@ function NavigationTabs({ location: { pathname }, history }: RouteComponentProps )} - ); + ) } -export default withRouter(NavigationTabs); +export default withRouter(NavigationTabs) diff --git a/src/components/NumericalInput/index.tsx b/src/components/NumericalInput/index.tsx index dcb8ce6d84..bdee51cf5f 100644 --- a/src/components/NumericalInput/index.tsx +++ b/src/components/NumericalInput/index.tsx @@ -1,7 +1,7 @@ import React from 'react' import styled from 'styled-components' -const StyledInput = styled.input<{error?: boolean; fontSize?: string; align?: string}>` +const StyledInput = styled.input<{ error?: boolean; fontSize?: string; align?: string }>` color: ${({ error, theme }) => error && theme.red1}; color: ${({ theme }) => theme.text1}; width: 0; @@ -45,8 +45,20 @@ function escapeRegExp(string: string): string { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') // $& means the whole matched string } -export const Input = React.memo(({ value, onUserInput, placeHolder = null, ...rest }: any) => { - function enforcer(nextUserInput: string) { +export const Input = React.memo(function InnerInput({ + value, + onUserInput, + placeHolder, + ...rest +}: { + value: string | number + onUserInput: (string) => void + placeHolder?: string + align?: 'right' | 'left' + id?: string + onClick?: () => void +}) { + const enforcer = (nextUserInput: string) => { if (nextUserInput === '' || inputRegex.test(escapeRegExp(nextUserInput))) { onUserInput(nextUserInput) } diff --git a/src/components/PoolFinder/index.tsx b/src/components/PoolFinder/index.tsx index 4cc63a84a7..32716998ec 100644 --- a/src/components/PoolFinder/index.tsx +++ b/src/components/PoolFinder/index.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react' -import { withRouter } from 'react-router-dom' +import { RouteComponentProps, withRouter } from 'react-router-dom' import { TokenAmount, JSBI, Token, Pair } from '@uniswap/sdk' import Row from '../Row' @@ -21,7 +21,7 @@ import { useWeb3React } from '@web3-react/core' import { useAddressBalance } from '../../contexts/Balances' import { usePair, useAllPairs } from '../../contexts/Pairs' -function PoolFinder({ history }) { +function PoolFinder({ history }: RouteComponentProps) { const Fields = { TOKEN0: 0, TOKEN1: 1 @@ -65,20 +65,20 @@ function PoolFinder({ history }) { function endSearch() { history.goBack() // return to previous page newLiquidity && - addPopup( - - - Pool Imported - - - - - UNI {token0?.symbol} / {token1?.symbol} + addPopup( + + + Pool Imported - - View on Uniswap Info. - - ) + + + + UNI {token0?.symbol} / {token1?.symbol} + + + View on Uniswap Info. + + ) } return ( @@ -101,7 +101,7 @@ function PoolFinder({ history }) { }} > - + {token0?.symbol} @@ -109,7 +109,7 @@ function PoolFinder({ history }) { )} - + {!token1Address ? ( - + {token1?.symbol} @@ -137,7 +137,8 @@ function PoolFinder({ history }) { )} {allowImport && ( + style={{ justifyItems: 'center', backgroundColor: '', padding: '12px 0px', borderRadius: '12px' }} + > {newLiquidity ? 'Pool Found!' : 'Pool already imported.'} diff --git a/src/components/Popups/index.tsx b/src/components/Popups/index.tsx index ebc3b1bd48..28982d1ba1 100644 --- a/src/components/Popups/index.tsx +++ b/src/components/Popups/index.tsx @@ -79,7 +79,7 @@ export default function App() { {activePopups.map(item => { return ( - removePopup(item.key)}/> + removePopup(item.key)} /> {React.cloneElement(item.content, { popKey: item.key })} ) @@ -98,7 +98,7 @@ export default function App() { .map(item => { return ( - removePopup(item.key)}/> + removePopup(item.key)} /> {React.cloneElement(item.content, { popKey: item.key })} ) diff --git a/src/components/PositionCard/index.tsx b/src/components/PositionCard/index.tsx index 50bc54d201..5efc7d26cd 100644 --- a/src/components/PositionCard/index.tsx +++ b/src/components/PositionCard/index.tsx @@ -31,7 +31,7 @@ const HoverCard = styled(Card)` ` interface PositionCardProps extends RouteComponentProps<{}> { - pairAddress: string; + pairAddress: string token0: Token token1: Token minimal?: boolean @@ -86,7 +86,7 @@ function PositionCard({ pairAddress, token0, token1, history, border, minimal = setShowMore(!showMore)}> - + {token0?.symbol}:{token1?.symbol} @@ -104,7 +104,7 @@ function PositionCard({ pairAddress, token0, token1, history, border, minimal = {token0Deposited ? ( - {!minimal && } + {!minimal && } {token0Deposited?.toFixed(8)} @@ -119,7 +119,7 @@ function PositionCard({ pairAddress, token0, token1, history, border, minimal = {token1Deposited ? ( - {!minimal && } + {!minimal && } {token1Deposited?.toFixed(8)} @@ -140,16 +140,16 @@ function PositionCard({ pairAddress, token0, token1, history, border, minimal = setShowMore(!showMore)} style={{ cursor: 'pointer' }}> - + {token0?.symbol}:{token1?.symbol} {showMore ? ( - + ) : ( - + )} @@ -167,7 +167,7 @@ function PositionCard({ pairAddress, token0, token1, history, border, minimal = {token0Deposited?.toFixed(8)} {!minimal && ( - + )} ) : ( @@ -187,7 +187,7 @@ function PositionCard({ pairAddress, token0, token1, history, border, minimal = {token1Deposited?.toFixed(8)} {!minimal && ( - + )} ) : ( diff --git a/src/components/Question/index.tsx b/src/components/Question/index.tsx index 5ae907982c..bbe0f4909e 100644 --- a/src/components/Question/index.tsx +++ b/src/components/Question/index.tsx @@ -62,7 +62,7 @@ const Popup = styled.div` `} ` -export default function QuestionHelper({ text }) { +export default function QuestionHelper({ text }: { text: string }) { const [showPopup, setPopup] = useState(false) return ( diff --git a/src/components/SearchModal/index.tsx b/src/components/SearchModal/index.tsx index ff67548b6d..99dd173c56 100644 --- a/src/components/SearchModal/index.tsx +++ b/src/components/SearchModal/index.tsx @@ -154,18 +154,18 @@ interface SearchModalProps extends RouteComponentProps<{}> { } function SearchModal({ - history, - isOpen, - onDismiss, - onTokenSelect, - urlAddedTokens, - filterType, - hiddenToken, - showSendWithSwap, - otherSelectedTokenAddress, - otherSelectedText, - showCommonBases = false - }: SearchModalProps) { + history, + isOpen, + onDismiss, + onTokenSelect, + urlAddedTokens, + filterType, + hiddenToken, + showSendWithSwap, + otherSelectedTokenAddress, + otherSelectedText, + showCommonBases = false +}: SearchModalProps) { const { t } = useTranslation() const { account, chainId } = useWeb3React() const theme = useContext(ThemeContext) @@ -377,7 +377,7 @@ function SearchModal({ }} > - + {`${token0?.symbol}/${token1?.symbol}`} {/* @@ -418,7 +418,7 @@ function SearchModal({ }} > - + {temporaryToken.symbol} (Found by search) @@ -431,16 +431,16 @@ function SearchModal({ return {t('noToken')} } } - // TODO is this the right place to link to create exchange? - // else if (isAddress(searchQuery) && tokenAddress === ethers.constants.AddressZero) { - // return ( - // <> - // {t('noToken')} - // - // {t('createExchange')} - // - // - // ) + // TODO is this the right place to link to create exchange? + // else if (isAddress(searchQuery) && tokenAddress === ethers.constants.AddressZero) { + // return ( + // <> + // {t('noToken')} + // + // {t('createExchange')} + // + // + // ) // } else { return filteredTokenList @@ -453,8 +453,8 @@ function SearchModal({ ? -1 : 1 : sortDirection - ? 1 - : -1 + ? 1 + : -1 }) .map(({ address, symbol, balance }) => { const urlAdded = urlAddedTokens && urlAddedTokens.hasOwnProperty(address) @@ -467,13 +467,12 @@ function SearchModal({ return ( (hiddenToken && hiddenToken === address ? () => { - } : _onTokenSelect(address))} + onClick={() => (hiddenToken && hiddenToken === address ? () => {} : _onTokenSelect(address))} disabled={hiddenToken && hiddenToken === address} selected={otherSelectedTokenAddress === address} > - + {symbol} @@ -500,9 +499,7 @@ function SearchModal({ {balance ? ( {zeroBalance && showSendWithSwap ? ( - + Send With Swap @@ -514,7 +511,7 @@ function SearchModal({ )} ) : account ? ( - + ) : ( '-' )} @@ -569,7 +566,7 @@ function SearchModal({ Import A Token - + To import a custom token, paste token address in the search bar. @@ -589,7 +586,7 @@ function SearchModal({ {filterType === 'tokens' ? 'Select A Token' : 'Select A Pool'} - + Common Bases - + {COMMON_BASES[chainId]?.map(token => { @@ -615,7 +612,7 @@ function SearchModal({ disable={hiddenToken === token.address} key={token.address} > - + {token.symbol} @@ -637,16 +634,16 @@ function SearchModal({ )} - {!showTokenImport &&
} + {!showTokenImport &&
} {!showTokenImport && {filterType === 'tokens' ? renderTokenList() : renderPairsList()}} - {!showTokenImport &&
} + {!showTokenImport &&
} {!showTokenImport && (
{filterType !== 'tokens' && ( - {!isMobile && 'Don\'t see a pool? '} + {!isMobile && "Don't see a pool? "} { history.push('/find') @@ -658,7 +655,7 @@ function SearchModal({ )} {filterType === 'tokens' && ( - {!isMobile && 'Don\'t see a token? '} + {!isMobile && "Don't see a token? "} { diff --git a/src/components/Slider/index.tsx b/src/components/Slider/index.tsx index 757005082a..0079c0ae47 100644 --- a/src/components/Slider/index.tsx +++ b/src/components/Slider/index.tsx @@ -58,12 +58,15 @@ export default function InputSlider({ value, onChange, override }: InputSliderPr const [internalVal, setInternalVal] = useState(value) const debouncedInternalValue = useDebounce(internalVal, 100) - const handleChange = useCallback((e, val) => { - setInternalVal(val) - if (val !== debouncedInternalValue) { - onChange(val) - } - }, [setInternalVal, onChange, debouncedInternalValue]) + const handleChange = useCallback( + (e, val) => { + setInternalVal(val) + if (val !== debouncedInternalValue) { + onChange(val) + } + }, + [setInternalVal, onChange, debouncedInternalValue] + ) useEffect(() => { if (override) { diff --git a/src/components/SlippageTabs/index.tsx b/src/components/SlippageTabs/index.tsx index 5004f25e38..198e1d1bf4 100644 --- a/src/components/SlippageTabs/index.tsx +++ b/src/components/SlippageTabs/index.tsx @@ -61,21 +61,21 @@ const Input = styled.input<{ active?: boolean }>` color: ${({ theme }) => theme.text1}; text-align: left; ${({ active }) => - active && - css` + active && + css` color: initial; cursor: initial; text-align: right; `} ${({ placeholder }) => - placeholder !== 'Custom' && - css` + placeholder !== 'Custom' && + css` text-align: right; color: ${({ theme }) => theme.text1}; `} ${({ color }) => - color === 'red' && - css` + color === 'red' && + css` color: ${({ theme }) => theme.red1}; `} ` @@ -84,8 +84,8 @@ const BottomError = styled(Text)` font-size: 14px; font-weight: 400; ${({ show }) => - show && - css` + show && + css` padding-top: 12px; `} ` @@ -94,9 +94,10 @@ const OptionCustom = styled(FancyButton)<{ active?: boolean; warning?: boolean } height: 2rem; position: relative; padding: 0 0.75rem; - border: ${({ theme, active, warning }) => active && `1px solid ${(warning ? theme.red1 : theme.blue1)}`}; + border: ${({ theme, active, warning }) => active && `1px solid ${warning ? theme.red1 : theme.blue1}`}; :hover { - border: ${({ theme, active, warning }) => active && `1px solid ${(warning ? darken(0.1, theme.red1) : darken(0.1, theme.blue1))}`}; + border: ${({ theme, active, warning }) => + active && `1px solid ${warning ? darken(0.1, theme.red1) : darken(0.1, theme.blue1)}`}; } input { @@ -116,12 +117,12 @@ const Percent = styled.div` font-size: 0, 8rem; flex-grow: 0; ${({ color, theme }) => - (color === 'faded' && - css` + (color === 'faded' && + css` color: ${theme.bg1}; `) || - (color === 'red' && - css` + (color === 'red' && + css` color: ${theme.red1}; `)}; ` @@ -133,7 +134,12 @@ interface TransactionDetailsProps { setDeadline: (deadline: number) => void } -export default function TransactionDetails({ setRawSlippage, rawSlippage, deadline, setDeadline }: TransactionDetailsProps) { +export default function TransactionDetails({ + setRawSlippage, + rawSlippage, + deadline, + setDeadline +}: TransactionDetailsProps) { const [activeIndex, setActiveIndex] = useState(2) const [warningType, setWarningType] = useState(WARNING_TYPE.none) @@ -147,26 +153,10 @@ export default function TransactionDetails({ setRawSlippage, rawSlippage, deadli const [deadlineInput, setDeadlineInput] = useState(deadline / 60) - function parseCustomDeadline(e) { - let val = e.target.value - const acceptableValues = [/^$/, /^\d+$/] - if (acceptableValues.some(re => re.test(val))) { - setDeadlineInput(val) - setDeadline(val * 60) - } - } - - const setFromCustom = () => { - setActiveIndex(4) - inputRef.current.focus() - // if there's a value, evaluate the bounds - checkBounds(debouncedInput) - } - const updateSlippage = useCallback( newSlippage => { // round to 2 decimals to prevent ethers error - let numParsed = newSlippage * 100 + const numParsed = newSlippage * 100 // set both slippage values in parents setRawSlippage(numParsed) @@ -174,39 +164,6 @@ export default function TransactionDetails({ setRawSlippage, rawSlippage, deadli [setRawSlippage] ) - // used for slippage presets - const setFromFixed = useCallback( - (index, slippage) => { - // update slippage in parent, reset errors and input state - updateSlippage(slippage) - setWarningType(WARNING_TYPE.none) - setActiveIndex(index) - }, - [updateSlippage] - ) - - useEffect(() => { - switch (initialSlippage) { - case 10: - setFromFixed(1, 0.1) - break - case 50: - setFromFixed(2, 0.5) - break - case 100: - setFromFixed(3, 1) - break - default: - // restrict to 2 decimal places - let acceptableValues = [/^$/, /^\d{1,2}$/, /^\d{0,2}\.\d{0,2}$/] - // if its within accepted decimal limit, update the input state - if (acceptableValues.some(val => val.test('' + (initialSlippage / 100)))) { - setUserInput('' + (initialSlippage / 100)) - setActiveIndex(4) - } - } - }, [initialSlippage, setFromFixed]) - const checkBounds = useCallback( slippageValue => { setWarningType(WARNING_TYPE.none) @@ -231,12 +188,60 @@ export default function TransactionDetails({ setRawSlippage, rawSlippage, deadli [updateSlippage] ) + function parseCustomDeadline(e) { + const val = e.target.value + const acceptableValues = [/^$/, /^\d+$/] + if (acceptableValues.some(re => re.test(val))) { + setDeadlineInput(val) + setDeadline(val * 60) + } + } + const setFromCustom = () => { + setActiveIndex(4) + inputRef.current.focus() + // if there's a value, evaluate the bounds + checkBounds(debouncedInput) + } + + // used for slippage presets + const setFromFixed = useCallback( + (index, slippage) => { + // update slippage in parent, reset errors and input state + updateSlippage(slippage) + setWarningType(WARNING_TYPE.none) + setActiveIndex(index) + }, + [updateSlippage] + ) + + useEffect(() => { + switch (initialSlippage) { + case 10: + setFromFixed(1, 0.1) + break + case 50: + setFromFixed(2, 0.5) + break + case 100: + setFromFixed(3, 1) + break + default: + // restrict to 2 decimal places + const acceptableValues = [/^$/, /^\d{1,2}$/, /^\d{0,2}\.\d{0,2}$/] + // if its within accepted decimal limit, update the input state + if (acceptableValues.some(val => val.test('' + initialSlippage / 100))) { + setUserInput('' + initialSlippage / 100) + setActiveIndex(4) + } + } + }, [initialSlippage, setFromFixed]) + // check that the theyve entered number and correct decimal const parseInput = e => { - let input = e.target.value + const input = e.target.value // restrict to 2 decimal places - let acceptableValues = [/^$/, /^\d{1,2}$/, /^\d{0,2}\.\d{0,2}$/] + const acceptableValues = [/^$/, /^\d{1,2}$/, /^\d{0,2}\.\d{0,2}$/] // if its within accepted decimal limit, update the input state if (acceptableValues.some(a => a.test(input))) { setUserInput(input) @@ -313,8 +318,8 @@ export default function TransactionDetails({ setRawSlippage, rawSlippage, deadli placeholder={ activeIndex === 4 ? !!userInput - ? '' - : '0' + ? '' + : '0' : activeIndex !== 4 && userInput !== '' ? userInput : 'Custom' @@ -352,8 +357,8 @@ export default function TransactionDetails({ setRawSlippage, rawSlippage, deadli : warningType !== WARNING_TYPE.none && warningType !== WARNING_TYPE.riskyEntryLow ? 'red' : warningType === WARNING_TYPE.riskyEntryLow - ? '#F3841E' - : '' + ? '#F3841E' + : '' } > {warningType === WARNING_TYPE.emptyInput && 'Enter a slippage percentage'} @@ -366,12 +371,16 @@ export default function TransactionDetails({ setRawSlippage, rawSlippage, deadli Deadline - + - + minutes diff --git a/src/components/TokenLogo/index.tsx b/src/components/TokenLogo/index.tsx index 9271e9b125..e9392503ab 100644 --- a/src/components/TokenLogo/index.tsx +++ b/src/components/TokenLogo/index.tsx @@ -20,7 +20,7 @@ const Image = styled.img<{ size: string }>` box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075); ` -const Emoji = styled.span<{size?:string}>` +const Emoji = styled.span<{ size?: string }>` display: flex; align-items: center; justify-content: center; @@ -30,7 +30,7 @@ const Emoji = styled.span<{size?:string}>` margin-bottom: -4px; ` -const StyledEthereumLogo = styled(EthereumLogo)<{size: string}>` +const StyledEthereumLogo = styled(EthereumLogo)<{ size: string }>` width: ${({ size }) => size}; height: ${({ size }) => size}; ` diff --git a/src/components/TxnPopup/index.tsx b/src/components/TxnPopup/index.tsx index bcf130a86c..5298345184 100644 --- a/src/components/TxnPopup/index.tsx +++ b/src/components/TxnPopup/index.tsx @@ -28,7 +28,7 @@ const delay = 100 export default function TxnPopup({ hash, success, summary, popKey }) { const { chainId } = useWeb3React() - let [count, setCount] = useState(1) + const [count, setCount] = useState(1) const [isRunning, setIsRunning] = useState(true) const [, , removePopup] = usePopups() @@ -44,9 +44,9 @@ export default function TxnPopup({ hash, success, summary, popKey }) { return ( setIsRunning(false)} onMouseLeave={() => setIsRunning(true)}> {success ? ( - + ) : ( - + )} @@ -54,7 +54,7 @@ export default function TxnPopup({ hash, success, summary, popKey }) { View on Etherscan - + ) } diff --git a/src/components/WalletModal/Option.tsx b/src/components/WalletModal/Option.tsx index 97d6d737f7..52218a0362 100644 --- a/src/components/WalletModal/Option.tsx +++ b/src/components/WalletModal/Option.tsx @@ -88,16 +88,16 @@ const IconWrapper = styled.div<{ size?: number }>` ` export default function Option({ - link = null, - clickable = true, - size = null, - onClick = null, - color, - header, - subheader = null, - icon, - active = false - }) { + link = null, + clickable = true, + size = null, + onClick = null, + color, + header, + subheader = null, + icon, + active = false +}) { const content = ( @@ -106,7 +106,7 @@ export default function Option({ {active ? ( -
+
) : ( @@ -117,7 +117,7 @@ export default function Option({ {subheader && {subheader}} - {'Icon'}/ + {'Icon'} ) diff --git a/src/components/WalletModal/PendingView.tsx b/src/components/WalletModal/PendingView.tsx index dbefe47c39..7fcc796620 100644 --- a/src/components/WalletModal/PendingView.tsx +++ b/src/components/WalletModal/PendingView.tsx @@ -75,10 +75,10 @@ export default function PendingView({ uri = '', size, connector, error = false, return ( - {!error && connector === walletconnect && } + {!error && connector === walletconnect && } - {!error && } + {!error && } {error ? (
Error connecting.
diff --git a/src/components/WalletModal/WalletConnectData.tsx b/src/components/WalletModal/WalletConnectData.tsx index e61167270d..0beed98e6b 100644 --- a/src/components/WalletModal/WalletConnectData.tsx +++ b/src/components/WalletModal/WalletConnectData.tsx @@ -21,7 +21,7 @@ export default function WalletConnectData({ uri = '', size }: WalletConnectDataP return ( {uri && ( - + )} ) diff --git a/src/components/WalletModal/index.tsx b/src/components/WalletModal/index.tsx index 16a6733868..2a955277d2 100644 --- a/src/components/WalletModal/index.tsx +++ b/src/components/WalletModal/index.tsx @@ -286,7 +286,7 @@ export default function WalletModal({ pendingTransactions, confirmedTransactions return ( - + {error instanceof UnsupportedChainIdError ? 'Wrong Network' : 'Error connecting'} @@ -313,7 +313,7 @@ export default function WalletModal({ pendingTransactions, confirmedTransactions return ( - + {walletView !== WALLET_VIEWS.ACCOUNT ? ( @@ -358,12 +358,7 @@ export default function WalletModal({ pendingTransactions, confirmedTransactions } return ( - + {getModalContent()} ) diff --git a/src/components/Web3Status/index.tsx b/src/components/Web3Status/index.tsx index 0fffbda6ff..62edc2ea65 100644 --- a/src/components/Web3Status/index.tsx +++ b/src/components/Web3Status/index.tsx @@ -76,8 +76,8 @@ const Web3StatusConnect = styled(Web3StatusGeneric)` } ${({ faded }) => - faded && - css` + faded && + css` background-color: ${({ theme }) => theme.blue5}; border: 1px solid ${({ theme }) => theme.blue5}; color: ${({ theme }) => theme.buttonSecondaryText}; @@ -140,29 +140,29 @@ export default function Web3Status() { // handle the logo we want to show with the account function getStatusIcon() { if (connector === injected) { - return + return } else if (connector === walletconnect) { return ( - {''}/ + {''} ) } else if (connector === walletlink) { return ( - {''}/ + {''} ) } else if (connector === fortmatic) { return ( - {''}/ + {''} ) } else if (connector === portis) { return ( - {''}/ + {''} ) } @@ -174,7 +174,7 @@ export default function Web3Status() { {hasPendingTransactions ? ( - {pending?.length} Pending + {pending?.length} Pending ) : ( {ENSName || shortenAddress(account)} @@ -185,7 +185,7 @@ export default function Web3Status() { } else if (error) { return ( - + {error instanceof UnsupportedChainIdError ? 'Wrong Network' : 'Error'} ) @@ -205,7 +205,7 @@ export default function Web3Status() { return ( <> {getWeb3Status()} - + ) } diff --git a/src/connectors/Fortmatic.ts b/src/connectors/Fortmatic.ts index dfbbd23c12..ba2ad42bbc 100644 --- a/src/connectors/Fortmatic.ts +++ b/src/connectors/Fortmatic.ts @@ -14,10 +14,7 @@ export class FortmaticConnector extends FortmaticConnectorCore { if (!this.fortmatic) { const { default: Fortmatic } = await import('fortmatic') const { apiKey, chainId } = this as any - this.fortmatic = new Fortmatic( - apiKey, - chainId === 1 || chainId === 4 ? undefined : chainIdToNetwork[chainId] - ) + this.fortmatic = new Fortmatic(apiKey, chainId === 1 || chainId === 4 ? undefined : chainIdToNetwork[chainId]) } const provider = this.fortmatic.getProvider() diff --git a/src/connectors/Network.ts b/src/connectors/Network.ts index e76a2ffd13..13b51b5eff 100644 --- a/src/connectors/Network.ts +++ b/src/connectors/Network.ts @@ -3,13 +3,13 @@ import { NetworkConnector as NetworkConnectorCore } from '@web3-react/network-co export class NetworkConnector extends NetworkConnectorCore { pause() { if ((this as any).active) { - (this as any).providers[(this as any).currentChainId].stop() + ;(this as any).providers[(this as any).currentChainId].stop() } } resume() { if ((this as any).active) { - (this as any).providers[(this as any).currentChainId].start() + ;(this as any).providers[(this as any).currentChainId].start() } } } diff --git a/src/contexts/Allowances.tsx b/src/contexts/Allowances.tsx index d7d7693b86..6147ee3912 100644 --- a/src/contexts/Allowances.tsx +++ b/src/contexts/Allowances.tsx @@ -1,13 +1,27 @@ -import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react' -import { Token, TokenAmount, WETH } from '@uniswap/sdk' +import { BigintIsh, Token, TokenAmount, WETH } from '@uniswap/sdk' +import { BigNumber } from 'ethers/utils' +import React, { createContext, useCallback, useContext, useEffect, useMemo, useReducer } from 'react' import { useWeb3React } from '../hooks' -import { safeAccess, isAddress, getTokenAllowance } from '../utils' +import { getTokenAllowance, isAddress } from '../utils' import { useBlockNumber } from './Application' const UPDATE = 'UPDATE' -const AllowancesContext = createContext([]) +interface AllowancesState { + [chainId: number]: { + [address: string]: { + [tokenAddress: string]: { + [spenderAddress: string]: { + value: BigintIsh + blockNumber: BigNumber + } + } + } + } +} + +const AllowancesContext = createContext<[AllowancesState, any]>([{}, {}]) function useAllowancesContext() { return useContext(AllowancesContext) @@ -20,11 +34,11 @@ function reducer(state, { type, payload }) { return { ...state, [networkId]: { - ...(safeAccess(state, [networkId]) || {}), + ...state?.[networkId], [address]: { - ...(safeAccess(state, [networkId, address]) || {}), + ...state?.[networkId]?.[address], [tokenAddress]: { - ...(safeAccess(state, [networkId, address, tokenAddress]) || {}), + ...state?.[networkId]?.[address]?.[tokenAddress], [spenderAddress]: { value, blockNumber @@ -34,9 +48,8 @@ function reducer(state, { type, payload }) { } } } - default: { + default: throw Error(`Unexpected action type in AllowancesContext reducer: '${type}'.`) - } } } @@ -60,7 +73,7 @@ export function useAddressAllowance(address: string, token: Token, spenderAddres const globalBlockNumber = useBlockNumber() const [state, { update }] = useAllowancesContext() - const { value, blockNumber } = safeAccess(state, [chainId, address, token?.address, spenderAddress]) || {} + const { value, blockNumber } = state?.[chainId]?.[address]?.[token?.address]?.[spenderAddress] ?? {} useEffect(() => { if ( @@ -92,6 +105,5 @@ export function useAddressAllowance(address: string, token: Token, spenderAddres } }, [address, token, spenderAddress, value, blockNumber, globalBlockNumber, chainId, library, update]) - const newTokenAmount: TokenAmount = value ? new TokenAmount(token, value) : null - return newTokenAmount + return value ? new TokenAmount(token, value) : null } diff --git a/src/contexts/Application.tsx b/src/contexts/Application.tsx index dfdea7f011..c0f6d5bc4a 100644 --- a/src/contexts/Application.tsx +++ b/src/contexts/Application.tsx @@ -1,7 +1,6 @@ import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react' import { useWeb3React } from '../hooks' -import { safeAccess } from '../utils' const BLOCK_NUMBER = 'BLOCK_NUMBER' const USD_PRICE = 'USD_PRICE' @@ -17,22 +16,25 @@ const USER_ADVANCED = 'USER_ADVANCED' const TOGGLE_USER_ADVANCED = 'TOGGLE_USER_ADVANCED' interface ApplicationState { - BLOCK_NUMBER: {}, - USD_PRICE: {}, - POPUP_LIST: Array<{ key: number; show: boolean; content: React.ReactElement }>, - POPUP_KEY: number, - WALLET_MODAL_OPEN: boolean, + BLOCK_NUMBER: {} + USD_PRICE: {} + POPUP_LIST: Array<{ key: number; show: boolean; content: React.ReactElement }> + POPUP_KEY: number + WALLET_MODAL_OPEN: boolean USER_ADVANCED: boolean } -const ApplicationContext = createContext<[ApplicationState, { [updater: string]: (...args: any[]) => void }]>([{ - [BLOCK_NUMBER]: {}, - [USD_PRICE]: {}, - [POPUP_LIST]: [], - [POPUP_KEY]: 0, - [WALLET_MODAL_OPEN]: false, - [USER_ADVANCED]: false -}, {}]) +const ApplicationContext = createContext<[ApplicationState, { [updater: string]: (...args: any[]) => void }]>([ + { + [BLOCK_NUMBER]: {}, + [USD_PRICE]: {}, + [POPUP_LIST]: [], + [POPUP_KEY]: 0, + [WALLET_MODAL_OPEN]: false, + [USER_ADVANCED]: false + }, + {} +]) function useApplicationContext() { return useContext(ApplicationContext) @@ -45,7 +47,7 @@ function reducer(state: ApplicationState, { type, payload }): ApplicationState { return { ...state, [BLOCK_NUMBER]: { - ...(safeAccess(state, [BLOCK_NUMBER]) || {}), + ...state?.[BLOCK_NUMBER], [networkId]: blockNumber } } @@ -80,9 +82,12 @@ export default function Provider({ children }) { [USER_ADVANCED]: false }) - const updateBlockNumber = useCallback((networkId, blockNumber) => { - dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } }) - }, [dispatch]) + const updateBlockNumber = useCallback( + (networkId, blockNumber) => { + dispatch({ type: UPDATE_BLOCK_NUMBER, payload: { networkId, blockNumber } }) + }, + [dispatch] + ) const toggleWalletModal = useCallback(() => { dispatch({ type: TOGGLE_WALLET_MODAL, payload: null }) @@ -92,9 +97,12 @@ export default function Provider({ children }) { dispatch({ type: TOGGLE_USER_ADVANCED, payload: null }) }, [dispatch]) - const setPopups = useCallback(newList => { - dispatch({ type: ADD_POPUP, payload: { newList } }) - }, [dispatch]) + const setPopups = useCallback( + newList => { + dispatch({ type: ADD_POPUP, payload: { newList } }) + }, + [dispatch] + ) return ( void, (key: number) => void] { +export function usePopups(): [ + ApplicationState['POPUP_LIST'], + (content: React.ReactElement) => void, + (key: number) => void +] { const [state, { setPopups }] = useApplicationContext() const index = state[POPUP_KEY] diff --git a/src/contexts/Balances.tsx b/src/contexts/Balances.tsx index fb87c6c51c..62c538ba00 100644 --- a/src/contexts/Balances.tsx +++ b/src/contexts/Balances.tsx @@ -411,7 +411,7 @@ export function useAllBalances(): Array { if (!state || !state[chainId]) { return {} } else { - let newBalances = {} + const newBalances = {} Object.keys(state[chainId]).map(address => { return Object.keys(state[chainId][address]).map(tokenAddress => { if (state[chainId][address][tokenAddress].value) { diff --git a/src/contexts/Transactions.tsx b/src/contexts/Transactions.tsx index 226fcd83c1..03579faa02 100644 --- a/src/contexts/Transactions.tsx +++ b/src/contexts/Transactions.tsx @@ -3,21 +3,23 @@ import React, { createContext, useContext, useReducer, useMemo, useCallback, use import TxnPopup from '../components/TxnPopup' import { useWeb3React } from '../hooks' -import { safeAccess } from '../utils' import { useBlockNumber, usePopups } from './Application' -const RESPONSE = 'response' -const CUSTOM_DATA = 'CUSTOM_DATA' -const BLOCK_NUMBER_CHECKED = 'BLOCK_NUMBER_CHECKED' -const RECEIPT = 'receipt' -const SUMMARY = 'summary' - const ADD = 'ADD' const CHECK = 'CHECK' const FINALIZE = 'FINALIZE' interface TransactionState { - + [chainId: number]: { + [txHash: string]: { + blockNumberChecked: any + response: { + customData?: any + summary: any + } + receipt: any + } + } } const TransactionsContext = createContext<[TransactionState, { [updater: string]: (...args: any[]) => void }]>([{}, {}]) @@ -26,21 +28,21 @@ export function useTransactionsContext() { return useContext(TransactionsContext) } -function reducer(state, { type, payload }) { +function reducer(state: TransactionState, { type, payload }): TransactionState { switch (type) { case ADD: { const { networkId, hash, response } = payload - if (safeAccess(state, [networkId, hash]) !== null) { + if (state[networkId]?.[hash]) { throw Error('Attempted to add existing transaction.') } return { ...state, [networkId]: { - ...(safeAccess(state, [networkId]) || {}), + ...state[networkId], [hash]: { - [RESPONSE]: response + response } } } @@ -48,17 +50,17 @@ function reducer(state, { type, payload }) { case CHECK: { const { networkId, hash, blockNumber } = payload - if (safeAccess(state, [networkId, hash]) === null) { + if (!state[networkId]?.[hash]) { throw Error('Attempted to check non-existent transaction.') } return { ...state, [networkId]: { - ...(safeAccess(state, [networkId]) || {}), + ...state[networkId], [hash]: { - ...(safeAccess(state, [networkId, hash]) || {}), - [BLOCK_NUMBER_CHECKED]: blockNumber + ...state[networkId]?.[hash], + blockNumberChecked: blockNumber } } } @@ -66,17 +68,17 @@ function reducer(state, { type, payload }) { case FINALIZE: { const { networkId, hash, receipt } = payload - if (safeAccess(state, [networkId, hash]) === null) { + if (!state[networkId]?.[hash]) { throw Error('Attempted to finalize non-existent transaction.') } return { ...state, [networkId]: { - ...(safeAccess(state, [networkId]) || {}), + ...state[networkId], [hash]: { - ...(safeAccess(state, [networkId, hash]) || {}), - [RECEIPT]: receipt + ...state[networkId]?.[hash], + receipt } } } @@ -115,7 +117,7 @@ export function Updater() { const globalBlockNumber = useBlockNumber() const [state, { check, finalize }] = useTransactionsContext() - const allTransactions = safeAccess(state, [chainId]) || {} + const allTransactions = state[chainId] ?? {} // show popup on confirm const [, addPopup] = usePopups() @@ -125,7 +127,7 @@ export function Updater() { let stale = false Object.keys(allTransactions) .filter( - hash => !allTransactions[hash][RECEIPT] && allTransactions[hash][BLOCK_NUMBER_CHECKED] !== globalBlockNumber + hash => !allTransactions[hash].receipt && allTransactions[hash].blockNumberChecked !== globalBlockNumber ) .forEach(hash => { library @@ -138,12 +140,22 @@ export function Updater() { finalize(chainId, hash, receipt) // add success or failure popup if (receipt.status === 1) { - addPopup() + addPopup( + + ) } else { addPopup( - + ) } } @@ -173,11 +185,11 @@ export function useTransactionAdder() { if (!(chainId || chainId === 0)) { throw Error(`Invalid networkId '${chainId}`) } - const hash = safeAccess(response, ['hash']) + const hash = response?.hash if (!hash) { throw Error('No transaction hash found.') } - add(chainId, hash, { ...response, [CUSTOM_DATA]: customData, [SUMMARY]: summary }) + add(chainId, hash, { ...response, customData: customData, summary }) }, [chainId, add] ) @@ -188,18 +200,18 @@ export function useAllTransactions() { const [state] = useTransactionsContext() - return safeAccess(state, [chainId]) || {} + return state[chainId] || {} } export function usePendingApproval(tokenAddress) { const allTransactions = useAllTransactions() return ( Object.keys(allTransactions).filter(hash => { - if (allTransactions[hash][RECEIPT]) { + if (allTransactions[hash]?.receipt) { return false - } else if (!allTransactions[hash][RESPONSE]) { + } else if (!allTransactions[hash]?.response) { return false - } else if (allTransactions[hash][RESPONSE][CUSTOM_DATA].approval !== tokenAddress) { + } else if (allTransactions[hash]?.response?.customData?.approval !== tokenAddress) { return false } else { return true diff --git a/src/hooks/useInterval.ts b/src/hooks/useInterval.ts index 8ce326f6de..6674ab588c 100644 --- a/src/hooks/useInterval.ts +++ b/src/hooks/useInterval.ts @@ -6,8 +6,6 @@ export default function useInterval(callback: () => void, delay: null | number) // Remember the latest callback. useEffect(() => { savedCallback.current = callback - return () => { - } }, [callback]) // Set up the interval. @@ -17,10 +15,8 @@ export default function useInterval(callback: () => void, delay: null | number) } if (delay !== null) { - let id = setInterval(tick, delay) + const id = setInterval(tick, delay) return () => clearInterval(id) } - return () => { - } }, [delay]) -} \ No newline at end of file +} diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 29b3615191..c2528baead 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -99,21 +99,21 @@ export default function App() { -
+
- + - + {/* this Suspense is for route code-splitting */} - }/> - }/> - }/> - }/> - }/> - }/> + } /> + } /> + } /> + } /> + } /> + } /> } else { - return + return } }} /> @@ -142,19 +142,19 @@ export default function App() { const t1 = tokens?.[1] === 'ETH' ? 'ETH' : isAddress(tokens?.[1]) ? isAddress(tokens[1]) : undefined if (t0 && t1) { - return + return } else { - return + return } }} /> - + -