diff --git a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts index 4630be0d51..89bd865995 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/actions.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/actions.ts @@ -107,7 +107,9 @@ export type OrderInfoApi = Pick< | 'executedSellAmount' | 'executedSellAmountBeforeFees' | 'executedFeeAmount' - | 'executedSurplusFee' + | 'executedFee' + | 'executedFeeToken' + | 'totalFee' | 'invalidated' | 'ethflowData' | 'onchainOrderData' @@ -139,6 +141,7 @@ export interface AddPendingOrderParams { order: SerializedOrder isSafeWallet: boolean } + export type ChangeOrderStatusParams = { id: UID; chainId: ChainId } export type SetOrderCancellationHashParams = ChangeOrderStatusParams & { hash: string } @@ -177,11 +180,13 @@ export interface BatchOrdersUpdateParams { } export type PresignedOrdersParams = BatchOrdersUpdateParams + export interface UpdatePresignGnosisSafeTxParams { orderId: UID chainId: ChainId safeTransaction: SafeMultisigTransactionResponse } + export type ExpireOrdersBatchParams = BatchOrdersUpdateParams export type InvalidateOrdersBatchParams = BatchOrdersUpdateParams export type CancelOrdersBatchParams = BatchOrdersUpdateParams @@ -196,7 +201,7 @@ export const fulfillOrdersBatch = createAction('order/ export const preSignOrders = createAction('order/presignOrders') export const updatePresignGnosisSafeTx = createAction( - 'order/updatePresignGnosisSafeTx' + 'order/updatePresignGnosisSafeTx', ) export const expireOrdersBatch = createAction('order/expireOrdersBatch') @@ -214,7 +219,7 @@ export const deleteOrders = createAction('order/deleteOrders export const clearOrders = createAction<{ chainId: ChainId }>('order/clearOrders') export const updateLastCheckedBlock = createAction<{ chainId: ChainId; lastCheckedBlock: number }>( - 'order/updateLastCheckedBlock' + 'order/updateLastCheckedBlock', ) export const clearOrdersStorage = createAction('order/clearOrdersStorage') diff --git a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts index 4e32f45fd1..f3068c7554 100644 --- a/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts +++ b/apps/cowswap-frontend/src/legacy/state/orders/reducer.ts @@ -121,7 +121,7 @@ export function getDefaultNetworkState(chainId: ChainId): OrdersStateNetwork { // makes sure there's always an object at state[chainId], state[chainId].pending | .fulfilled function prefillState( state: Writable, - { payload: { chainId } }: PayloadAction + { payload: { chainId } }: PayloadAction, ): asserts state is Required { const stateAtChainId = state[chainId] @@ -174,7 +174,7 @@ function addOrderToState( id: string, status: OrderTypeKeys, order: SerializedOrder, - isSafeWallet: boolean + isSafeWallet: boolean, ): void { // Attempt to fix `TypeError: Cannot add property , object is not extensible` // seen on https://user-images.githubusercontent.com/34510341/138450105-bb94a2d1-656e-4e15-ae99-df9fb33c8ca4.png @@ -200,7 +200,7 @@ function cancelOrderInState( state: Required, chainId: ChainId, orderObject: OrderObject, - isSafeWallet: boolean + isSafeWallet: boolean, ) { const id = orderObject.id @@ -368,12 +368,13 @@ export default createReducer(initialState, (builder) => orderObject.order.apiAdditionalInfo = { creationDate: order.creationDate, - availableBalance: order.availableBalance, executedBuyAmount: order.executedBuyAmount, executedSellAmount: order.executedSellAmount, executedSellAmountBeforeFees: order.executedSellAmountBeforeFees, executedFeeAmount: order.executedFeeAmount, - executedSurplusFee: order.executedSurplusFee, + executedFee: order.executedFee, + executedFeeToken: order.executedFeeToken, + totalFee: order.totalFee, invalidated: order.invalidated, ethflowData: order.ethflowData, onchainOrderData: order.onchainOrderData, @@ -458,7 +459,7 @@ export default createReducer(initialState, (builder) => const allOrdersMap = flatOrdersStateNetwork(state[chainId]) const children = Object.values(allOrdersMap).filter( - (item) => item?.order.composableCowInfo?.parentId === id + (item) => item?.order.composableCowInfo?.parentId === id, ) children.forEach((child) => { @@ -544,12 +545,12 @@ export default createReducer(initialState, (builder) => orderListByChain[status] = ordersCleaned }) }) - }) + }), ) function reClassifyOrder( newOrder: SerializedOrder, - existingOrder: OrderObject | undefined + existingOrder: OrderObject | undefined, ): { status: OrderStatus; isCancelling: boolean | undefined } { // Onchain cancellations are considered final // Still, the order classification at apps/cowswap-frontend/src/legacy/state/orders/utils.ts can't tell diff --git a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx index b4fbd70538..11ffafbdaf 100644 --- a/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx +++ b/apps/cowswap-frontend/src/modules/application/containers/App/index.tsx @@ -1,8 +1,7 @@ import { lazy, PropsWithChildren, Suspense, useMemo } from 'react' import { ACTIVE_CUSTOM_THEME, CustomTheme } from '@cowprotocol/common-const' -import { useMediaQuery } from '@cowprotocol/common-hooks' -import { useFeatureFlags } from '@cowprotocol/common-hooks' +import { useFeatureFlags, useMediaQuery } from '@cowprotocol/common-hooks' import { isInjectedWidget } from '@cowprotocol/common-utils' import { Color, Footer, GlobalCoWDAOStyles, Media, MenuBar } from '@cowprotocol/ui' @@ -55,7 +54,10 @@ export function App() { useAnalyticsReporterCowSwap() useInitializeUtm() - const { isYieldEnabled, isChristmasEnabled, isHalloweenEnabled } = useFeatureFlags() + const { isYieldEnabled, } = useFeatureFlags() + // TODO: load them from feature flags when we want to enable again + const isChristmasEnabled = false + const isHalloweenEnabled = false const isInjectedWidgetMode = isInjectedWidget() const menuItems = useMenuItems() diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts index 46c3abdb6d..b6d8259577 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/orders.mock.ts @@ -100,6 +100,19 @@ export const ordersMock: ParsedOrder[] = [ signingScheme: SigningScheme.EIP712, class: OrderClass.MARKET, kind: OrderKind.SELL, + apiAdditionalInfo: { + executedFeeAmount: '1', + executedFee: '1', + executedFeeToken: USDC[chainId].address, + totalFee: '1', + creationDate: '2022-11-11T13:15:13.551Z', + executedBuyAmount: '23000000000000', + executedSellAmount: '5000300000000000', + executedSellAmountBeforeFees: '5000300000000000', + invalidated: false, + class: OrderClass.LIMIT, + signingScheme: SigningScheme.EIP712, + }, }, { id: '5', diff --git a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx index eed9c96389..4d348db3ff 100644 --- a/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx +++ b/apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/FeeField.tsx @@ -1,6 +1,8 @@ import { TokenAmount } from '@cowprotocol/ui' import { CurrencyAmount } from '@uniswap/sdk-core' +import { getFeeToken } from 'modules/ordersTable/utils/getFeeToken' + import { ParsedOrder } from 'utils/orderUtils/parseOrder' import * as styledEl from './styled' @@ -8,14 +10,13 @@ import * as styledEl from './styled' export type Props = { order: ParsedOrder } export function FeeField({ order }: Props): JSX.Element | null { - const { inputToken } = order - const { executedFeeAmount, executedSurplusFee } = order.executionData + const { totalFee } = order.executionData + const feeToken = getFeeToken(order) - if (!inputToken) return + if (!feeToken) return - // TODO: use the value from SDK - const totalFee = CurrencyAmount.fromRawAmount(inputToken, (executedSurplusFee ?? executedFeeAmount) || 0) - const quoteSymbol = inputToken.symbol + const totalFeeAmount = CurrencyAmount.fromRawAmount(feeToken, totalFee || 0) + const quoteSymbol = feeToken.symbol return ( @@ -23,7 +24,7 @@ export function FeeField({ order }: Props): JSX.Element | null { - ) : ( - + )} diff --git a/apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.test.ts b/apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.test.ts new file mode 100644 index 0000000000..0eba3524c7 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.test.ts @@ -0,0 +1,37 @@ +import { getFeeToken } from './getFeeToken' // Adjust the import path as necessary + +import { ordersMock } from '../pure/OrdersTableContainer/orders.mock' + +const BASE_ORDER = ordersMock[3] + +describe('getFeeToken', () => { + it("should return inputToken when that's the fee token", () => { + const input = BASE_ORDER + const expectedOutput = BASE_ORDER.inputToken + + const result = getFeeToken(input) + + expect(result).toEqual(expectedOutput) + }) + + it("should return outputToken when that's the fee token", () => { + const input = { + ...BASE_ORDER, + executionData: { ...BASE_ORDER.executionData, executedFeeToken: BASE_ORDER.outputToken.address }, + } + const expectedOutput = BASE_ORDER.outputToken + + const result = getFeeToken(input) + + expect(result).toEqual(expectedOutput) + }) + + it('should return inputToken when there is no fee token', () => { + const input = { ...BASE_ORDER, executionData: { ...BASE_ORDER.executionData, executedFeeToken: null } } + const expectedOutput = BASE_ORDER.inputToken + + const result = getFeeToken(input) + + expect(result).toEqual(expectedOutput) + }) +}) diff --git a/apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.ts b/apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.ts new file mode 100644 index 0000000000..a41a094bd4 --- /dev/null +++ b/apps/cowswap-frontend/src/modules/ordersTable/utils/getFeeToken.ts @@ -0,0 +1,14 @@ +import { ParsedOrder } from 'utils/orderUtils/parseOrder' + +export function getFeeToken(order: ParsedOrder) { + const { inputToken, outputToken } = order + const { executedFeeToken } = order.executionData + + const feeTokenAddress = executedFeeToken?.toLowerCase() + + if (!feeTokenAddress) { + return inputToken + } + + return [inputToken, outputToken].find((token) => token?.address.toLowerCase() === feeTokenAddress) +} diff --git a/apps/cowswap-frontend/src/modules/sounds/utils/sound.ts b/apps/cowswap-frontend/src/modules/sounds/utils/sound.ts index ca127702dc..f4557a299f 100644 --- a/apps/cowswap-frontend/src/modules/sounds/utils/sound.ts +++ b/apps/cowswap-frontend/src/modules/sounds/utils/sound.ts @@ -7,8 +7,6 @@ import { cowSwapStore } from 'legacy/state' import { injectedWidgetParamsAtom } from 'modules/injectedWidget/state/injectedWidgetParamsAtom' -import { featureFlagsAtom } from 'common/state/featureFlagsState' - type SoundType = 'SEND' | 'SUCCESS' | 'ERROR' type Sounds = Record type WidgetSounds = keyof NonNullable @@ -47,7 +45,12 @@ function isDarkMode(): boolean { } function getThemeBasedSound(type: SoundType): string { - const featureFlags = jotaiStore.get(featureFlagsAtom) as Record + // TODO: load featureFlags when enabling again + // const featureFlags = jotaiStore.get(featureFlagsAtom) as Record + // const { isChristmasEnabled, isHalloweenEnabled } = featureFlags + const isChristmasEnabled = false + const isHalloweenEnabled = false + const defaultSound = DEFAULT_COW_SOUNDS[type] const themedOptions = THEMED_SOUNDS[type] @@ -62,13 +65,13 @@ function getThemeBasedSound(type: SoundType): string { return defaultSound } - if (ACTIVE_CUSTOM_THEME === CustomTheme.CHRISTMAS && featureFlags.isChristmasEnabled && themedOptions.winterSound) { + if (ACTIVE_CUSTOM_THEME === CustomTheme.CHRISTMAS && isChristmasEnabled && themedOptions.winterSound) { return themedOptions.winterSound } if ( ACTIVE_CUSTOM_THEME === CustomTheme.HALLOWEEN && - featureFlags.isHalloweenEnabled && + isHalloweenEnabled && themedOptions.halloweenSound && isDarkMode() ) { diff --git a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts index 8031e391f3..f6a3d0b4e2 100644 --- a/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts +++ b/apps/cowswap-frontend/src/utils/orderUtils/parseOrder.ts @@ -24,7 +24,9 @@ export interface ParsedOrderExecutionData { surplusAmount: BigNumber surplusPercentage: BigNumber executedFeeAmount: string | undefined - executedSurplusFee: string | null + executedFee: string | null + executedFeeToken: string | null + totalFee: string | null filledPercentDisplay: string executedPrice: Price | null activityId: string | undefined @@ -60,7 +62,9 @@ export const parseOrder = (order: Order): ParsedOrder => { const { executedBuyAmount, executedSellAmount } = getOrderExecutedAmounts(order) const expirationTime = new Date(Number(order.validTo) * 1000) const executedFeeAmount = order.apiAdditionalInfo?.executedFeeAmount - const executedSurplusFee = order.apiAdditionalInfo?.executedSurplusFee || null + const executedFee = order.apiAdditionalInfo?.executedFee || null + const executedFeeToken = order.apiAdditionalInfo?.executedFeeToken || null + const totalFee = order.apiAdditionalInfo?.totalFee || null const creationTime = new Date(order.creationTime) const fullyFilled = isOrderFilled(order) const partiallyFilled = isPartiallyFilled(order) @@ -80,6 +84,7 @@ export const parseOrder = (order: Order): ParsedOrder => { const activityTitle = showCreationTxLink ? 'Creation transaction' : 'Order ID' const executionData: ParsedOrderExecutionData = { + executedFeeToken, executedBuyAmount, executedSellAmount, filledAmount, @@ -88,7 +93,8 @@ export const parseOrder = (order: Order): ParsedOrder => { surplusAmount, surplusPercentage, executedFeeAmount, - executedSurplusFee, + executedFee, + totalFee, executedPrice, fullyFilled, partiallyFilled, diff --git a/apps/explorer/src/api/operator/types.ts b/apps/explorer/src/api/operator/types.ts index 8ef8bf3dba..54240f124e 100644 --- a/apps/explorer/src/api/operator/types.ts +++ b/apps/explorer/src/api/operator/types.ts @@ -18,7 +18,15 @@ export type RawOrder = EnrichedOrder */ export type Order = Pick< RawOrder, - 'owner' | 'uid' | 'appData' | 'kind' | 'partiallyFillable' | 'signature' | 'class' | 'fullAppData' + | 'owner' + | 'uid' + | 'appData' + | 'kind' + | 'partiallyFillable' + | 'signature' + | 'class' + | 'fullAppData' + | 'executedFeeToken' > & { receiver: string txHash?: string @@ -35,7 +43,7 @@ export type Order = Pick< executedSellAmount: BigNumber feeAmount: BigNumber executedFeeAmount: BigNumber - executedSurplusFee: BigNumber | null + executedFee: BigNumber | null totalFee: BigNumber cancelled: boolean status: OrderStatus @@ -60,7 +68,7 @@ export type Trade = Pick