Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions apps/cowswap-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@cowprotocol/common-utils": "workspace:*",
"@cowprotocol/core": "workspace:*",
"@cowprotocol/cow-runner-game": "https://registry.npmjs.org/@cowprotocol/cow-runner-game/-/cow-runner-game-0.2.9.tgz",
"@cowprotocol/cow-sdk": "9.1.3",
"@cowprotocol/cow-sdk": "9.1.4",
"@cowprotocol/cowswap-abis": "workspace:*",
"@cowprotocol/currency": "workspace:*",
"@cowprotocol/ens": "workspace:*",
Expand All @@ -49,12 +49,12 @@
"@cowprotocol/iframe-transport": "workspace:*",
"@cowprotocol/multicall": "workspace:*",
"@cowprotocol/permit-utils": "workspace:*",
"@cowprotocol/sdk-bridging": "4.1.0",
"@cowprotocol/sdk-contracts-ts": "3.1.0",
"@cowprotocol/sdk-cow-shed": "0.3.11",
"@cowprotocol/sdk-order-book": "3.2.0",
"@cowprotocol/sdk-trading": "2.1.0",
"@cowprotocol/sdk-viem-adapter": "0.3.21",
"@cowprotocol/sdk-bridging": "4.1.1",
"@cowprotocol/sdk-contracts-ts": "3.1.1",
"@cowprotocol/sdk-cow-shed": "0.3.12",
"@cowprotocol/sdk-order-book": "3.2.1",
"@cowprotocol/sdk-trading": "2.1.1",
"@cowprotocol/sdk-viem-adapter": "0.3.22",
"@cowprotocol/snackbars": "workspace:*",
"@cowprotocol/tokens": "workspace:*",
"@cowprotocol/types": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS } from '@cowprotocol/common-utils'
import { EnrichedOrder, OrderClass, OrderKind, OrderStatus, SigningScheme } from '@cowprotocol/cow-sdk'

import { TwapOrderItem, TwapOrderStatus } from 'modules/twap'
Expand All @@ -12,7 +13,7 @@ const statusMap: Record<TwapOrderStatus, OrderStatus> = {
}

export function emulateTwapAsOrder(item: TwapOrderItem): EnrichedOrder {
const { safeAddress, id, status, executionInfo } = item
const { safeAddress, id, status, executionInfo, chainId } = item
const { sellToken, buyToken, partSellAmount, minPartLimit, n, t, appData, receiver } = item.order
const numOfParts = BigInt(n)
const sellAmountValue = BigInt(partSellAmount) * numOfParts
Expand Down Expand Up @@ -48,5 +49,6 @@ export function emulateTwapAsOrder(item: TwapOrderItem): EnrichedOrder {
executedFeeAmount,
invalidated: status === TwapOrderStatus.Cancelling,
receiver,
settlementContract: COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS[chainId],
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS } from '@cowprotocol/common-utils'
import { EnrichedOrder, getAddressKey, OrderClass, OrderStatus, SigningScheme } from '@cowprotocol/cow-sdk'

import { TwapPartOrderItem } from '../state/twapPartOrdersAtom'
Expand All @@ -24,6 +25,7 @@ export function emulatePartAsOrder(item: TwapPartOrderItem, parent: TwapOrderIte
executedBuyAmount: '0',
executedFeeAmount: '0',
invalidated: isCancelling,
settlementContract: COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS[item.chainId],
}
}

Expand Down
10 changes: 5 additions & 5 deletions apps/explorer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
"@cowprotocol/common-hooks": "workspace:*",
"@cowprotocol/common-utils": "workspace:*",
"@cowprotocol/core": "workspace:*",
"@cowprotocol/cow-sdk": "9.1.3",
"@cowprotocol/cow-sdk": "9.1.4",
"@cowprotocol/hook-dapp-lib": "workspace:*",
"@cowprotocol/sdk-bridging": "4.1.0",
"@cowprotocol/sdk-contracts-ts": "3.1.0",
"@cowprotocol/sdk-subgraph": "1.1.0",
"@cowprotocol/sdk-viem-adapter": "0.3.21",
"@cowprotocol/sdk-bridging": "4.1.1",
"@cowprotocol/sdk-contracts-ts": "3.1.1",
"@cowprotocol/sdk-subgraph": "1.1.1",
"@cowprotocol/sdk-viem-adapter": "0.3.22",
"@cowprotocol/types": "workspace:*",
"@cowprotocol/ui": "workspace:*",
"@fortawesome/fontawesome-svg-core": "6.7.2",
Expand Down
35 changes: 34 additions & 1 deletion apps/explorer/src/api/operator/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
AddressKey,
CompetitionOrderStatus,
EnrichedOrder,
OrderKind,
Expand Down Expand Up @@ -67,6 +68,35 @@ export type GetTxOrdersParams = WithNetworkId & {
txHash: TxHash
}

/**
* How a protocol fee was calculated, derived from the trade's fee policy.
* Used to label each fee so the different fees on an order can be told apart.
*/
export enum ProtocolFeeType {
Surplus = 'surplus',
Volume = 'volume',
PriceImprovement = 'priceImprovement',
Unknown = 'unknown',
}

/**
* A single protocol fee charged on a trade, derived from the trade's executedProtocolFees.
* `tokenAddress` is a normalized AddressKey (the surplus-side token the fee is taken in).
*/
export type ProtocolFee = {
amount: BigNumber
tokenAddress: AddressKey
type: ProtocolFeeType
/**
* The fee policy's `factor`, when known. Its meaning is policy-specific: for
* {@link ProtocolFeeType.Volume} it's a fraction of trade volume, which we surface as basis
* points to tell otherwise identically labeled fees apart (e.g. a protocol volume fee vs a
* partner volume fee, which the API does not distinguish). For surplus / price-improvement fees
* it's a fraction of the surplus / improvement, so it is not shown as bps.
*/
factor?: number
}

/**
* Enriched Order type.
* Applies some transformations on the raw api data.
Expand Down Expand Up @@ -101,6 +131,9 @@ export type Order = Pick<
executedFeeAmount: BigNumber
executedFee: BigNumber | null
totalFee: BigNumber
// Derived client-side from the trades' executedProtocolFees (not returned directly on the order).
// Each entry is kept separate rather than aggregated; network costs are intentionally not surfaced.
protocolFees?: ProtocolFee[]
cancelled: boolean
status: OrderStatus
partiallyFilled: boolean
Expand All @@ -127,7 +160,7 @@ export type RawTrade = TradeMetaData
/**
* Enriched Trade type
*/
export type Trade = Pick<RawTrade, 'blockNumber' | 'logIndex' | 'owner' | 'txHash'> & {
export type Trade = Pick<RawTrade, 'blockNumber' | 'logIndex' | 'owner' | 'txHash' | 'executedProtocolFees'> & {
orderId: string
kind?: OrderKind
buyAmount: BigNumber
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import { ReactNode, useState } from 'react'

import { AppDataWrapper } from 'components/common/AppDataWrapper'
import { RowWithCopyButton } from 'components/common/RowWithCopyButton'
import { ShowMoreButton } from 'components/common/ShowMoreButton'
import { useAppData } from 'hooks/useAppData'

import * as styledEl from './AppDataRowContent.styles'

import { AppDataContent } from '../AppData/AppDataContent'

interface AppDataRowContentProps {
Expand Down Expand Up @@ -44,9 +43,9 @@ export function AppDataRowContent({ appData, showExpanded = false, fullAppData }
)}
&nbsp;
{hasAppData && (
<styledEl.ShowMoreButton onClick={() => setShowDecodedAppData((state) => !state)}>
<ShowMoreButton onClick={() => setShowDecodedAppData((state) => !state)}>
{showDecodedAppData ? '[-] Show less' : '[+] Show more'}
</styledEl.ShowMoreButton>
</ShowMoreButton>
)}
</>
<div className={`hidden-content ${appDataError && 'error'}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,5 @@ export const DetailsTableTooltips = {
'The (averaged) surplus for this order. This is the positive difference between the initial limit price and the actual (average) execution price.',
filled:
'Indicates what percentage amount this order has been filled and the amount sold/bought. Amount sold includes the fee.',
fees: 'The amount of fees paid for this order. This will show a progressive number for orders with partial fills. Might take a few minutes to show the final value.',
fees: 'The protocol fees charged for this order, listed per token. Network costs are not included. Might take a few minutes to show the final value.',
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface CostAndFeesItemProps {

export function CostAndFeesItem({ order }: CostAndFeesItemProps): ReactNode {
return (
<DetailRow label="Costs & Fees" tooltipText={DetailsTableTooltips.fees}>
<DetailRow label="Costs & Fees" tooltipText={DetailsTableTooltips.fees} stack>
<GasFeeDisplay order={order} />
</DetailRow>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import React from 'react'

import { getAddressKey } from '@cowprotocol/cow-sdk'

import { Story, Meta } from '@storybook/react/types-6-0'
import BigNumber from 'bignumber.js'
import { ZERO_BIG_NUMBER } from 'const'
import { GlobalStyles, ThemeToggler } from 'storybook/decorators'

import { RICH_ORDER, WETH } from '../../../test/data'
import { ProtocolFeeType } from 'api/operator'

import { RICH_ORDER, USDT, WETH } from '../../../test/data'

import { GasFeeDisplay, Props } from '.'

Expand All @@ -22,28 +25,35 @@ const Template: Story<Props> = (args) => (
</div>
)

const order = {
...RICH_ORDER,
feeAmount: new BigNumber('200000'),
executedFeeAmount: ZERO_BIG_NUMBER,
const defaultProps: Props = { order: RICH_ORDER }

// No protocol fees -> renders a dash
export const NoProtocolFees = Template.bind({})
NoProtocolFees.args = { ...defaultProps }

// Single protocol fee, denominated in the buy token (surplus side)
export const SingleProtocolFee = Template.bind({})
SingleProtocolFee.args = {
order: {
...RICH_ORDER,
protocolFees: [
{ amount: new BigNumber('1166200'), tokenAddress: getAddressKey(USDT.address), type: ProtocolFeeType.Surplus },
],
},
}

const defaultProps: Props = { order }

export const NoFee = Template.bind({})
NoFee.args = { ...defaultProps }

export const PartialFee = Template.bind({})
PartialFee.args = { ...defaultProps, order: { ...order, executedFeeAmount: new BigNumber('100000') } }

export const FullFee = Template.bind({})
FullFee.args = { ...defaultProps, order: { ...order, executedFeeAmount: order.feeAmount, fullyFilled: true } }

export const TinyFee6DecimalsToken = Template.bind({})
TinyFee6DecimalsToken.args = { ...defaultProps, order: { ...order, executedFeeAmount: new BigNumber('1') } }

export const TinyFee18DecimalsToken = Template.bind({})
TinyFee18DecimalsToken.args = {
...defaultProps,
order: { ...order, executedFeeAmount: new BigNumber('1'), sellToken: WETH },
// Multiple protocol fees of different types/tokens, each shown on its own labelled row
export const MultipleProtocolFees = Template.bind({})
MultipleProtocolFees.args = {
order: {
...RICH_ORDER,
protocolFees: [
{ amount: new BigNumber('1166200'), tokenAddress: getAddressKey(USDT.address), type: ProtocolFeeType.Surplus },
{
amount: new BigNumber('50000000000000000'),
tokenAddress: getAddressKey(WETH.address),
type: ProtocolFeeType.PriceImprovement,
},
],
},
}
Loading
Loading