From b37a6deadcb9dfe012dcf572bbd9ba465e15d94f Mon Sep 17 00:00:00 2001
From: fairlighteth <31534717+fairlighteth@users.noreply.github.com>
Date: Thu, 16 Jan 2025 12:15:45 +0000
Subject: [PATCH 1/6] feat: only show twap market price for non final states
---
.../OrdersTableContainer/OrderRow/index.tsx | 45 +++++++++++++------
1 file changed, 31 insertions(+), 14 deletions(-)
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 28c433e3af..22e94ebdd0 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
@@ -381,13 +381,32 @@ export function OrderRow({
)
}
- const renderMarketPrice = () => (
- <>
- {children ? (
- '-'
- ) : order.status === OrderStatus.CANCELLED || withWarning || order.status === OrderStatus.PRESIGNATURE_PENDING ? (
- '-'
- ) : spotPrice ? (
+ const renderMarketPrice = () => {
+ // Early return for cancelled, warning, or presignature pending states
+ if (order.status === OrderStatus.CANCELLED || withWarning || order.status === OrderStatus.PRESIGNATURE_PENDING) {
+ return '-'
+ }
+
+ // Check children finalization status
+ if (children) {
+ const childrenArray = React.Children.toArray(children) as React.ReactElement<{ order: ParsedOrder }>[]
+ if (childrenArray.every((child) => child.props?.order && getIsFinalizedOrder(child.props.order))) {
+ return '-'
+ }
+ }
+
+ // Check if child and order is finalized
+ if (isChild && getIsFinalizedOrder(order)) {
+ return '-'
+ }
+
+ // Handle spot price cases
+ if (spotPrice === null) {
+ return '-'
+ }
+
+ if (spotPrice) {
+ return (
- ) : spotPrice === null ? (
- '-'
- ) : (
-
- )}
- >
- )
+ )
+ }
+
+ return
+ }
return (
Date: Thu, 16 Jan 2025 14:30:00 +0000
Subject: [PATCH 2/6] feat: address comments children
---
.../pure/OrdersTableContainer/OrderRow/index.tsx | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
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 22e94ebdd0..2163877b6d 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
@@ -88,6 +88,7 @@ export interface OrderRowProps {
onClick: Command
orderActions: OrderActions
children?: React.ReactNode
+ childOrders?: ParsedOrder[]
isTwapTable?: boolean
}
@@ -105,6 +106,7 @@ export function OrderRow({
prices,
spotPrice,
children,
+ childOrders,
isTwapTable,
}: OrderRowProps) {
const { buyAmount, rateInfoParams, hasEnoughAllowance, hasEnoughBalance, chainId } = orderParams
@@ -292,14 +294,10 @@ export function OrderRow({
}
// For TWAP parent orders, show the next scheduled child order's fills at price
- if (children) {
- // Get the next scheduled order from the children prop
- const childrenArray = React.Children.toArray(children) as React.ReactElement<{ order: ParsedOrder }>[]
- const nextScheduledOrder = childrenArray
- .map((child) => child.props.order)
- .find((childOrder) => {
- return childOrder && childOrder.status === OrderStatus.SCHEDULED && !getIsFinalizedOrder(childOrder)
- })
+ if (children && childOrders) {
+ const nextScheduledOrder = childOrders.find(
+ (childOrder) => childOrder.status === OrderStatus.SCHEDULED && !getIsFinalizedOrder(childOrder),
+ )
if (nextScheduledOrder) {
// Get the execution price from the next scheduled order
From 64efd7878ebc71de721cc9ac6a82ffa04fe19483 Mon Sep 17 00:00:00 2001
From: fairlighteth <31534717+fairlighteth@users.noreply.github.com>
Date: Thu, 16 Jan 2025 14:39:23 +0000
Subject: [PATCH 3/6] feat: update market price logic display
---
.../pure/OrdersTableContainer/OrderRow/index.tsx | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
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 2163877b6d..a60a101aa5 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
@@ -380,8 +380,13 @@ export function OrderRow({
}
const renderMarketPrice = () => {
- // Early return for cancelled, warning, or presignature pending states
- if (order.status === OrderStatus.CANCELLED || withWarning || order.status === OrderStatus.PRESIGNATURE_PENDING) {
+ // Early return for warning states and non-active orders
+ if (
+ withWarning ||
+ order.status === OrderStatus.CREATING ||
+ order.status === OrderStatus.PRESIGNATURE_PENDING ||
+ getIsFinalizedOrder(order)
+ ) {
return '-'
}
@@ -393,11 +398,6 @@ export function OrderRow({
}
}
- // Check if child and order is finalized
- if (isChild && getIsFinalizedOrder(order)) {
- return '-'
- }
-
// Handle spot price cases
if (spotPrice === null) {
return '-'
From f449a1d5de0633881d03b2fa65e8b74039418b18 Mon Sep 17 00:00:00 2001
From: fairlighteth <31534717+fairlighteth@users.noreply.github.com>
Date: Thu, 16 Jan 2025 16:00:08 +0000
Subject: [PATCH 4/6] feat: twap child order status logic optimisations
---
.../OrdersTableContainer/OrderRow/index.tsx | 79 +++++++++++++++++--
.../pure/OrdersTableContainer/TableGroup.tsx | 1 +
2 files changed, 73 insertions(+), 7 deletions(-)
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 a60a101aa5..b5d6c2204d 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
@@ -200,19 +200,37 @@ export function OrderRow({
)
+ const areAllChildOrdersCancelled = (orders: ParsedOrder[] | undefined): boolean => {
+ if (!orders || orders.length === 0) return false
+ return orders.every((order) => order.status === OrderStatus.CANCELLED)
+ }
+
const renderFillsAt = () => (
<>
{getIsFinalizedOrder(order) ? (
- order.status === OrderStatus.CANCELLED ? (
-
-
- Order cancelled
-
- ) : order.status === OrderStatus.FULFILLED ? (
+ order.executionData.partiallyFilled || order.status === OrderStatus.FULFILLED ? (
Order {order.partiallyFillable && Number(filledPercentDisplay) < 100 ? 'partially ' : ''}filled
+ ) : order.status === OrderStatus.CANCELLED ? (
+ // For TWAP parent orders, show cancelled only when ALL child orders are cancelled
+ children ? (
+ childOrders && areAllChildOrdersCancelled(childOrders) ? (
+
+
+ Order cancelled
+
+ ) : (
+ '-'
+ )
+ ) : (
+ // For non-TWAP orders and TWAP child orders, show cancelled normally
+
+
+ Order cancelled
+
+ )
) : order.status === OrderStatus.EXPIRED ? (
@@ -288,13 +306,60 @@ export function OrderRow({
)
const renderFillsAtWithDistance = () => {
+ console.log('Debug - Order:', {
+ id: order.id,
+ status: order.status,
+ hasChildren: !!children,
+ hasChildOrders: !!childOrders,
+ childOrdersLength: childOrders?.length,
+ childOrdersStatuses: childOrders?.map((o) => o.status),
+ areAllCancelled: childOrders && areAllChildOrdersCancelled(childOrders),
+ })
+
// Special case for PRESIGNATURE_PENDING - return just the signing content
if (order.status === OrderStatus.PRESIGNATURE_PENDING) {
+ console.log('Debug - Path: PRESIGNATURE_PENDING')
return renderFillsAt()
}
- // For TWAP parent orders, show the next scheduled child order's fills at price
+ // Handle warning states first, regardless of order type
+ if (withWarning) {
+ console.log('Debug - Path: Warning state')
+ return (
+
+ orderActions.approveOrderToken(order.inputToken) : undefined}
+ />
+
+ )
+ }
+
+ // For TWAP parent orders
if (children && childOrders) {
+ console.log('Debug - Path: TWAP parent')
+ // Check if all child orders are cancelled first
+ if (areAllChildOrdersCancelled(childOrders)) {
+ console.log('Debug - All child orders are cancelled')
+ return (
+
+
+
+
+ Order cancelled
+
+
+
+
+ )
+ }
+
const nextScheduledOrder = childOrders.find(
(childOrder) => childOrder.status === OrderStatus.SCHEDULED && !getIsFinalizedOrder(childOrder),
)
diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx
index 3e1704684a..214b925d61 100644
--- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx
+++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/TableGroup.tsx
@@ -162,6 +162,7 @@ export function TableGroup(props: TableGroupProps) {
orderParams={getOrderParams(chainId, balancesAndAllowances, parent)}
onClick={() => orderActions.selectReceiptOrder(parent)}
isExpanded={!isCollapsed}
+ childOrders={children}
>
{isParentSigning ? undefined : (
Date: Thu, 16 Jan 2025 16:35:56 +0000
Subject: [PATCH 5/6] feat: order display logic
---
.../OrdersTableContainer/OrderRow/index.tsx | 73 ++++++++-----------
1 file changed, 30 insertions(+), 43 deletions(-)
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 b5d6c2204d..e78e8351d5 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,15 +3,16 @@ 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 { formatDateWithTimezone, getAddress, getEtherscanLink } from '@cowprotocol/common-utils'
+import { getAddress, getEtherscanLink, formatDateWithTimezone } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { TokenLogo } from '@cowprotocol/tokens'
import { Command, UiOrderType } from '@cowprotocol/types'
-import { HoverTooltip, Loader, PercentDisplay, percentIsAlmostHundred, TokenAmount, UI } from '@cowprotocol/ui'
+import { UI, TokenAmount, Loader, HoverTooltip } from '@cowprotocol/ui'
+import { PercentDisplay, percentIsAlmostHundred } from '@cowprotocol/ui'
import { useIsSafeWallet } from '@cowprotocol/wallet'
import { Currency, CurrencyAmount, Percent, Price } from '@uniswap/sdk-core'
-import { Check, Clock, X, Zap } from 'react-feather'
+import { Clock, Zap, Check, X } from 'react-feather'
import SVG from 'react-inlinesvg'
import { OrderStatus } from 'legacy/state/orders/actions'
@@ -20,9 +21,9 @@ import { PendingOrderPrices } from 'modules/orders/state/pendingOrdersPricesAtom
import { getIsEthFlowOrder } from 'modules/swap/containers/EthFlowStepper'
import {
- FAIR_PRICE_THRESHOLD_PERCENTAGE,
- GOOD_PRICE_THRESHOLD_PERCENTAGE,
PENDING_EXECUTION_THRESHOLD_PERCENTAGE,
+ GOOD_PRICE_THRESHOLD_PERCENTAGE,
+ FAIR_PRICE_THRESHOLD_PERCENTAGE,
} from 'common/constants/common'
import { useSafeMemo } from 'common/hooks/useSafeMemo'
import { RateInfo } from 'common/pure/RateInfo'
@@ -172,19 +173,17 @@ export function OrderRow({
return 'Unfillable'
}
- const renderWarningTooltip =
- (showIcon?: boolean) =>
- ({ children }: { children: React.ReactNode }) => (
- orderActions.approveOrderToken(order.inputToken)}
- showIcon={showIcon}
- children={children}
- />
- )
+ const renderWarningTooltip = (showIcon?: boolean) => (props: { children: React.ReactNode }) => (
+ orderActions.approveOrderToken(order.inputToken)}
+ showIcon={showIcon}
+ {...props}
+ />
+ )
const renderLimitPrice = () => (
@@ -306,25 +305,13 @@ export function OrderRow({
)
const renderFillsAtWithDistance = () => {
- console.log('Debug - Order:', {
- id: order.id,
- status: order.status,
- hasChildren: !!children,
- hasChildOrders: !!childOrders,
- childOrdersLength: childOrders?.length,
- childOrdersStatuses: childOrders?.map((o) => o.status),
- areAllCancelled: childOrders && areAllChildOrdersCancelled(childOrders),
- })
-
// Special case for PRESIGNATURE_PENDING - return just the signing content
if (order.status === OrderStatus.PRESIGNATURE_PENDING) {
- console.log('Debug - Path: PRESIGNATURE_PENDING')
return renderFillsAt()
}
// Handle warning states first, regardless of order type
if (withWarning) {
- console.log('Debug - Path: Warning state')
return (
@@ -365,13 +350,16 @@ export function OrderRow({
)
if (nextScheduledOrder) {
- // Get the execution price from the next scheduled order
- const nextOrderExecutionPrice = nextScheduledOrder.executionData.executedPrice
- const nextOrderPriceDiffs = calculatePriceDifference({
- referencePrice: spotPrice,
- targetPrice: nextOrderExecutionPrice,
- isInverted: false,
- })
+ // For scheduled orders, use the execution price if available, otherwise use the estimated price from props
+ const nextOrderExecutionPrice =
+ nextScheduledOrder.executionData.executedPrice || prices?.estimatedExecutionPrice
+ const nextOrderPriceDiffs = nextOrderExecutionPrice
+ ? calculatePriceDifference({
+ referencePrice: spotPrice,
+ targetPrice: nextOrderExecutionPrice,
+ isInverted: false,
+ })
+ : null
// Show the execution price for the next scheduled order
let nextOrderFillsAtContent
@@ -382,7 +370,7 @@ export function OrderRow({
} else {
nextOrderFillsAtContent = (
@@ -456,9 +444,8 @@ export function OrderRow({
}
// Check children finalization status
- if (children) {
- const childrenArray = React.Children.toArray(children) as React.ReactElement<{ order: ParsedOrder }>[]
- if (childrenArray.every((child) => child.props?.order && getIsFinalizedOrder(child.props.order))) {
+ if (children && childOrders) {
+ if (childOrders.every((childOrder) => getIsFinalizedOrder(childOrder))) {
return '-'
}
}
From e135932f899084f8998809696a134ab6b650361e Mon Sep 17 00:00:00 2001
From: fairlight <31534717+fairlighteth@users.noreply.github.com>
Date: Thu, 16 Jan 2025 16:50:38 +0000
Subject: [PATCH 6/6] feat: hide orders table widget (#5303)
* feat: hide orders table widget
* feat: hide orders table widget for limit and twap
---
.../trade/pure/TradePageLayout/index.tsx | 20 ++++++++++++-------
.../src/pages/AdvancedOrders/index.tsx | 9 +++++----
.../pages/LimitOrders/RegularLimitOrders.tsx | 15 +++++++++-----
3 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/apps/cowswap-frontend/src/modules/trade/pure/TradePageLayout/index.tsx b/apps/cowswap-frontend/src/modules/trade/pure/TradePageLayout/index.tsx
index 7e48603ae6..26f05e9e45 100644
--- a/apps/cowswap-frontend/src/modules/trade/pure/TradePageLayout/index.tsx
+++ b/apps/cowswap-frontend/src/modules/trade/pure/TradePageLayout/index.tsx
@@ -5,29 +5,35 @@ import { WIDGET_MAX_WIDTH } from 'theme'
const DEFAULT_MAX_WIDTH = '1500px'
-export const PageWrapper = styled.div<{ isUnlocked: boolean; secondaryOnLeft?: boolean; maxWidth?: string }>`
+export const PageWrapper = styled.div<{
+ isUnlocked: boolean
+ secondaryOnLeft?: boolean
+ maxWidth?: string
+ hideOrdersTable?: boolean
+}>`
width: 100%;
display: grid;
max-width: ${({ maxWidth = DEFAULT_MAX_WIDTH }) => maxWidth};
margin: 0 auto;
grid-template-columns: 1fr;
- grid-template-rows: auto auto;
- grid-template-areas: 'primary' 'secondary';
+ grid-template-rows: auto;
+ grid-template-areas: ${({ hideOrdersTable }) => (hideOrdersTable ? '"primary"' : '"primary" "secondary"')};
gap: 20px;
${Media.LargeAndUp()} {
- grid-template-columns: ${({ isUnlocked, secondaryOnLeft }) =>
- isUnlocked
+ grid-template-columns: ${({ isUnlocked, hideOrdersTable, secondaryOnLeft }) =>
+ isUnlocked && !hideOrdersTable
? secondaryOnLeft
? '1fr minmax(auto, ' + WIDGET_MAX_WIDTH.swap.replace('px', '') + 'px)'
: 'minmax(auto, ' + WIDGET_MAX_WIDTH.swap.replace('px', '') + 'px) 1fr'
: '1fr'};
grid-template-rows: 1fr;
- grid-template-areas: ${({ secondaryOnLeft }) => (secondaryOnLeft ? '"secondary primary"' : '"primary secondary"')};
+ grid-template-areas: ${({ secondaryOnLeft, hideOrdersTable }) =>
+ hideOrdersTable ? '"primary"' : secondaryOnLeft ? '"secondary primary"' : '"primary secondary"'};
}
> div:last-child {
- display: ${({ isUnlocked }) => (isUnlocked ? '' : 'none')};
+ display: ${({ isUnlocked }) => (!isUnlocked ? 'none' : '')};
}
`
diff --git a/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx b/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx
index 7c629bf4f4..c5b28c7a60 100644
--- a/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx
+++ b/apps/cowswap-frontend/src/pages/AdvancedOrders/index.tsx
@@ -51,6 +51,7 @@ export default function AdvancedOrdersPage() {
isUnlocked={isUnlocked}
maxWidth={ADVANCED_ORDERS_MAX_WIDTH}
secondaryOnLeft={ordersTableOnLeft}
+ hideOrdersTable={hideOrdersTable}
>
{isFallbackHandlerRequired && pendingOrders.length > 0 && }
@@ -69,15 +70,15 @@ export default function AdvancedOrdersPage() {
-
- {!hideOrdersTable && (
+ {!hideOrdersTable && (
+
- )}
-
+
+ )}
>
)
diff --git a/apps/cowswap-frontend/src/pages/LimitOrders/RegularLimitOrders.tsx b/apps/cowswap-frontend/src/pages/LimitOrders/RegularLimitOrders.tsx
index 2254eb869b..24f37d3b9a 100644
--- a/apps/cowswap-frontend/src/pages/LimitOrders/RegularLimitOrders.tsx
+++ b/apps/cowswap-frontend/src/pages/LimitOrders/RegularLimitOrders.tsx
@@ -20,20 +20,25 @@ export function RegularLimitOrders() {
const { ordersTableOnLeft } = useAtomValue(limitOrdersSettingsAtom)
return (
-
+
-
- {!hideOrdersTable && (
+ {!hideOrdersTable && (
+
- )}
-
+
+ )}
)
}