8000 feat(bridge): display execution price in swap details by shoom3301 · Pull Request #5920 · cowprotocol/cowswap · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(bridge): display execution price in swap details #5920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ export function ActivityDetails(props: {
<SummaryInnerRow>
<b>{isOrderFulfilled ? 'Exec. price' : 'Limit price'}</b>
<i>
<RateInfo noLabel={true} rateInfoParams={rateInfoParams} />
<RateInfo noLabel rateInfoParams={rateInfoParams} />
</i>
</SummaryInnerRow>
<SummaryInnerRow isCancelled={isCancelled} isExpired={isExpired}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function SwapStepRow({ context }: SwapStepRowProps): ReactNode {
sellAmount={sourceAmounts.sellAmount}
buyAmount={sourceAmounts.buyAmount}
>
<SwapResultContent context={swapResultContext} />
<SwapResultContent context={swapResultContext} sellAmount={sourceAmounts.sellAmount} />
</BridgeDetailsContainer>
</StepContent>
</SwapSummaryRow>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export function ProgressDetails({
return (
<CollapsibleBridgeRoute className={className} isCollapsible={false} isExpanded={true} providerInfo={bridgeProvider}>
<BridgeDetailsContainer
isCollapsible={true}
defaultExpanded={true}
isCollapsible
defaultExpanded
status={swapStatus}
statusIcon={SwapStatusIcons[swapStatus]}
protocolIconShowOnly="first"
Expand All @@ -49,12 +49,12 @@ export function ProgressDetails({
sellAmount={sourceAmounts.sellAmount}
buyAmount={sourceAmounts.buyAmount}
>
<SwapResultContent context={swapResultContext} />
<SwapResultContent context={swapResultContext} sellAmount={sourceAmounts.sellAmount} />
</BridgeDetailsContainer>
<DividerHorizontal margin="8px 0 4px" />
<BridgeDetailsContainer
isCollapsible={true}
defaultExpanded={true}
isCollapsible
defaultExpanded
status={bridgeStatus}
statusIcon={BridgeStatusIcons[bridgeStatus]}
protocolIconShowOnly="second"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { ReactNode } from 'react'

import PlusIcon from '@cowprotocol/assets/cow-swap/plus.svg'
import type { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'

import styled from 'styled-components/macro'

import { AMM_LOGOS } from 'legacy/components/AMMsLogo'

import { ConfirmDetailsItem, ReceiveAmountTitle } from 'modules/trade'

import { RateInfo, RateInfoParams } from 'common/pure/RateInfo'
import type { SolverCompetition } from 'common/types/soverCompetition'

import { StyledTimelinePlusIcon, SuccessTextBold, TimelineIconCircleWrapper } from '../../../styles'
import { TokenAmountDisplay } from '../../TokenAmountDisplay'

const WinningSolverContainer = styled.div`
display: flex;
align-items: center;
gap: 4px;
`

export function ReceivedContent({
receivedAmount,
receivedAmountUsd,
}: {
receivedAmount: CurrencyAmount<Currency>
receivedAmountUsd: CurrencyAmount<Token> | null
}): ReactNode {
return (
<ConfirmDetailsItem
label={
<ReceiveAmountTitle>
<b>Received</b>
</ReceiveAmountTitle>
}
>
<b>
<TokenAmountDisplay currencyAmount={receivedAmount} displaySymbol usdValue={receivedAmountUsd} />
</b>
</ConfirmDetailsItem>
)
}

export function ExecPriceContent({ rateInfoParams }: { rateInfoParams: RateInfoParams }): ReactNode {
return (
<ConfirmDetailsItem withTimelineDot label={<span>Exec. price</span>}>
<span>
<RateInfo noLabel rateInfoParams={rateInfoParams} />
</span>
</ConfirmDetailsItem>
)
}

export function SolverContent({ winningSolver }: { winningSolver: SolverCompetition }): ReactNode {
return (
<ConfirmDetailsItem withTimelineDot label="Winning solver">
<WinningSolverContainer>
<b>{winningSolver.displayName || winningSolver.solver}</b>
<img
src={winningSolver.image || AMM_LOGOS[winningSolver.solver]?.src || AMM_LOGOS.default.src}
alt={`${winningSolver.solver} logo`}
width="16"
height="16"
/>
</WinningSolverContainer>
</ConfirmDetailsItem>
)
}

export function SurplusConfig({
surplusAmount,
surplusAmountUsd,
}: {
surplusAmount: CurrencyAmount<Currency>
surplusAmountUsd: CurrencyAmount<Token> | null
}): ReactNode {
return (
<ConfirmDetailsItem
label={
<ReceiveAmountTitle
icon={
<TimelineIconCircleWrapper>
<StyledTimelinePlusIcon src={PlusIcon} />
</TimelineIconCircleWrapper>
}
>
<SuccessTextBold>Surplus received</SuccessTextBold>
</ReceiveAmountTitle>
}
>
<SuccessTextBold>
<TokenAmountDisplay
currencyAmount={surplusAmount}
displaySymbol
usdValue={surplusAmountUsd}
hideTokenIcon={true}
>
+
</TokenAmountDisplay>
</SuccessTextBold>
</ConfirmDetailsItem>
)
}
Original file line number Diff line number Diff line change
@@ -1,97 +1,41 @@
import { ReactNode } from 'react'

import PlusIcon from '@cowprotocol/assets/cow-swap/plus.svg'
import { isTruthy } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'

import styled from 'styled-components/macro'
import { useSafeMemo } from 'common/hooks/useSafeMemo'
import { RateInfoParams } from 'common/pure/RateInfo'

import { AMM_LOGOS } from 'legacy/components/AMMsLogo'
import { ExecPriceContent, ReceivedContent, SolverContent, SurplusConfig } from './contents'

import { ConfirmDetailsItem, ReceiveAmountTitle } from 'modules/trade'

import { StyledTimelinePlusIcon, SuccessTextBold, TimelineIconCircleWrapper } from '../../../styles'
import { SwapResultContext } from '../../../types'
import { TokenAmountDisplay } from '../../TokenAmountDisplay'

const WinningSolverContainer = styled.div`
display: flex;
align-items: center;
gap: 4px;
`

interface SwapResultContentProps {
context: SwapResultContext
sellAmount: CurrencyAmount<Currency>
}

export function SwapResultContent({
sellAmount,
context: { winningSolver, receivedAmount, receivedAmountUsd, surplusAmount, surplusAmountUsd },
}: SwapResultContentProps): ReactNode {
const contents = [
winningSolver
? {
withTimelineDot: true,
label: 'Winning solver',
content: (
<WinningSolverContainer>
<b>{winningSolver.displayName || winningSolver.solver}</b>
<img
src={winningSolver.image || AMM_LOGOS[winningSolver.solver]?.src || AMM_LOGOS.default.src}
alt={`${winningSolver.solver} logo`}
width="16"
height="16"
/>
</WinningSolverContainer>
),
}
: null,
{
label: (
<ReceiveAmountTitle>
<b>Received</b>
</ReceiveAmountTitle>
),
content: (
<b>
<TokenAmountDisplay currencyAmount={receivedAmount} displaySymbol usdValue={receivedAmountUsd} />
</b>
),
},
surplusAmount.greaterThan(0)
? {
label: (
<ReceiveAmountTitle
icon={
<TimelineIconCircleWrapper>
<StyledTimelinePlusIcon src={PlusIcon} />
</TimelineIconCircleWrapper>
}
F438 >
<SuccessTextBold>Surplus received</SuccessTextBold>
</ReceiveAmountTitle>
),
content: (
<SuccessTextBold>
<TokenAmountDisplay
currencyAmount={surplusAmount}
displaySymbol
usdValue={surplusAmountUsd}
hideTokenIcon={true}
>
+
</TokenAmountDisplay>
</SuccessTextBold>
),
}
: null,
]
const rateInfoParams: RateInfoParams = useSafeMemo(() => {
return {
chainId: sellAmount.currency.chainId,
inputCurrencyAmount: sellAmount,
outputCurrencyAmount: receivedAmount,
activeRateFiatAmount: null,
invertedActiveRateFiatAmount: null,
}
}, [sellAmount, receivedAmount])

return (
<>
{contents.filter(isTruthy).map(({ withTimelineDot, label, content }, index) => (
<ConfirmDetailsItem key={index} withTimelineDot={withTimelineDot} label={label}>
{content}
</ConfirmDetailsItem>
))}
{winningSolver && <SolverContent winningSolver={winningSolver} />}
<ReceivedContent receivedAmount={receivedAmount} receivedAmountUsd={receivedAmountUsd} />
<ExecPriceContent rateInfoParams={rateInfoParams} />
{surplusAmount.greaterThan(0) && (
<SurplusConfig surplusAmount={surplusAmount} surplusAmountUsd={surplusAmountUsd} />
)}
</>
)
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import { useCallback, useEffect, useState } from 'react'
import { ReactNode, useEffect, useState } from 'react'

import { SupportedChainId } from '@cowprotocol/cow-sdk'
import { Command } from '@cowprotocol/types'
import { useWalletInfo } from '@cowprotocol/wallet'

import { useOrder } from 'legacy/state/orders/hooks'

import { BridgeQuoteAmounts } from 'modules/bridge'
import { useNavigateToNewOrderCallback, useTradeConfirmState } from 'modules/trade'

import { useOrderProgressBarProps } from './useOrderProgressBarProps'

import { useOrderProgressBarProps } from '../hooks/useOrderProgressBarProps'
import { TransactionSubmittedContent } from '../pure/TransactionSubmittedContent'

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function useOrderSubmittedContent(chainId: SupportedChainId, _bridgeQuoteAmounts?: BridgeQuoteAmounts) {
interface OrderSubmittedContentProps {
onDismiss: Command
bridgeQuoteAmounts?: BridgeQuoteAmounts
}

export function OrderSubmittedContent({
onDismiss,
bridgeQuoteAmounts: _bridgeQuoteAmounts,
}: OrderSubmittedContentProps): ReactNode {
const { chainId } = useWalletInfo()
const { transactionHash, pendingTrade } = useTradeConfirmState()
const hasPendingTrade = !!pendingTrade
const order = useOrder({ chainId, id: transactionHash || undefined })
Expand All @@ -39,17 +45,14 @@ export function useOrderSubmittedContent(chainId: SupportedChainId, _bridgeQuote

const navigateToNewOrderCallback = useNavigateToNewOrderCallback()

return useCallback(
(onDismiss: Command) => (
<TransactionSubmittedContent
chainId={chainId}
hash={transactionHash || undefined}
>
activityDerivedState={activityDerivedState}
orderProgressBarProps={orderProgressBarProps}
navigateToNewOrderCallback={navigateToNewOrderCallback}
/>
),
[chainId, transactionHash, orderProgressBarProps, activityDerivedState, navigateToNewOrderCallback],
return (
<TransactionSubmittedContent
chainId={chainId}
hash={transactionHash || undefined}
>
activityDerivedState={activityDerivedState}
orderProgressBarProps={orderProgressBarProps}
navigateToNewOrderCallback={navigateToNewOrderCallback}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ export { ProgressBarExecutingOrdersUpdater } from './updaters/ProgressBarExecuti
export { SurplusModalSetup } from './containers/SurplusModalSetup'

// Hooks
export { useOrderSubmittedContent } from './hooks/useOrderSubmittedContent'
export { OrderSubmittedContent } from './containers/OrderSubmittedContent'

export * from './types'
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ReactNode } from 'react'

import styled from 'styled-components/macro'

import { OrderProgressBarProps, OrderProgressBarStepName } from '../../types'
import { OrderProgressBarStepName } from '../../types'

const Wrapper = styled.div`
position: fixed;
Expand All @@ -14,14 +16,11 @@ const Wrapper = styled.div`
`

interface DebugPanelProps {
stepNameToStepComponent: Record<OrderProgressBarStepName, React.ComponentType<OrderProgressBarProps>>
stepName: OrderProgressBarStepName
setDebugStep: (stepName: OrderProgressBarStepName) => void
}

// TODO: Add proper return type annotation
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function DebugPanel({ stepNameToStepComponent, stepName, setDebugStep }: DebugPanelProps) {
export function DebugPanel({ stepName, setDebugStep }: DebugPanelProps): ReactNode {
return (
<Wrapper>
<label htmlFor="debug-step-select">Debug Step:</label>
Expand All @@ -31,7 +30,7 @@ export function DebugPanel({ stepNameToStepComponent, stepName, setDebugStep }:
aria-label="Select debug step"
=> setDebugStep(e.target.value as OrderProgressBarStepName)}
>
{Object.keys(stepNameToStepComponent).map((step) => (
{Object.values(OrderProgressBarStepName).map((step) => (
<option key={step} value={step}>
{step}
</option>
Expand Down
Loading
Loading
0