feat: gas costs ui updates (#7405)

* feat: gas costs ui updates

* lint

* test: update snapshots

* test: update other snapshots
This commit is contained in:
cartcrom 2023-10-04 16:08:00 -04:00 committed by GitHub
parent b6bdbcf587
commit b9db195017
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 435 additions and 240 deletions

@ -107,13 +107,13 @@ function AdvancedSwapDetails(props: SwapDetailsProps & { open: boolean }) {
<AnimatedDropdown open={open}> <AnimatedDropdown open={open}>
<SwapDetailsWrapper gap="md" data-testid="advanced-swap-details"> <SwapDetailsWrapper gap="md" data-testid="advanced-swap-details">
<Separator /> <Separator />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.NETWORK_FEE} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.PRICE_IMPACT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.PRICE_IMPACT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.INPUT_TOKEN_FEE_ON_TRANSFER} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.INPUT_TOKEN_FEE_ON_TRANSFER} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.OUTPUT_TOKEN_FEE_ON_TRANSFER} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.OUTPUT_TOKEN_FEE_ON_TRANSFER} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.MAXIMUM_INPUT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.MAXIMUM_INPUT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.MINIMUM_OUTPUT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.MINIMUM_OUTPUT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.EXPECTED_OUTPUT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.EXPECTED_OUTPUT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.NETWORK_COST} />
<Separator /> <Separator />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.ROUTING_INFO} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.ROUTING_INFO} />
</SwapDetailsWrapper> </SwapDetailsWrapper>

@ -1,15 +1,16 @@
import { Plural, t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core' import { Currency, CurrencyAmount, Percent, TradeType } from '@uniswap/sdk-core'
import { LoadingRow } from 'components/Loader/styled' import { LoadingRow } from 'components/Loader/styled'
import RouterLabel from 'components/RouterLabel' import RouterLabel from 'components/RouterLabel'
import { RowBetween } from 'components/Row' import Row, { RowBetween } from 'components/Row'
import { MouseoverTooltip, TooltipSize } from 'components/Tooltip' import { MouseoverTooltip, TooltipSize } from 'components/Tooltip'
import { getChainInfo } from 'constants/chainInfo'
import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains' import { SUPPORTED_GAS_ESTIMATE_CHAIN_IDS } from 'constants/chains'
import useHoverProps from 'hooks/useHoverProps' import useHoverProps from 'hooks/useHoverProps'
import { useIsMobile } from 'nft/hooks' import { useIsMobile } from 'nft/hooks'
import React, { PropsWithChildren, useEffect, useState } from 'react' import React, { PropsWithChildren, useEffect, useState } from 'react'
import { InterfaceTrade, TradeFillType } from 'state/routing/types' import { InterfaceTrade, TradeFillType } from 'state/routing/types'
import { getTransactionCount, isPreviewTrade, isUniswapXTrade } from 'state/routing/utils' import { isPreviewTrade, isUniswapXTrade } from 'state/routing/utils'
import styled, { DefaultTheme } from 'styled-components' import styled, { DefaultTheme } from 'styled-components'
import { ExternalLink, ThemedText } from 'theme/components' import { ExternalLink, ThemedText } from 'theme/components'
import { NumberType, useFormatter } from 'utils/formatNumbers' import { NumberType, useFormatter } from 'utils/formatNumbers'
@ -20,7 +21,7 @@ import SwapRoute from './SwapRoute'
export enum SwapLineItemType { export enum SwapLineItemType {
EXCHANGE_RATE, EXCHANGE_RATE,
NETWORK_FEE, NETWORK_COST,
INPUT_TOKEN_FEE_ON_TRANSFER, INPUT_TOKEN_FEE_ON_TRANSFER,
OUTPUT_TOKEN_FEE_ON_TRANSFER, OUTPUT_TOKEN_FEE_ON_TRANSFER,
PRICE_IMPACT, PRICE_IMPACT,
@ -108,14 +109,19 @@ function useLineItem(props: SwapLineItemProps): LineItemData | undefined {
Label: () => <Trans>Exchange rate</Trans>, Label: () => <Trans>Exchange rate</Trans>,
Value: () => <ExchangeRateRow trade={trade} />, Value: () => <ExchangeRateRow trade={trade} />,
} }
case SwapLineItemType.NETWORK_FEE: case SwapLineItemType.NETWORK_COST:
if (!SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId)) return if (!SUPPORTED_GAS_ESTIMATE_CHAIN_IDS.includes(chainId)) return
return { return {
Label: () => <Plural value={getTransactionCount(trade) || 1} one="Network fee" other="Network fees" />, Label: () => <Trans>Network cost</Trans>,
TooltipBody: () => <GasBreakdownTooltip trade={trade} hideUniswapXDescription />, TooltipBody: () => <GasBreakdownTooltip trade={trade} hideUniswapXDescription />,
Value: () => { Value: () => {
if (isPreview) return <Loading /> if (isPreview) return <Loading />
return <>{formatNumber({ input: trade.totalGasUseEstimateUSD, type: NumberType.FiatGasPrice })}</> return (
<Row gap="4px">
<img src={getChainInfo(chainId)?.logoUrl} alt="gas cost icon" width={16} height={16} />
{formatNumber({ input: trade.totalGasUseEstimateUSD, type: NumberType.FiatGasPrice })}
</Row>
)
}, },
} }
case SwapLineItemType.PRICE_IMPACT: case SwapLineItemType.PRICE_IMPACT:

@ -73,12 +73,12 @@ export default function SwapModalFooter({
<> <>
<DetailsContainer gap="md"> <DetailsContainer gap="md">
<SwapLineItem {...lineItemProps} type={SwapLineItemType.EXCHANGE_RATE} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.EXCHANGE_RATE} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.NETWORK_FEE} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.PRICE_IMPACT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.PRICE_IMPACT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.INPUT_TOKEN_FEE_ON_TRANSFER} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.INPUT_TOKEN_FEE_ON_TRANSFER} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.OUTPUT_TOKEN_FEE_ON_TRANSFER} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.OUTPUT_TOKEN_FEE_ON_TRANSFER} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.MAXIMUM_INPUT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.MAXIMUM_INPUT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.MINIMUM_OUTPUT} /> <SwapLineItem {...lineItemProps} type={SwapLineItemType.MINIMUM_OUTPUT} />
<SwapLineItem {...lineItemProps} type={SwapLineItemType.NETWORK_COST} />
</DetailsContainer> </DetailsContainer>
{showAcceptChanges ? ( {showAcceptChanges ? (
<SwapShowAcceptChanges data-testid="show-accept-changes"> <SwapShowAcceptChanges data-testid="show-accept-changes">

@ -297,27 +297,6 @@ exports[`SwapDetailsDropdown.tsx renders a trade 1`] = `
<div <div
class="c18" class="c18"
/> />
<div
class="c2 c3 c4"
>
<div
class="c9 c19 css-142zc9n"
data-testid="swap-li-label"
>
Network fee
</div>
<div
class="c12"
>
<div>
<div
class="c9 c20 css-142zc9n"
>
$1.00
</div>
</div>
</div>
</div>
<div <div
class="c2 c3 c4" class="c2 c3 c4"
> >
@ -385,6 +364,37 @@ exports[`SwapDetailsDropdown.tsx renders a trade 1`] = `
</div> </div>
</div> </div>
</div> </div>
<div
class="c2 c3 c4"
>
<div
class="c9 c19 css-142zc9n"
data-testid="swap-li-label"
>
Network cost
</div>
<div
class="c12"
>
<div>
<div
class="c9 c20 css-142zc9n"
>
<div
class="c2 c10"
>
<img
alt="gas cost icon"
height="16"
src="ethereum-logo.png"
width="16"
/>
$1.00
</div>
</div>
</div>
</div>
</div>
<div <div
class="c18" class="c18"
/> />

File diff suppressed because it is too large Load Diff

@ -25,6 +25,24 @@ exports[`SwapModalFooter.tsx matches base snapshot, test trade exact input 1`] =
justify-content: flex-start; justify-content: flex-start;
} }
.c10 {
width: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
padding: 0;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-webkit-justify-content: flex-start;
-ms-flex-pack: start;
justify-content: flex-start;
gap: 4px;
}
.c4 { .c4 {
-webkit-box-pack: justify; -webkit-box-pack: justify;
-webkit-justify-content: space-between; -webkit-justify-content: space-between;
@ -93,27 +111,6 @@ exports[`SwapModalFooter.tsx matches base snapshot, test trade exact input 1`] =
1 DEF = 1.00 ABC 1 DEF = 1.00 ABC
</div> </div>
</div> </div>
<div
class="c2 c3 c4"
>
<div
class="c5 c8 css-142zc9n"
data-testid="swap-li-label"
>
Network fee
</div>
<div
class="c9"
>
<div>
<div
class="c5 c7 css-142zc9n"
>
$1.00
</div>
</div>
</div>
</div>
<div <div
class="c2 c3 c4" class="c2 c3 c4"
> >
@ -160,6 +157,37 @@ exports[`SwapModalFooter.tsx matches base snapshot, test trade exact input 1`] =
</div> </div>
</div> </div>
</div> </div>
<div
class="c2 c3 c4"
>
<div
class="c5 c8 css-142zc9n"
data-testid="swap-li-label"
>
Network cost
</div>
<div
class="c9"
>
<div>
<div
class="c5 c7 css-142zc9n"
>
<div
class="c2 c10"
>
<img
alt="gas cost icon"
height="16"
src="ethereum-logo.png"
width="16"
/>
$1.00
</div>
</div>
</div>
</div>
</div>
</div> </div>
.c0 { .c0 {
box-sizing: border-box; box-sizing: border-box;
@ -442,32 +470,6 @@ exports[`SwapModalFooter.tsx renders a preview trade while disabling submission
1 DEF = 1.00 ABC 1 DEF = 1.00 ABC
</div> </div>
</div> </div>
<div
class="c2 c3 c4"
>
<div
class="c5 c8 css-142zc9n"
data-testid="swap-li-label"
>
Network fee
</div>
<div
class="c9"
>
<div>
<div
class="c5 c7 css-142zc9n"
>
<div
class="c10"
data-testid="loading-row"
height="15"
width="50"
/>
</div>
</div>
</div>
</div>
<div <div
class="c2 c3 c4" class="c2 c3 c4"
> >
@ -515,6 +517,32 @@ exports[`SwapModalFooter.tsx renders a preview trade while disabling submission
</div> </div>
</div> </div>
</div> </div>
<div
class="c2 c3 c4"
>
<div
class="c5 c8 css-142zc9n"
data-testid="swap-li-label"
>
Network cost
</div>
<div
class="c9"
>
<div>
<div
class="c5 c7 css-142zc9n"
>
<div
class="c10"
data-testid="loading-row"
height="15"
width="50"
/>
</div>
</div>
</div>
</div>
</div> </div>
.c0 { .c0 {
box-sizing: border-box; box-sizing: border-box;

@ -343,20 +343,3 @@ export function isUniswapXTrade(trade?: InterfaceTrade): trade is DutchOrderTrad
export function shouldUseAPIRouter(args: GetQuoteArgs): boolean { export function shouldUseAPIRouter(args: GetQuoteArgs): boolean {
return args.routerPreference !== RouterPreference.CLIENT return args.routerPreference !== RouterPreference.CLIENT
} }
export function getTransactionCount(trade: InterfaceTrade): number {
if (!isSubmittableTrade(trade)) return 0
let count = 0
if (trade.approveInfo.needsApprove) {
count++ // approval step, which can happen in both classic and uniswapx
}
if (isUniswapXTrade(trade)) {
if (trade.wrapInfo.needsWrap) {
count++ // wrapping step for uniswapx
}
} else {
count++ // classic onchain swap
}
return count
}