Skip to content

Commit 0998f1d

Browse files
authored
Merge pull request #6090 from cowprotocol/hotfix/2025-07-31
Hotfix 2025-07-31
2 parents f51652a + 95b9089 commit 0998f1d

File tree

8 files changed

+73
-24
lines changed

8 files changed

+73
-24
lines changed

apps/cowswap-frontend/src/common/hooks/useSwapResultsContext.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export function useSwapResultsContext(
2828
const receivedAmount = useMemo(() => {
2929
if (!intermediateToken || !swappedAmountWithFee) return undefined
3030

31-
return CurrencyAmount.fromRawAmount(intermediateToken, swappedAmountWithFee.toString())
31+
return CurrencyAmount.fromRawAmount(intermediateToken, swappedAmountWithFee.toFixed(0))
3232
}, [swappedAmountWithFee, intermediateToken])
3333

3434
const receivedAmountUsd = useUsdAmount(receivedAmount).value

apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export function SelectTokenWidget({ displayLpTokenLists, standalone }: SelectTok
9595
const importTokenCallback = useAddUserToken()
9696

9797
const { tokens: allTokens, isLoading: areTokensLoading, favoriteTokens, areTokensFromBridge } = useTokensToSelect()
98+
9899
const userAddedTokens = useUserAddedTokens()
99100
const allTokenLists = useAllListsList()
100101
const balancesState = useTokensBalancesCombined()

apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ export function useSetupTradeState(): void {
206206

207207
if (!providerChainId || providerChainId === currentChainId) return
208208

209-
const targetChainId = rememberedUrlStateRef.current?.chainId || currentChainId
209+
const targetChainId = urlChainId ?? rememberedUrlStateRef.current?.chainId ?? currentChainId
210210
switchNetworkInWallet(targetChainId)
211211

212212
console.debug('[TRADE STATE]', 'Set chainId to provider', { provider, urlChainId })

apps/cowswap-frontend/src/modules/trade/hooks/setupTradeState/useSetupTradeStateFromUrl.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import { useLocation, useParams } from 'react-router'
66
import { tradeStateFromUrlAtom } from '../../state/tradeStateFromUrlAtom'
77
import { TradeRawState } from '../../types/TradeRawState'
88

9+
const getChainId = (chainId: string | undefined | null): number | null => {
10+
if (!chainId) return null
11+
if (/^\d+$/.test(chainId)) return Number(chainId)
12+
return null
13+
}
14+
915
/**
1016
* Updater to fetch trade state from URL params and query, and store it on jotai state
1117
* /1/swap/WETH/DAI?recipient=0x -> { chainId: 1, inputCurrencyId: 'WETH', outputCurrencyId: 'DAI', recipient: '0x' }
@@ -18,30 +24,40 @@ export function useSetupTradeStateFromUrl(): null {
1824
const stringifiedParams = JSON.stringify(params)
1925
const setState = useSetAtom(tradeStateFromUrlAtom)
2026

21-
/**
22-
* useEffect() runs after the render completes and useMemo() runs during rendering.
23-
* In order to update tradeStateFromUrlAtom faster we use useMemo() here.
24-
* We need this, because useSetupTradeState() depends on the atom value and needs it to be udpated ASAP.
25-
*/
26-
useMemo(() => {
27+
const { chainId, recipient, recipientAddress, targetChainId, inputCurrencyId, outputCurrencyId } = useMemo(() => {
2728
const searchParams = new URLSearchParams(location.search)
2829
const targetChainId = searchParams.get('targetChainId')
2930
const recipient = searchParams.get('recipient')
3031
const recipientAddress = searchParams.get('recipientAddress')
3132
const { chainId, inputCurrencyId, outputCurrencyId } = JSON.parse(stringifiedParams)
32-
const chainIdAsNumber = chainId && /^\d+$/.test(chainId) ? parseInt(chainId) : null
3333

34+
return {
35+
chainId: getChainId(chainId),
36+
inputCurrencyId: inputCurrencyId ?? null,
37+
outputCurrencyId: outputCurrencyId ?? null,
38+
recipient,
39+
recipientAddress,
40+
targetChainId: getChainId(targetChainId),
41+
}
42+
}, [location.search, stringifiedParams])
43+
44+
/**
45+
* useEffect() runs after the render completes and useMemo() runs during rendering.
46+
* In order to update tradeStateFromUrlAtom faster we use useMemo() here.
47+
* We need this, because useSetupTradeState() depends on the atom value and needs it to be udpated ASAP.
48+
*/
49+
useMemo(() => {
3450
const state: TradeRawState = {
35-
chainId: chainIdAsNumber,
36-
targetChainId: targetChainId ? +targetChainId : null,
37-
inputCurrencyId: inputCurrencyId || searchParams.get('inputCurrency') || null,
38-
outputCurrencyId: outputCurrencyId || searchParams.get('outputCurrency') || null,
51+
chainId,
52+
targetChainId,
53+
inputCurrencyId,
54+
outputCurrencyId,
3955
...(recipient ? { recipient } : undefined),
4056
...(recipientAddress ? { recipientAddress } : undefined),
4157
}
4258

4359
setState(state)
44-
}, [location.search, stringifiedParams, setState])
60+
}, [chainId, recipient, recipientAddress, setState, targetChainId, inputCurrencyId, outputCurrencyId])
4561

4662
return null
4763
}

apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ const quoteErrorTexts: Record<QuoteApiErrorCodes, string> = {
4242
[QuoteApiErrorCodes.SameBuyAndSellToken]: 'Tokens must be different',
4343
}
4444

45+
const quoteErrorTextsForBridges: Partial<Record<QuoteApiErrorCodes, string>> = {
46+
[QuoteApiErrorCodes.SameBuyAndSellToken]: 'Not yet supported',
47+
}
48+
4549
const bridgeQuoteErrorTexts: Record<BridgeQuoteErrors, string> = {
4650
[BridgeQuoteErrors.API_ERROR]: DEFAULT_QUOTE_ERROR,
4751
[BridgeQuoteErrors.INVALID_BRIDGE]: DEFAULT_QUOTE_ERROR,
@@ -53,6 +57,11 @@ const bridgeQuoteErrorTexts: Record<BridgeQuoteErrors, string> = {
5357
[BridgeQuoteErrors.ONLY_SELL_ORDER_SUPPORTED]: 'Only "sell" orders are supported',
5458
}
5559

60+
const errorTooltipContentForBridges: Partial<Record<QuoteApiErrorCodes, string>> = {
61+
[QuoteApiErrorCodes.SameBuyAndSellToken]:
62+
'Bridging without swapping is not yet supported. Let us know if you want this feature!',
63+
}
64+
5665
// TODO: Add proper return type annotation
5766
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
5867
const unsupportedTokenButton = (context: TradeFormButtonContext) => {
@@ -105,15 +114,24 @@ export const tradeButtonsMap: Record<TradeFormValidation, ButtonErrorConfig | Bu
105114
const { quote } = context
106115

107116
if (quote.error instanceof QuoteApiError) {
108-
if (quote.error.type === QuoteApiErrorCodes.UnsupportedToken) {
117+
const errorType = quote.error.type
118+
119+
if (errorType === QuoteApiErrorCodes.UnsupportedToken) {
109120
return unsupportedTokenButton(context)
110121
}
111122

112-
const errorText = quoteErrorTexts[quote.error.type] || DEFAULT_QUOTE_ERROR
123+
const isBridge = quote.isBridgeQuote
124+
const errorText =
125+
(isBridge && quoteErrorTextsForBridges[errorType]) || quoteErrorTexts[errorType] || DEFAULT_QUOTE_ERROR
126+
127+
const errorTooltipText = isBridge && errorTooltipContentForBridges[errorType]
113128

114129
return (
115130
<TradeFormBlankButton disabled={true}>
116-
<Trans>{errorText}</Trans>
131+
<>
132+
<Trans>{errorText}</Trans>
133+
{errorTooltipText && <HelpTooltip text={errorTooltipText} />}
134+
</>
117135
</TradeFormBlankButton>
118136
)
119137
}

apps/cowswap-frontend/src/modules/tradeQuote/hooks/useTradeQuoteManager.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import { useSetAtom } from 'jotai'
22
import { useMemo } from 'react'
33

4-
import { BridgeQuoteResults, PriceQuality, QuoteBridgeRequest, SupportedChainId } from '@cowprotocol/cow-sdk'
5-
import { QuoteAndPost } from '@cowprotocol/cow-sdk'
4+
import {
5+
BridgeQuoteResults,
6+
PriceQuality,
7+
QuoteAndPost,
8+
QuoteBridgeRequest,
9+
SupportedChainId,
10+
} from '@cowprotocol/cow-sdk'
611

712
import { QuoteApiError, QuoteApiErrorCodes } from 'api/cowProtocol/errors/QuoteError'
813

@@ -14,13 +19,16 @@ import { TradeQuoteFetchParams } from '../types'
1419

1520
export interface TradeQuoteManager {
1621
setLoading(hasParamsChanged: boolean): void
22+
1723
reset(): void
24+
1825
onError(
1926
error: TradeQuoteState['error'],
2027
chainId: SupportedChainId,
2128
quoteParams: QuoteBridgeRequest,
2229
fetchParams: TradeQuoteFetchParams,
2330
): void
31+
2432
onResponse(data: QuoteAndPost, bridgeQuote: BridgeQuoteResults | null, fetchParams: TradeQuoteFetchParams): void
2533
}
2634

@@ -48,7 +56,13 @@ export function useTradeQuoteManager(sellTokenAddress: SellTokenAddress | undefi
4856
quoteParams: QuoteBridgeRequest,
4957
fetchParams: TradeQuoteFetchParams,
5058
) {
51-
update(sellTokenAddress, { error, fetchParams, isLoading: false, hasParamsChanged: false })
59+
update(sellTokenAddress, {
60+
error,
61+
fetchParams,
62+
isLoading: false,
63+
hasParamsChanged: false,
64+
isBridgeQuote: quoteParams.sellTokenChainId !== quoteParams.buyTokenChainId,
65+
})
5266

5367
if (error instanceof QuoteApiError && error.type === QuoteApiErrorCodes.UnsupportedToken) {
5468
processUnsupportedTokenError(error, chainId, quoteParams)

apps/cowswap-frontend/src/modules/tradeQuote/state/tradeQuoteAtom.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { atom } from 'jotai'
22

3-
import { PriceQuality, QuoteAndPost, BridgeQuoteResults, BridgeProviderQuoteError } from '@cowprotocol/cow-sdk'
3+
import { BridgeProviderQuoteError, BridgeQuoteResults, PriceQuality, QuoteAndPost } from '@cowprotocol/cow-sdk'
44

55
import { QuoteApiError } from 'api/cowProtocol/errors/QuoteError'
66

@@ -10,6 +10,7 @@ type SellTokenAddress = string
1010

1111
export interface TradeQuoteState {
1212
quote: QuoteAndPost | null
13+
isBridgeQuote: boolean | null
1314
bridgeQuote: BridgeQuoteResults | null
1415
fetchParams: TradeQuoteFetchParams | null
1516
error: QuoteApiError | BridgeProviderQuoteError | null
@@ -21,6 +22,7 @@ export interface TradeQuoteState {
2122
export const DEFAULT_TRADE_QUOTE_STATE: TradeQuoteState = {
2223
quote: null,
2324
bridgeQuote: null,
25+
isBridgeQuote: null,
2426
fetchParams: null,
2527
error: null,
2628
hasParamsChanged: false,
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { TokenInfo } from '@cowprotocol/types'
22
import { Token } from '@uniswap/sdk-core'
33

4-
// TODO: Add proper return type annotation
5-
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
6-
export const doesTokenMatchSymbolOrAddress = (token: Token | TokenInfo, symbolOrAddress?: string) =>
4+
export const doesTokenMatchSymbolOrAddress = (token: Token | TokenInfo, symbolOrAddress?: string): boolean =>
75
token.address.toLowerCase() === symbolOrAddress?.toLowerCase() ||
86
token.symbol?.toLowerCase() === symbolOrAddress?.toLowerCase()

0 commit comments

Comments
 (0)