Commit 0fa238af authored by Moody Salem's avatar Moody Salem Committed by GitHub

fix(swap): swap to account if recipient is null (#940)

* fix(swap): swap to account if recipient is null

* fix naming and strict ts error
parent 21c1484c
...@@ -62,12 +62,13 @@ export function useSwapCallback( ...@@ -62,12 +62,13 @@ export function useSwapCallback(
trade: Trade | undefined, // trade to execute, required trade: Trade | undefined, // trade to execute, required
allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips allowedSlippage: number = INITIAL_ALLOWED_SLIPPAGE, // in bips
deadline: number = DEFAULT_DEADLINE_FROM_NOW, // in seconds from now deadline: number = DEFAULT_DEADLINE_FROM_NOW, // in seconds from now
recipientAddressOrName: string // the ENS name or address of the recipient of the trade recipientAddressOrName: string | null // the ENS name or address of the recipient of the trade, or null if swap should be returned to sender
): null | (() => Promise<string>) { ): null | (() => Promise<string>) {
const { account, chainId, library } = useActiveWeb3React() const { account, chainId, library } = useActiveWeb3React()
const addTransaction = useTransactionAdder() const addTransaction = useTransactionAdder()
const { address: recipient } = useENS(recipientAddressOrName) const { address: recipientAddress } = useENS(recipientAddressOrName)
const recipient = recipientAddressOrName === null ? account : recipientAddress
const tradeVersion = getTradeVersion(trade) const tradeVersion = getTradeVersion(trade)
const v1Exchange = useV1ExchangeContract(useV1TradeExchangeAddress(trade), true) const v1Exchange = useV1ExchangeContract(useV1TradeExchangeAddress(trade), true)
...@@ -284,7 +285,9 @@ export function useSwapCallback( ...@@ -284,7 +285,9 @@ export function useSwapCallback(
recipient === account recipient === account
? base ? base
: `${base} to ${ : `${base} to ${
isAddress(recipientAddressOrName) ? shortenAddress(recipientAddressOrName) : recipientAddressOrName recipientAddressOrName && isAddress(recipientAddressOrName)
? shortenAddress(recipientAddressOrName)
: recipientAddressOrName
}` }`
const withVersion = const withVersion =
......
import { JSBI, TokenAmount, WETH } from '@uniswap/sdk' import { JSBI, TokenAmount, WETH } from '@uniswap/sdk'
import React, { useContext, useState, useEffect } from 'react' import React, { useContext, useState, useEffect, useCallback } from 'react'
import { ArrowDown } from 'react-feather' import { ArrowDown } from 'react-feather'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import { Text } from 'rebass' import { Text } from 'rebass'
...@@ -61,18 +61,19 @@ export default function Swap() { ...@@ -61,18 +61,19 @@ export default function Swap() {
// swap state // swap state
const { independentField, typedValue, recipient } = useSwapState() const { independentField, typedValue, recipient } = useSwapState()
const { bestTrade: bestTradeV2, tokenBalances, parsedAmount, tokens, error, v1Trade } = useDerivedSwapInfo() const { v1Trade, v2Trade, tokenBalances, parsedAmount, tokens, error } = useDerivedSwapInfo()
const { address: recipientAddress } = useENSAddress(recipient) const { address: recipientAddress } = useENSAddress(recipient)
const toggledVersion = useToggledVersion() const toggledVersion = useToggledVersion()
const trade = { const trade =
[Version.v1]: v1Trade, {
[Version.v2]: bestTradeV2 [Version.v1]: v1Trade,
}[toggledVersion] [Version.v2]: v2Trade
}[toggledVersion] ?? undefined
const betterTradeLinkVersion: Version | undefined = const betterTradeLinkVersion: Version | undefined =
toggledVersion === Version.v2 && isTradeBetter(bestTradeV2, v1Trade, BETTER_TRADE_LINK_THRESHOLD) toggledVersion === Version.v2 && isTradeBetter(v2Trade, v1Trade, BETTER_TRADE_LINK_THRESHOLD)
? Version.v1 ? Version.v1
: toggledVersion === Version.v1 && isTradeBetter(v1Trade, bestTradeV2) : toggledVersion === Version.v1 && isTradeBetter(v1Trade, v2Trade)
? Version.v2 ? Version.v2
: undefined : undefined
...@@ -85,6 +86,19 @@ export default function Swap() { ...@@ -85,6 +86,19 @@ export default function Swap() {
const isValid = !error const isValid = !error
const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT
const handleTypeInput = useCallback(
(field, value) => {
onUserInput(Field.INPUT, value)
},
[onUserInput]
)
const handleTypeOutput = useCallback(
(field, value) => {
onUserInput(Field.OUTPUT, value)
},
[onUserInput]
)
// modal and loading // modal and loading
const [showConfirm, setShowConfirm] = useState<boolean>(false) // show confirmation modal const [showConfirm, setShowConfirm] = useState<boolean>(false) // show confirmation modal
const [attemptingTxn, setAttemptingTxn] = useState<boolean>(false) // waiting for user confirmaion/rejection const [attemptingTxn, setAttemptingTxn] = useState<boolean>(false) // waiting for user confirmaion/rejection
...@@ -92,15 +106,13 @@ export default function Swap() { ...@@ -92,15 +106,13 @@ export default function Swap() {
const formattedAmounts = { const formattedAmounts = {
[independentField]: typedValue, [independentField]: typedValue,
[dependentField]: parsedAmounts[dependentField] ? parsedAmounts[dependentField].toSignificant(6) : '' [dependentField]: parsedAmounts[dependentField]?.toSignificant(6) ?? ''
} }
const route = trade?.route const route = trade?.route
const userHasSpecifiedInputOutput = const userHasSpecifiedInputOutput = Boolean(
!!tokens[Field.INPUT] && tokens[Field.INPUT] && tokens[Field.OUTPUT] && parsedAmounts[independentField]?.greaterThan(JSBI.BigInt(0))
!!tokens[Field.OUTPUT] && )
!!parsedAmounts[independentField] &&
parsedAmounts[independentField].greaterThan(JSBI.BigInt(0))
const noRoute = !route const noRoute = !route
// check whether the user has approved the router on the input token // check whether the user has approved the router on the input token
...@@ -116,19 +128,22 @@ export default function Swap() { ...@@ -116,19 +128,22 @@ export default function Swap() {
} }
}, [approval, approvalSubmitted]) }, [approval, approvalSubmitted])
const maxAmountInput: TokenAmount = let maxAmountInput: TokenAmount | undefined
!!tokenBalances[Field.INPUT] && {
!!tokens[Field.INPUT] && const inputToken = tokens[Field.INPUT]
!!WETH[chainId] && maxAmountInput =
tokenBalances[Field.INPUT].greaterThan( inputToken &&
new TokenAmount(tokens[Field.INPUT], tokens[Field.INPUT].equals(WETH[chainId]) ? MIN_ETH : '0') chainId &&
) WETH[chainId] &&
? tokens[Field.INPUT].equals(WETH[chainId]) tokenBalances[Field.INPUT]?.greaterThan(
? tokenBalances[Field.INPUT].subtract(new TokenAmount(WETH[chainId], MIN_ETH)) new TokenAmount(inputToken, inputToken.equals(WETH[chainId]) ? MIN_ETH : '0')
: tokenBalances[Field.INPUT] )
: undefined ? inputToken.equals(WETH[chainId])
const atMaxAmountInput: boolean = ? tokenBalances[Field.INPUT]?.subtract(new TokenAmount(WETH[chainId], MIN_ETH))
maxAmountInput && parsedAmounts[Field.INPUT] ? maxAmountInput.equalTo(parsedAmounts[Field.INPUT]) : undefined : tokenBalances[Field.INPUT]
: undefined
}
const atMaxAmountInput = Boolean(maxAmountInput && parsedAmounts[Field.INPUT]?.equalTo(maxAmountInput))
const slippageAdjustedAmounts = computeSlippageAdjustedAmounts(trade, allowedSlippage) const slippageAdjustedAmounts = computeSlippageAdjustedAmounts(trade, allowedSlippage)
...@@ -141,6 +156,9 @@ export default function Swap() { ...@@ -141,6 +156,9 @@ export default function Swap() {
if (priceImpactWithoutFee && !confirmPriceImpactWithoutFee(priceImpactWithoutFee)) { if (priceImpactWithoutFee && !confirmPriceImpactWithoutFee(priceImpactWithoutFee)) {
return return
} }
if (!swapCallback) {
return
}
setAttemptingTxn(true) setAttemptingTxn(true)
swapCallback() swapCallback()
.then(hash => { .then(hash => {
...@@ -155,7 +173,9 @@ export default function Swap() { ...@@ -155,7 +173,9 @@ export default function Swap() {
: (recipientAddress ?? recipient) === account : (recipientAddress ?? recipient) === account
? 'Swap w/o Send + recipient' ? 'Swap w/o Send + recipient'
: 'Swap w/ Send', : 'Swap w/ Send',
label: [trade.inputAmount.token.symbol, trade.outputAmount.token.symbol, getTradeVersion(trade)].join('/') label: [trade?.inputAmount?.token?.symbol, trade?.outputAmount?.token?.symbol, getTradeVersion(trade)].join(
'/'
)
}) })
}) })
.catch(error => { .catch(error => {
...@@ -248,7 +268,7 @@ export default function Swap() { ...@@ -248,7 +268,7 @@ export default function Swap() {
value={formattedAmounts[Field.INPUT]} value={formattedAmounts[Field.INPUT]}
showMaxButton={!atMaxAmountInput} showMaxButton={!atMaxAmountInput}
token={tokens[Field.INPUT]} token={tokens[Field.INPUT]}
onUserInput={onUserInput} onUserInput={handleTypeInput}
onMax={() => { onMax={() => {
maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact()) maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact())
}} }}
...@@ -284,7 +304,7 @@ export default function Swap() { ...@@ -284,7 +304,7 @@ export default function Swap() {
<CurrencyInputPanel <CurrencyInputPanel
field={Field.OUTPUT} field={Field.OUTPUT}
value={formattedAmounts[Field.OUTPUT]} value={formattedAmounts[Field.OUTPUT]}
onUserInput={onUserInput} onUserInput={handleTypeOutput}
label={independentField === Field.INPUT ? 'To (estimated)' : 'To'} label={independentField === Field.INPUT ? 'To (estimated)' : 'To'}
showMaxButton={false} showMaxButton={false}
token={tokens[Field.OUTPUT]} token={tokens[Field.OUTPUT]}
......
// Redirects to swap but only replace the pathname
import React from 'react' import React from 'react'
import { Redirect, RouteComponentProps } from 'react-router-dom' import { Redirect, RouteComponentProps } from 'react-router-dom'
// Redirects to swap but only replace the pathname
export function RedirectPathToSwapOnly({ location }: RouteComponentProps) { export function RedirectPathToSwapOnly({ location }: RouteComponentProps) {
return <Redirect to={{ ...location, pathname: '/swap' }} /> return <Redirect to={{ ...location, pathname: '/swap' }} />
} }
......
{
"extends": "../../../tsconfig.strict.json",
"include": ["**/*"]
}
\ No newline at end of file
...@@ -91,7 +91,7 @@ export function useDerivedSwapInfo(): { ...@@ -91,7 +91,7 @@ export function useDerivedSwapInfo(): {
tokens: { [field in Field]?: Token } tokens: { [field in Field]?: Token }
tokenBalances: { [field in Field]?: TokenAmount } tokenBalances: { [field in Field]?: TokenAmount }
parsedAmount: TokenAmount | undefined parsedAmount: TokenAmount | undefined
bestTrade: Trade | null v2Trade: Trade | undefined
error?: string error?: string
v1Trade: Trade | undefined v1Trade: Trade | undefined
} { } {
...@@ -123,7 +123,7 @@ export function useDerivedSwapInfo(): { ...@@ -123,7 +123,7 @@ export function useDerivedSwapInfo(): {
const bestTradeExactIn = useTradeExactIn(isExactIn ? parsedAmount : undefined, tokenOut ?? undefined) const bestTradeExactIn = useTradeExactIn(isExactIn ? parsedAmount : undefined, tokenOut ?? undefined)
const bestTradeExactOut = useTradeExactOut(tokenIn ?? undefined, !isExactIn ? parsedAmount : undefined) const bestTradeExactOut = useTradeExactOut(tokenIn ?? undefined, !isExactIn ? parsedAmount : undefined)
const bestTrade = isExactIn ? bestTradeExactIn : bestTradeExactOut const v2Trade = isExactIn ? bestTradeExactIn : bestTradeExactOut
const tokenBalances = { const tokenBalances = {
[Field.INPUT]: relevantTokenBalances?.[tokenIn?.address ?? ''], [Field.INPUT]: relevantTokenBalances?.[tokenIn?.address ?? ''],
...@@ -157,8 +157,7 @@ export function useDerivedSwapInfo(): { ...@@ -157,8 +157,7 @@ export function useDerivedSwapInfo(): {
const [allowedSlippage] = useUserSlippageTolerance() const [allowedSlippage] = useUserSlippageTolerance()
const slippageAdjustedAmounts = const slippageAdjustedAmounts = v2Trade && allowedSlippage && computeSlippageAdjustedAmounts(v2Trade, allowedSlippage)
bestTrade && allowedSlippage && computeSlippageAdjustedAmounts(bestTrade, allowedSlippage)
const slippageAdjustedAmountsV1 = const slippageAdjustedAmountsV1 =
v1Trade && allowedSlippage && computeSlippageAdjustedAmounts(v1Trade, allowedSlippage) v1Trade && allowedSlippage && computeSlippageAdjustedAmounts(v1Trade, allowedSlippage)
...@@ -183,7 +182,7 @@ export function useDerivedSwapInfo(): { ...@@ -183,7 +182,7 @@ export function useDerivedSwapInfo(): {
tokens, tokens,
tokenBalances, tokenBalances,
parsedAmount, parsedAmount,
bestTrade, v2Trade: v2Trade ?? undefined,
error, error,
v1Trade v1Trade
} }
......
import { BLOCKED_PRICE_IMPACT_NON_EXPERT } from './../constants/index' import { BLOCKED_PRICE_IMPACT_NON_EXPERT } from '../constants'
import { Fraction, JSBI, Percent, TokenAmount, Trade } from '@uniswap/sdk' import { Fraction, JSBI, Percent, TokenAmount, Trade } from '@uniswap/sdk'
import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM } from '../constants' import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM } from '../constants'
import { Field } from '../state/swap/actions' import { Field } from '../state/swap/actions'
...@@ -42,7 +42,7 @@ export function computeTradePriceBreakdown( ...@@ -42,7 +42,7 @@ export function computeTradePriceBreakdown(
// computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips // computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips
export function computeSlippageAdjustedAmounts( export function computeSlippageAdjustedAmounts(
trade: Trade, trade: Trade | undefined,
allowedSlippage: number allowedSlippage: number
): { [field in Field]?: TokenAmount } { ): { [field in Field]?: TokenAmount } {
const pct = basisPointsToPercent(allowedSlippage) const pct = basisPointsToPercent(allowedSlippage)
...@@ -52,7 +52,7 @@ export function computeSlippageAdjustedAmounts( ...@@ -52,7 +52,7 @@ export function computeSlippageAdjustedAmounts(
} }
} }
export function warningSeverity(priceImpact: Percent): 0 | 1 | 2 | 3 | 4 { export function warningSeverity(priceImpact: Percent | undefined): 0 | 1 | 2 | 3 | 4 {
if (!priceImpact?.lessThan(BLOCKED_PRICE_IMPACT_NON_EXPERT)) return 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_HIGH)) return 3
if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_MEDIUM)) return 2 if (!priceImpact?.lessThan(ALLOWED_PRICE_IMPACT_MEDIUM)) return 2
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment