Skip to content

Commit

Permalink
feat: initial display of networks costs and protocol fees
Browse files Browse the repository at this point in the history
  • Loading branch information
alfetopito committed Oct 23, 2024
1 parent 4b8e137 commit eede08a
Showing 1 changed file with 94 additions and 53 deletions.
147 changes: 94 additions & 53 deletions apps/explorer/src/components/orders/GasFeeDisplay/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
// TODO: Enable once API is ready
// import { NumbersBreakdown } from 'components/orders/NumbersBreakdown'

import { useMemo } from 'react'

import { isSellOrder } from '@cowprotocol/common-utils'
import { Nullish } from '@cowprotocol/ui'

import { TokenErc20 } from '@gnosis.pm/dex-js'
import BigNumber from 'bignumber.js'
import { ZERO_BIG_NUMBER } from 'const'
import styled from 'styled-components/macro'
import { formatSmartMaxPrecision, safeTokenName } from 'utils'

import { Order } from 'api/operator'

import { NumbersBreakdown } from '../NumbersBreakdown'

const Wrapper = styled.div`
> span {
margin: 0 0.5rem 0 0;
Expand All @@ -15,55 +24,11 @@ const Wrapper = styled.div`

export type Props = { order: Order }

// TODO: Enable once API is ready
// const fetchFeeBreakdown = async (initialFee: string): Promise<any> => {
// // TODO: Simulating API call to fetch fee breakdown data
// return new Promise((resolve) => {
// resolve({
// networkCosts: 'TODO: Get network costs here',
// fee: 'TODO: Get fee here',
// total: initialFee,
// })
// })
// }
export function GasFeeDisplay({ order }: Props): React.ReactNode | null {
const { feeAmount, totalFee, fullyFilled } = order

// TODO: Enable once API is ready
// const renderFeeBreakdown = (data: any): React.ReactNode => {
// return (
// <table>
// <tbody>
// <tr>
// <td>Network Costs:</td>
// <td>{data.networkCosts}</td>
// </tr>
// <tr>
// <td>Fee:</td>
// <td>{data.fee}</td>
// </tr>
// <tr>
// <td>Total Costs & Fees:</td>
// <td>{data.total}</td>
// </tr>
// </tbody>
// </table>
// )
// }

export function GasFeeDisplay(props: Props): React.ReactNode | null {
const {
order: { feeAmount, sellToken, sellTokenAddress, fullyFilled, totalFee },
} = props

let formattedExecutedFee: string = totalFee.toString(10)
let formattedTotalFee: string = feeAmount.toString(10)
let quoteSymbol: string = sellTokenAddress

if (sellToken) {
formattedExecutedFee = formatSmartMaxPrecision(totalFee, sellToken)
formattedTotalFee = formatSmartMaxPrecision(feeAmount, sellToken)

quoteSymbol = safeTokenName(sellToken)
}
const { quoteSymbol, formattedNetworkCosts, formattedProtocolFees, formattedExecutedFee, formattedTotalFee } =
useMemo(() => getFeeDisplayAmounts(order), [order])

const noFee = feeAmount.isZero() && totalFee.isZero()

Expand All @@ -83,11 +48,87 @@ export function GasFeeDisplay(props: Props): React.ReactNode | null {
return (
<Wrapper>
{FeeElement}
{/*TODO: Enable once API is ready*/}
{/*<NumbersBreakdown*/}
{/* fetchData={() => fetchFeeBreakdown(`${formattedExecutedFee} ${quoteSymbol}`)}*/}
{/* renderContent={renderFeeBreakdown}*/}
{/*/>*/}
<NumbersBreakdown>
<table>
<tbody>
{formattedNetworkCosts && (
<tr>
<td>Network Costs:</td>
<td>{formattedNetworkCosts}</td>
</tr>
)}
{formattedProtocolFees && (
<tr>
<td>Fee:</td>
<td>{formattedProtocolFees}</td>
</tr>
)}
<tr>
<td>Total Costs & Fees:</td>
<td>{formattedExecutedFee}</td>
</tr>
</tbody>
</table>
</NumbersBreakdown>
</Wrapper>
)
}

function getFeeDisplayAmounts(order: Order) {
const {
kind,
networkCosts,
protocolFees,
sellToken,
sellTokenAddress,
buyToken,
buyTokenAddress,
totalFee,
feeAmount,
} = order

const isSell = isSellOrder(kind)

let quoteSymbol = ''
let formattedNetworkCosts = ''
let formattedProtocolFees = ''
let formattedExecutedFee = ''
let formattedTotalFee = ''

// When these 2 are set, for sure we have new style fees
if (networkCosts || protocolFees) {
if (isSell) {
quoteSymbol = buyToken ? safeTokenName(buyToken) : buyTokenAddress
formattedNetworkCosts = getFormattedAmount(networkCosts || ZERO_BIG_NUMBER, buyToken)
formattedProtocolFees = getFormattedAmount(protocolFees || ZERO_BIG_NUMBER, buyToken)
formattedExecutedFee = getFormattedAmount(totalFee, buyToken)
formattedTotalFee = getFormattedAmount(feeAmount, buyToken)
} else {
quoteSymbol = sellToken ? safeTokenName(sellToken) : sellTokenAddress
formattedNetworkCosts = getFormattedAmount(networkCosts || ZERO_BIG_NUMBER, sellToken)
formattedProtocolFees = getFormattedAmount(protocolFees || ZERO_BIG_NUMBER, sellToken)
formattedExecutedFee = getFormattedAmount(totalFee, sellToken)
formattedTotalFee = getFormattedAmount(feeAmount, sellToken)
}
} else {
// Otherwise, it can have no fees OR be old style fees, without the policies
// TODO: handle old and new styles, as the fee token will vary! (always sell for old vs surplus token for new)
quoteSymbol = sellToken ? safeTokenName(sellToken) : sellTokenAddress
formattedNetworkCosts = ''
formattedProtocolFees = ''
formattedExecutedFee = getFormattedAmount(totalFee, sellToken)
formattedTotalFee = getFormattedAmount(feeAmount, sellToken)
}

return {
quoteSymbol,
formattedNetworkCosts,
formattedProtocolFees,
formattedExecutedFee,
formattedTotalFee,
}
}

function getFormattedAmount(amount: BigNumber, token: Nullish<TokenErc20>): string {
return token ? formatSmartMaxPrecision(amount, token) : amount.toString(10)
}

0 comments on commit eede08a

Please sign in to comment.