Compare commits

...

7 Commits

Author SHA1 Message Date
Moody Salem
ae27e245b4 replace the message when we fail to parse an error 2021-05-14 14:13:13 -05:00
Moody Salem
897f354202 chore: bump mathieudutour/github-tag-action to latest release version to fix generated changelogs
https://github.com/Uniswap/uniswap-interface/issues/1572
2021-05-14 10:56:57 -05:00
Moody Salem
4745052f0e fix: break words in swap error messages (fixes https://github.com/Uniswap/uniswap-interface/issues/1462) 2021-05-14 10:50:55 -05:00
Moody Salem
5bc5d6504e improve the text slightly 2021-05-14 08:45:17 -05:00
Moody Salem
7a0b85bf41 improvement: estimated amounts instead of minimum/maximums (#1570)
* estimated amounts instead of minimum/maximums

* missed a spot

* fix linting error
2021-05-14 07:15:53 -05:00
OMGspidertanx
534afb3278 fix: tweak element sizing/wraping in approve button (#1569) 2021-05-14 07:15:41 -05:00
Moody Salem
7d71af353e perf: debounce localStorage save 2021-05-14 07:10:25 -05:00
13 changed files with 76 additions and 73 deletions

View File

@@ -19,7 +19,7 @@ jobs:
- name: Bump version and push tag
id: github_tag_action
uses: mathieudutour/github-tag-action@v4.5
uses: mathieudutour/github-tag-action@331898d5052eedac9b15fec867b5ba66ebf9b692
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
release_branches: .*

View File

@@ -51,7 +51,7 @@
"@uniswap/v2-sdk": "^3.0.0-alpha.0",
"@uniswap/v3-core": "1.0.0",
"@uniswap/v3-periphery": "1.0.0",
"@uniswap/v3-sdk": "^3.0.0-alpha.2",
"@uniswap/v3-sdk": "^3.0.0-alpha.4",
"@web3-react/core": "^6.0.9",
"@web3-react/fortmatic-connector": "^6.0.9",
"@web3-react/injected-connector": "^6.0.7",

View File

@@ -184,7 +184,12 @@ export function TransactionErrorContent({ message, onDismiss }: { message: strin
</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%' }}>
<Text
fontWeight={500}
fontSize={16}
color={theme.red1}
style={{ textAlign: 'center', width: '85%', wordBreak: 'break-word' }}
>
{message}
</Text>
</AutoColumn>

View File

@@ -1,11 +1,10 @@
import { Percent, Currency, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useContext } from 'react'
import React, { useContext, useMemo } from 'react'
import { ThemeContext } from 'styled-components'
import { TYPE } from '../../theme'
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
import { computeRealizedLPFeeAmount } from '../../utils/prices'
import { computeRealizedLPFeePercent } from '../../utils/prices'
import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row'
import FormattedPriceImpact from './FormattedPriceImpact'
@@ -19,7 +18,14 @@ export interface AdvancedSwapDetailsProps {
export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDetailsProps) {
const theme = useContext(ThemeContext)
const realizedLPFee = computeRealizedLPFeeAmount(trade)
const { realizedLPFee, priceImpact } = useMemo(() => {
if (!trade) return { realizedLPFee: undefined, priceImpact: undefined }
const realizedLpFeePercent = computeRealizedLPFeePercent(trade)
const realizedLPFee = trade.inputAmount.multiply(realizedLpFeePercent)
const priceImpact = trade.priceImpact.subtract(realizedLpFeePercent)
return { priceImpact, realizedLPFee }
}, [trade])
return !trade ? null : (
<AutoColumn gap="8px">
@@ -30,7 +36,7 @@ export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDeta
</TYPE.black>
</RowFixed>
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${trade.inputAmount.currency.symbol}` : '-'}
{realizedLPFee ? `${realizedLPFee.toSignificant(4)} ${realizedLPFee.currency.symbol}` : '-'}
</TYPE.black>
</RowBetween>
@@ -48,11 +54,24 @@ export function AdvancedSwapDetails({ trade, allowedSlippage }: AdvancedSwapDeta
<RowBetween>
<RowFixed>
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
Execution price vs. spot price
Price Impact
</TYPE.black>
</RowFixed>
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
<FormattedPriceImpact priceImpact={computePriceImpactWithMaximumSlippage(trade, allowedSlippage)} />
<FormattedPriceImpact priceImpact={priceImpact} />
</TYPE.black>
</RowBetween>
<RowBetween>
<RowFixed>
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
{trade.tradeType === TradeType.EXACT_INPUT ? 'Minimum received' : 'Maximum sent'}
</TYPE.black>
</RowFixed>
<TYPE.black textAlign="right" fontSize={12} color={theme.text1}>
{trade.tradeType === TradeType.EXACT_INPUT
? `${trade.minimumAmountOut(allowedSlippage).toSignificant(6)} ${trade.outputAmount.currency.symbol}`
: `${trade.maximumAmountIn(allowedSlippage).toSignificant(6)} ${trade.inputAmount.currency.symbol}`}
</TYPE.black>
</RowBetween>

View File

@@ -90,9 +90,9 @@ export default function ConfirmSwapModal({
}, [onConfirm, showAcceptChanges, swapErrorMessage, trade])
// text to show while loading
const pendingText = `Swapping ${trade?.maximumAmountIn(allowedSlippage)?.toSignificant(6)} ${
const pendingText = `Swapping ${trade?.inputAmount?.toSignificant(6)} ${
trade?.inputAmount?.currency?.symbol
} for ${trade?.minimumAmountOut(allowedSlippage)?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
} for ${trade?.outputAmount?.toSignificant(6)} ${trade?.outputAmount?.currency?.symbol}`
const confirmationContent = useCallback(
() =>

View File

@@ -31,12 +31,10 @@ export const ArrowWrapper = styled.div`
margin-top: -18px;
margin-bottom: -18px;
left: calc(50% - 16px);
/* transform: rotate(90deg); */
display: flex;
justify-content: center;
align-items: center;
background-color: ${({ theme }) => theme.bg1};
/* border: 4px solid ${({ theme }) => theme.bg0}; */
z-index: 2;
`
@@ -53,15 +51,12 @@ export default function SwapModalHeader({
showAcceptChanges: boolean
onAcceptChanges: () => void
}) {
const maximumAmountIn = trade.maximumAmountIn(allowedSlippage)
const minimumAmountOut = trade.minimumAmountOut(allowedSlippage)
const theme = useContext(ThemeContext)
const [showInverted, setShowInverted] = useState<boolean>(false)
const fiatValueInput = useUSDCValue(maximumAmountIn)
const fiatValueOutput = useUSDCValue(minimumAmountOut)
const fiatValueInput = useUSDCValue(trade.inputAmount)
const fiatValueOutput = useUSDCValue(trade.outputAmount)
return (
<AutoColumn gap={'4px'} style={{ marginTop: '1rem' }}>
@@ -86,7 +81,7 @@ export default function SwapModalHeader({
fontWeight={500}
color={showAcceptChanges && trade.tradeType === TradeType.EXACT_OUTPUT ? theme.primary1 : ''}
>
{maximumAmountIn.toSignificant(6)}
{trade.inputAmount.toSignificant(6)}
</TruncatedText>
</RowFixed>
</RowBetween>
@@ -117,7 +112,7 @@ export default function SwapModalHeader({
</RowFixed>
<RowFixed gap={'0px'}>
<TruncatedText fontSize={24} fontWeight={500}>
{minimumAmountOut.toSignificant(6)}
{trade.outputAmount.toSignificant(6)}
</TruncatedText>
</RowFixed>
</RowBetween>
@@ -127,11 +122,7 @@ export default function SwapModalHeader({
<TYPE.body color={theme.text2} fontWeight={500} fontSize={14}>
{'Price:'}
</TYPE.body>
<TradePrice
price={trade.worstExecutionPrice(allowedSlippage)}
showInverted={showInverted}
setShowInverted={setShowInverted}
/>
<TradePrice price={trade.executionPrice} showInverted={showInverted} setShowInverted={setShowInverted} />
</RowBetween>
<LightCard style={{ padding: '.75rem', marginTop: '0.5rem' }}>
@@ -155,12 +146,12 @@ export default function SwapModalHeader({
</SwapShowAcceptChanges>
) : null}
{/* <AutoColumn justify="flex-start" gap="sm" style={{ padding: '.75rem 1rem' }}>
<AutoColumn justify="flex-start" gap="sm" style={{ padding: '.75rem 1rem' }}>
{trade.tradeType === TradeType.EXACT_INPUT ? (
<TYPE.italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
{`Output is estimated. You will receive at least `}
<b>
{minimumAmountOut.toSignificant(6)} {trade.outputAmount.currency.symbol}
{trade.minimumAmountOut(allowedSlippage).toSignificant(6)} {trade.outputAmount.currency.symbol}
</b>
{' or the transaction will revert.'}
</TYPE.italic>
@@ -168,12 +159,12 @@ export default function SwapModalHeader({
<TYPE.italic fontWeight={400} textAlign="left" style={{ width: '100%' }}>
{`Input is estimated. You will sell at most `}
<b>
{maximumAmountIn.toSignificant(6)} {trade.inputAmount.currency.symbol}
{trade.maximumAmountIn(allowedSlippage).toSignificant(6)} {trade.inputAmount.currency.symbol}
</b>
{' or the transaction will revert.'}
</TYPE.italic>
)}
</AutoColumn> */}
</AutoColumn>
{recipient !== null ? (
<AutoColumn justify="flex-start" gap="sm" style={{ padding: '12px 0 0 0px' }}>
<TYPE.main>

View File

@@ -171,7 +171,7 @@ export function SwapCallbackError({ error }: { error: string }) {
<SwapCallbackErrorInnerAlertTriangle>
<AlertTriangle size={24} />
</SwapCallbackErrorInnerAlertTriangle>
<p>{error}</p>
<p style={{ wordBreak: 'break-word' }}>{error}</p>
</SwapCallbackErrorInner>
)
}

View File

@@ -166,7 +166,13 @@ export function swapErrorToUserReadableMessage(error: any): string {
case 'TF':
return 'The output token cannot be transferred. There may be an issue with the output token. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.'
default:
return `Unknown error${reason ? `: "${reason}"` : ''}. Please join the Discord to get help.`
if (reason?.indexOf('undefined is not an object') !== -1) {
console.error(error, reason)
return 'An error occurred when trying to execute this swap. You may need to increase your slippage tolerance. If that does not work, there may be an incompatibility with the token you are trading. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.'
}
return `Unknown error${
reason ? `: "${reason}"` : ''
}. Try increasing your slippage tolerance. Note fee on transfer and rebase tokens are incompatible with Uniswap V3.`
}
}
@@ -275,8 +281,8 @@ export function useSwapCallback(
.then((response) => {
const inputSymbol = trade.inputAmount.currency.symbol
const outputSymbol = trade.outputAmount.currency.symbol
const inputAmount = trade.maximumAmountIn(allowedSlippage).toSignificant(4)
const outputAmount = trade.minimumAmountOut(allowedSlippage).toSignificant(4)
const inputAmount = trade.inputAmount.toSignificant(4)
const outputAmount = trade.outputAmount.toSignificant(4)
const base = `Swap ${inputAmount} ${inputSymbol} for ${outputAmount} ${outputSymbol}`
const withRecipient =
@@ -312,5 +318,5 @@ export function useSwapCallback(
},
error: null,
}
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, allowedSlippage, addTransaction])
}, [trade, library, account, chainId, recipient, recipientAddressOrName, swapCalls, addTransaction])
}

View File

@@ -49,7 +49,6 @@ import {
import { useExpertModeManager, useUserSingleHopOnly } from '../../state/user/hooks'
import { HideSmall, LinkStyledButton, TYPE } from '../../theme'
import { computeFiatValuePriceImpact } from '../../utils/computeFiatValuePriceImpact'
import { computePriceImpactWithMaximumSlippage } from '../../utils/computePriceImpactWithMaximumSlippage'
import { getTradeVersion } from '../../utils/getTradeVersion'
import { isTradeBetter } from '../../utils/isTradeBetter'
import { maxAmountSpend } from '../../utils/maxAmountSpend'
@@ -132,10 +131,10 @@ export default function Swap({ history }: RouteComponentProps) {
[Field.OUTPUT]: parsedAmount,
}
: {
[Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.maximumAmountIn(allowedSlippage),
[Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.minimumAmountOut(allowedSlippage),
[Field.INPUT]: independentField === Field.INPUT ? parsedAmount : trade?.inputAmount,
[Field.OUTPUT]: independentField === Field.OUTPUT ? parsedAmount : trade?.outputAmount,
},
[allowedSlippage, independentField, parsedAmount, showWrap, trade]
[independentField, parsedAmount, showWrap, trade]
)
const fiatValueInput = useUSDCValue(parsedAmounts[Field.INPUT])
@@ -292,7 +291,7 @@ export default function Swap({ history }: RouteComponentProps) {
// warnings on the greater of fiat value price impact and execution price impact
const priceImpactSeverity = useMemo(() => {
const executionPriceImpact = trade ? computePriceImpactWithMaximumSlippage(trade, allowedSlippage) : undefined
const executionPriceImpact = trade?.priceImpact
return warningSeverity(
executionPriceImpact && priceImpact
? executionPriceImpact.greaterThan(priceImpact)
@@ -300,7 +299,7 @@ export default function Swap({ history }: RouteComponentProps) {
: priceImpact
: executionPriceImpact ?? priceImpact
)
}, [allowedSlippage, priceImpact, trade])
}, [priceImpact, trade])
// show approve flow when: no error on inputs, not approved or pending, or approved in current session
// never show if price impact is above threshold in non expert mode
@@ -475,7 +474,7 @@ export default function Swap({ history }: RouteComponentProps) {
{trade ? (
<RowFixed>
<TradePrice
price={trade.worstExecutionPrice(allowedSlippage)}
price={trade.executionPrice}
showInverted={showInverted}
setShowInverted={setShowInverted}
/>
@@ -526,12 +525,12 @@ export default function Swap({ history }: RouteComponentProps) {
approvalState === ApprovalState.APPROVED || signatureState === UseERC20PermitState.SIGNED
}
>
<AutoRow justify="space-between">
<AutoRow justify="space-between" style={{ flexWrap: 'nowrap' }}>
<span style={{ display: 'flex', alignItems: 'center' }}>
<CurrencyLogo
currency={currencies[Field.INPUT]}
size={'20px'}
style={{ marginRight: '8px' }}
style={{ marginRight: '8px', flexShrink: 0 }}
/>
{/* we need to shorten this string on mobile */}
{approvalState === ApprovalState.APPROVED || signatureState === UseERC20PermitState.SIGNED
@@ -551,7 +550,7 @@ export default function Swap({ history }: RouteComponentProps) {
'. You only have to do this once per token.'
}
>
<HelpCircle size="20" color={'white'} />
<HelpCircle size="20" color={'white'} style={{ marginLeft: '8px' }} />
</MouseoverTooltip>
)}
</AutoRow>

View File

@@ -28,7 +28,7 @@ const store = configureStore({
multicall,
lists,
},
middleware: [...getDefaultMiddleware({ thunk: false }), save({ states: PERSISTED_KEYS })],
middleware: [...getDefaultMiddleware({ thunk: false }), save({ states: PERSISTED_KEYS, debounce: 1000 })],
preloadedState: load({ states: PERSISTED_KEYS }),
})

View File

@@ -1,14 +0,0 @@
import { computePriceImpact, Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
export function computePriceImpactWithMaximumSlippage(
trade: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType>,
allowedSlippage: Percent
): Percent {
return computePriceImpact(
trade.route.midPrice,
trade.maximumAmountIn(allowedSlippage),
trade.minimumAmountOut(allowedSlippage)
)
}

View File

@@ -22,15 +22,15 @@ export function computeRealizedLPFeePercent(
// 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))
percent = ONE_HUNDRED_PERCENT.subtract(
trade.route.pairs.reduce<Fraction>(
(currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
trade.route.pairs.reduce<Percent>(
(currentFee: Percent): Percent => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
ONE_HUNDRED_PERCENT
)
)
} else {
percent = ONE_HUNDRED_PERCENT.subtract(
trade.route.pools.reduce<Fraction>(
(currentFee: Fraction, pool): Fraction =>
trade.route.pools.reduce<Percent>(
(currentFee: Percent, pool): Percent =>
currentFee.multiply(ONE_HUNDRED_PERCENT.subtract(new Fraction(pool.fee, 1_000_000))),
ONE_HUNDRED_PERCENT
)
@@ -44,14 +44,11 @@ export function computeRealizedLPFeePercent(
export function computeRealizedLPFeeAmount(
trade?: V2Trade<Currency, Currency, TradeType> | V3Trade<Currency, Currency, TradeType> | null
): CurrencyAmount<Currency> | undefined {
if (trade instanceof V2Trade || trade instanceof V3Trade) {
if (trade) {
const realizedLPFee = computeRealizedLPFeePercent(trade)
// the amount of the input that accrues to LPs
return CurrencyAmount.fromRawAmount(
trade.inputAmount.currency,
trade.inputAmount.asFraction.multiply(realizedLPFee).quotient
)
return CurrencyAmount.fromRawAmount(trade.inputAmount.currency, trade.inputAmount.multiply(realizedLPFee).quotient)
}
return undefined

View File

@@ -4478,10 +4478,10 @@
"@uniswap/v3-core" "1.0.0"
base64-sol "1.0.1"
"@uniswap/v3-sdk@^3.0.0-alpha.2":
version "3.0.0-alpha.2"
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.0.0-alpha.2.tgz#c72c2a81da515839f48e8aba6dff2a7163c94da1"
integrity sha512-L5coA6F2/Xq25wLjEddXzj3uXCV0v5TOm7Fsw+Z8PubWmi2sXaJFqUfsoOXSfICD5NjJUb3u3bpe4+ZHRaUrnw==
"@uniswap/v3-sdk@^3.0.0-alpha.4":
version "3.0.0-alpha.4"
resolved "https://registry.yarnpkg.com/@uniswap/v3-sdk/-/v3-sdk-3.0.0-alpha.4.tgz#e8bf26291fd74e36a5a3d9b88f1809a7aceb7d3a"
integrity sha512-BcEH8eHt+b6eaaiLDlzbFox2NquP1H7KgrgmNjAlU/et+vC4azdfNN6SsRlTFzhioPOwHlAKAAZJLq+yzboDOQ==
dependencies:
"@ethersproject/abi" "^5.0.12"
"@ethersproject/solidity" "^5.0.9"