Skip to content

Commit f04d966

Browse files
committed
fix: fail closed for RWA geoblocking
1 parent c03a2d3 commit f04d966

25 files changed

Lines changed: 648 additions & 105 deletions

File tree

apps/cowswap-frontend/src/locales/en-US.po

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,12 @@ msgstr "Unsupported Token"
899899
#~ msgid "Limit price (incl. costs)"
900900
#~ msgstr "Limit price (incl. costs)"
901901

902+
#: apps/cowswap-frontend/src/modules/rwa/hooks/useImportTokenConsentFlow.tsx
903+
#: apps/cowswap-frontend/src/modules/tokensList/hooks/useRestrictedTokenImportStatus.ts
904+
#: apps/cowswap-frontend/src/modules/tokensList/hooks/useRestrictedTokensImportStatus.ts
905+
msgid "Checking token availability."
906+
msgstr "Checking token availability."
907+
902908
#: apps/cowswap-frontend/src/modules/ordersTable/pure/ContextMenu/OrderContextMenu.pure.tsx
903909
msgid "Order receipt"
904910
msgstr "Order receipt"
@@ -1992,6 +1998,10 @@ msgstr "Import List"
19921998
msgid "TWAP orders currently require a Safe with a special fallback handler. Have one? Switch to it! Need setup? <0>Click here</0>. Future updates may extend wallet support!"
19931999
msgstr "TWAP orders currently require a Safe with a special fallback handler. Have one? Switch to it! Need setup? <0>Click here</0>. Future updates may extend wallet support!"
19942000

2001+
#: apps/cowswap-frontend/src/modules/tradeFormValidation/pure/TradeFormButtons/tradeButtonsMap.tsx
2002+
msgid "Checking token availability"
2003+
msgstr "Checking token availability"
2004+
19952005
#: apps/cowswap-frontend/src/modules/orderProgressBar/constants.ts
19962006
msgid "CoW Swap was the first DEX to offer intent-based trading, gasless swaps, coincidences of wants, and many other DeFi innovations."
19972007
msgstr "CoW Swap was the first DEX to offer intent-based trading, gasless swaps, coincidences of wants, and many other DeFi innovations."

apps/cowswap-frontend/src/modules/application/containers/App/Updaters.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export function Updaters(): ReactNode {
121121
isYieldEnabled={isYieldEnabled}
122122
bridgeNetworkInfo={bridgeNetworkInfo?.data}
123123
/>
124-
<RestrictedTokensListUpdater isRwaGeoblockEnabled={!!isRwaGeoblockEnabled} />
124+
<RestrictedTokensListUpdater isRwaGeoblockEnabled={isRwaGeoblockEnabled} />
125125
<BlockedListSourcesUpdater />
126126
<RecentTokensStorageUpdater />
127127
<GeoDataUpdater />

apps/cowswap-frontend/src/modules/ethFlow/containers/EthFlow/hooks/useEthFlowActions.ts

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

4-
import { WRAPPED_NATIVE_CURRENCIES } from '@cowprotocol/common-const'
4+
import { TokenWithLogo, WRAPPED_NATIVE_CURRENCIES } from '@cowprotocol/common-const'
55
import { Command } from '@cowprotocol/types'
66
import { useWalletInfo } from '@cowprotocol/wallet'
77

@@ -10,8 +10,9 @@ import { Field } from 'legacy/state/types'
1010

1111
import { MAX_APPROVE_AMOUNT, TradeApproveCallback } from 'modules/erc20Approve'
1212
import { useIsInfiniteApproveDisabledInWidget } from 'modules/injectedWidget'
13+
import { RwaTokenStatus, useRwaConsentModalState, useRwaTokenStatus } from 'modules/rwa'
1314
import { useSwapPartialApprovalToggleState } from 'modules/swap/hooks/useSwapSettings'
14-
import { useOnCurrencySelection, useTradeConfirmActions } from 'modules/trade'
15+
import { useDerivedTradeState, useOnCurrencySelection, useTradeConfirmActions } from 'modules/trade'
1516

1617
import { updateEthFlowContextAtom } from '../../../state/ethFlowContextAtom'
1718

@@ -32,14 +33,21 @@ export interface EthFlowActions {
3233
directSwap(): void
3334
}
3435

36+
// eslint-disable-next-line max-lines-per-function
3537
export function useEthFlowActions(callbacks: EthFlowActionCallbacks, amountToApprove?: bigint): EthFlowActions {
3638
const { chainId } = useWalletInfo()
39+
const { outputCurrency } = useDerivedTradeState() || {}
3740

3841
const updateEthFlowContext = useSetAtom(updateEthFlowContextAtom)
3942
const onCurrencySelection = useOnCurrencySelection()
4043
const { onOpen: openSwapConfirmModal } = useTradeConfirmActions()
44+
const { openModal: openRwaConsentModal } = useRwaConsentModalState()
4145
const [isPartialApproveEnabledBySettings] = useSwapPartialApprovalToggleState()
4246
const isInfiniteApproveDisabledInWidget = useIsInfiniteApproveDisabledInWidget()
47+
const { status: rwaStatus, rwaTokenInfo } = useRwaTokenStatus({
48+
inputCurrency: WRAPPED_NATIVE_CURRENCIES[chainId],
49+
outputCurrency,
50+
})
4351

4452
return useMemo(() => {
4553
function sendTransaction(type: 'approve' | 'wrap', callback: () => Promise<string | undefined>): Promise<void> {
@@ -61,6 +69,19 @@ export function useEthFlowActions(callbacks: EthFlowActionCallbacks, amountToApp
6169
}
6270

6371
const swap = async (): Promise<void> => {
72+
if (rwaStatus === RwaTokenStatus.ChecksPending || rwaStatus === RwaTokenStatus.Restricted) {
73+
return
74+
}
75+
76+
if (rwaStatus === RwaTokenStatus.RequiredConsent && rwaTokenInfo) {
77+
callbacks.dismiss()
78+
openRwaConsentModal({
79+
consentHash: rwaTokenInfo.consentHash,
80+
token: TokenWithLogo.fromToken(rwaTokenInfo.token),
81+
})
82+
return
83+
}
84+
6485
callbacks.dismiss()
6586
onCurrencySelection(Field.INPUT, WRAPPED_NATIVE_CURRENCIES[chainId], () => {
6687
openSwapConfirmModal(true)
@@ -114,8 +135,11 @@ export function useEthFlowActions(callbacks: EthFlowActionCallbacks, amountToApp
114135
onCurrencySelection,
115136
chainId,
116137
openSwapConfirmModal,
138+
openRwaConsentModal,
117139
isPartialApproveEnabledBySettings,
118140
isInfiniteApproveDisabledInWidget,
119141
amountToApprove,
142+
rwaStatus,
143+
rwaTokenInfo,
120144
])
121145
}

apps/cowswap-frontend/src/modules/rwa/containers/RwaConsentModalContainer/index.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ import { ReactNode, useCallback, useMemo } from 'react'
33
import { useWalletInfo } from '@cowprotocol/wallet'
44

55
import { RwaConsentKey, RwaConsentModal, useRwaConsentModalState, useRwaConsentStatus } from 'modules/rwa'
6-
import { useTradeConfirmActions } from 'modules/trade'
6+
import { useDerivedTradeState, useTradeConfirmActions } from 'modules/trade'
7+
8+
import { RwaTokenStatus, useRwaTokenStatus } from '../../hooks/useRwaTokenStatus'
79

810
export function RwaConsentModalContainer(): ReactNode {
911
const { account } = useWalletInfo()
1012
const { isModalOpen, closeModal, context } = useRwaConsentModalState()
1113
const tradeConfirmActions = useTradeConfirmActions()
14+
const derivedState = useDerivedTradeState()
15+
const { inputCurrency, outputCurrency } = derivedState || {}
16+
const { status: currentRwaStatus } = useRwaTokenStatus({ inputCurrency, outputCurrency })
1217

1318
const consentKey: RwaConsentKey | null = useMemo(() => {
1419
if (!context || !account) {
@@ -32,17 +37,22 @@ export function RwaConsentModalContainer(): ReactNode {
3237
return
3338
}
3439

35-
confirmConsent()
36-
closeModal()
37-
3840
// if this is a token import flow, call the success callback to proceed to import modal
3941
// if this is a trade flow, open the trade confirmation
4042
if (context.onImportSuccess) {
43+
confirmConsent()
44+
closeModal()
4145
context.onImportSuccess()
4246
} else {
47+
if (currentRwaStatus === RwaTokenStatus.ChecksPending || currentRwaStatus === RwaTokenStatus.Restricted) {
48+
return
49+
}
50+
51+
confirmConsent()
52+
closeModal()
4353
tradeConfirmActions.onOpen()
4454
}
45-
}, [account, context, consentKey, confirmConsent, closeModal, tradeConfirmActions])
55+
}, [account, context, consentKey, confirmConsent, closeModal, currentRwaStatus, tradeConfirmActions])
4656

4757
if (!isModalOpen || !context) {
4858
return null

apps/cowswap-frontend/src/modules/rwa/hooks/useImportTokenConsentFlow.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import { useImportTokenWithConsent } from './useImportTokenWithConsent'
1212

1313
import { RwaConsentModal } from '../pure/RwaConsentModal'
1414

15-
function getRestrictedFlowResult(): CustomFlowResult<TokenSelectorView.ImportToken> {
15+
function getBlockedFlowResult(message: string): CustomFlowResult<TokenSelectorView.ImportToken> {
1616
return {
1717
content: null,
1818
data: {
1919
restriction: {
2020
isBlocked: true,
21-
message: t`This token is not available in your region.`,
21+
message,
2222
},
2323
},
2424
}
@@ -38,7 +38,11 @@ export function useImportTokenConsentFlow(): ViewFlowConfig<TokenSelectorView.Im
3838
if (!tokenToImport) return null
3939

4040
if (rwaStatus === 'restricted') {
41-
return getRestrictedFlowResult()
41+
return getBlockedFlowResult(t`This token is not available in your region.`)
42+
}
43+
44+
if (rwaStatus === 'checks-pending') {
45+
return getBlockedFlowResult(t`Checking token availability.`)
4246
}
4347

4448
// Don't show consent modal to non-connected users - they can import the token

apps/cowswap-frontend/src/modules/rwa/hooks/useImportTokenRwaCheck.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useSelectTokenWidgetState } from 'modules/tokensList'
66

77
import { useRwaTokenStatus, RwaTokenStatus, RwaTokenInfo } from './useRwaTokenStatus'
88

9-
type ImportTokenRwaStatus = 'allowed' | 'restricted' | 'requires-consent' | null
9+
type ImportTokenRwaStatus = 'allowed' | 'restricted' | 'requires-consent' | 'checks-pending' | null
1010

1111
interface UseImportTokenRwaCheckResult {
1212
tokenToImport: TokenWithLogo | undefined
@@ -16,6 +16,7 @@ interface UseImportTokenRwaCheckResult {
1616

1717
const RWA_STATUS_MAP: Readonly<Record<RwaTokenStatus, ImportTokenRwaStatus>> = {
1818
[RwaTokenStatus.Allowed]: 'allowed',
19+
[RwaTokenStatus.ChecksPending]: 'checks-pending',
1920
[RwaTokenStatus.Restricted]: 'restricted',
2021
[RwaTokenStatus.RequiredConsent]: 'requires-consent',
2122
[RwaTokenStatus.ConsentIsSigned]: 'allowed',

0 commit comments

Comments
 (0)