diff --git a/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts b/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts index be566a5fcc..31f0c824ed 100644 --- a/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts +++ b/apps/cowswap-frontend/src/common/hooks/useSafeMemo.ts @@ -1,6 +1,6 @@ import { EffectCallback, useEffect, useMemo } from 'react' -import { CurrencyAmount, NativeCurrency, Percent, Token } from '@uniswap/sdk-core' +import { CurrencyAmount, NativeCurrency, Percent, Price, Token } from '@uniswap/sdk-core' export function useSafeDeps(deps: unknown[]): unknown[] { return deps.map((dep) => { @@ -8,6 +8,7 @@ export function useSafeDeps(deps: unknown[]): unknown[] { if (dep instanceof Token) return dep.address.toLowerCase() if (dep instanceof CurrencyAmount) return dep.toExact() + dep.currency.symbol + dep.currency.chainId if (dep instanceof Percent) return dep.toFixed(6) + if (dep instanceof Price) return dep.toFixed(12) + dep.baseCurrency.symbol + dep.quoteCurrency.symbol return dep }) diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx index e30216a4eb..b61372ca47 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/EstimatedExecutionPrice.tsx @@ -2,14 +2,15 @@ import AlertTriangle from '@cowprotocol/assets/cow-swap/alert.svg' import allowanceIcon from '@cowprotocol/assets/images/icon-allowance.svg' import { ZERO_FRACTION } from '@cowprotocol/common-const' import { Command } from '@cowprotocol/types' -import { UI, SymbolElement, TokenAmount, TokenAmountProps, HoverTooltip, ButtonSecondary } from '@cowprotocol/ui' -import { Currency, CurrencyAmount, Fraction, Percent } from '@uniswap/sdk-core' +import { ButtonSecondary, HoverTooltip, SymbolElement, TokenAmount, TokenAmountProps, UI } from '@cowprotocol/ui' +import { Currency, CurrencyAmount, Fraction, Percent, Price } from '@uniswap/sdk-core' import { darken } from 'color2k' import SVG from 'react-inlinesvg' import styled from 'styled-components/macro' +import { Nullish } from 'types' -import { PENDING_EXECUTION_THRESHOLD_PERCENTAGE, HIGH_FEE_WARNING_PERCENTAGE } from 'common/constants/common' +import { HIGH_FEE_WARNING_PERCENTAGE, PENDING_EXECUTION_THRESHOLD_PERCENTAGE } from 'common/constants/common' import * as styledEl from './styled' @@ -28,6 +29,7 @@ export const EstimatedExecutionPriceWrapper = styled.span<{ hasWarning: boolean; } // Popover container override + > div > div, > span { display: flex; @@ -41,12 +43,10 @@ const UnfillableLabel = styled.span` position: relative; display: flex; align-items: center; - justify-content: center; font-size: inherit; font-weight: 500; line-height: 1.1; flex-flow: row wrap; - align-items: center; justify-content: flex-start; gap: 3px; @@ -94,6 +94,8 @@ export type EstimatedExecutionPriceProps = TokenAmountProps & { amountDifference?: CurrencyAmount percentageFee?: Percent amountFee?: CurrencyAmount + marketPrice?: Nullish> + executesAtPrice?: Nullish> warningText?: string WarningTooltip?: React.FC<{ children: React.ReactNode; showIcon: boolean }> onApprove?: Command @@ -109,6 +111,8 @@ export function EstimatedExecutionPrice(props: EstimatedExecutionPriceProps) { percentageDifference, amountDifference, percentageFee, + marketPrice, + executesAtPrice, amountFee, warningText, WarningTooltip, @@ -188,7 +192,11 @@ export function EstimatedExecutionPrice(props: EstimatedExecutionPriceProps) { <>The fill price of this order is close or at the market price and is expected to fill soon ) : ( <> - Market price needs to go {marketPriceNeedsToGoDown ? 'down 📉' : 'up 📈'} by  + Current market price is  + + + + and needs to go {marketPriceNeedsToGoDown ? 'down 📉' : 'up 📈'} by  @@ -196,7 +204,16 @@ export function EstimatedExecutionPrice(props: EstimatedExecutionPriceProps) { ({percentageDifferenceInverted?.toFixed(2)}%) -  to execute your order. + to execute your order at  + + + + . )} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx index e78e8351d5..5a89bf8cd9 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/OrderRow/index.tsx @@ -3,16 +3,15 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react' import orderPresignaturePending from '@cowprotocol/assets/cow-swap/order-presignature-pending.svg' import { ZERO_FRACTION } from '@cowprotocol/common-const' import { useTimeAgo } from '@cowprotocol/common-hooks' -import { getAddress, getEtherscanLink, formatDateWithTimezone } from '@cowprotocol/common-utils' +import { formatDateWithTimezone, getAddress, getEtherscanLink } from '@cowprotocol/common-utils' import { SupportedChainId } from '@cowprotocol/cow-sdk' import { TokenLogo } from '@cowprotocol/tokens' import { Command, UiOrderType } from '@cowprotocol/types' -import { UI, TokenAmount, Loader, HoverTooltip } from '@cowprotocol/ui' -import { PercentDisplay, percentIsAlmostHundred } from '@cowprotocol/ui' +import { HoverTooltip, Loader, PercentDisplay, percentIsAlmostHundred, TokenAmount, UI } from '@cowprotocol/ui' import { useIsSafeWallet } from '@cowprotocol/wallet' import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core' -import { Clock, Zap, Check, X } from 'react-feather' +import { Check, Clock, X, Zap } from 'react-feather' import SVG from 'react-inlinesvg' import { OrderStatus } from 'legacy/state/orders/actions' @@ -21,9 +20,9 @@ import { PendingOrderPrices } from 'modules/orders/state/pendingOrdersPricesAtom import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper' import { - PENDING_EXECUTION_THRESHOLD_PERCENTAGE, - GOOD_PRICE_THRESHOLD_PERCENTAGE, FAIR_PRICE_THRESHOLD_PERCENTAGE, + GOOD_PRICE_THRESHOLD_PERCENTAGE, + PENDING_EXECUTION_THRESHOLD_PERCENTAGE, } from 'common/constants/common' import { useSafeMemo } from 'common/hooks/useSafeMemo' import { RateInfo } from 'common/pure/RateInfo' @@ -158,7 +157,7 @@ export function OrderRow({ const executedPriceInverted = isInverted ? executedPrice?.invert() : executedPrice const spotPriceInverted = isInverted ? spotPrice?.invert() : spotPrice - const priceDiffs = usePricesDifference(prices, spotPrice) + const priceDiffs = usePricesDifference(prices, spotPrice, isInverted) const feeDifference = useFeeAmountDifference(rateInfoParams, prices) const isExecutedPriceZero = executedPriceInverted !== undefined && executedPriceInverted?.equalTo(ZERO_FRACTION) @@ -289,6 +288,8 @@ export function OrderRow({ percentageDifference={priceDiffs?.percentage} amountDifference={priceDiffs?.amount} percentageFee={feeDifference} + marketPrice={spotPriceInverted} + executesAtPrice={executionPriceInverted} amountFee={feeAmount} canShowWarning={getUiOrderType(order) !== UiOrderType.SWAP && !isUnfillable} isUnfillable={withWarning} @@ -623,20 +624,22 @@ export function OrderRow({ /** * Helper hook to prepare the parameters to calculate price difference */ -function usePricesDifference(prices: OrderRowProps['prices'], spotPrice: OrderRowProps['spotPrice']): PriceDifference { +function usePricesDifference( + prices: OrderRowProps['prices'], + spotPrice: OrderRowProps['spotPrice'], + isInverted: boolean, +): PriceDifference { const { estimatedExecutionPrice } = prices || {} - return useSafeMemo(() => { - if (!spotPrice || !estimatedExecutionPrice) return null - - // Calculate price difference using original (non-inverted) prices - // The percentage should stay the same regardless of display inversion - return calculatePriceDifference({ - referencePrice: spotPrice, - targetPrice: estimatedExecutionPrice, - isInverted: false, - }) - }, [estimatedExecutionPrice, spotPrice]) // Remove isInverted from dependencies since it shouldn't affect the calculation + return useSafeMemo( + () => + calculatePriceDifference({ + referencePrice: spotPrice, + targetPrice: estimatedExecutionPrice, + isInverted, + }), + [estimatedExecutionPrice, spotPrice, isInverted], + ) } /**