Skip to content
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
1 change: 1 addition & 0 deletions apps/cowswap-frontend/src/locales/en-US.po
Original file line number Diff line number Diff line change
Expand Up @@ -1526,6 +1526,7 @@ msgstr "Edit code"
msgid "Select an {accountProxyLabelString} to check for available refunds {chain}"
msgstr "Select an {accountProxyLabelString} to check for available refunds {chain}"

#: apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx
#: apps/cowswap-frontend/src/modules/twap/pure/PrimaryActionButton/index.tsx
msgid "Unsupported wallet"
msgstr "Unsupported wallet"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export function TwapFormWarnings({ localFormValidation, isConfirmationModal }: T
return (
<>
{(() => {
if (localFormValidation === TwapFormState.TX_BUNDLING_NOT_SUPPORTED) {
if (isUnsupportedWallet(localFormValidation)) {
return (
<UnsupportedWalletWarning
isSafeViaWc={isSafeViaWc}
Expand Down Expand Up @@ -151,3 +151,7 @@ export function TwapFormWarnings({ localFormValidation, isConfirmationModal }: T
</>
)
}

function isUnsupportedWallet(state: TwapFormState | null): boolean {
return state === TwapFormState.WALLET_NOT_SUPPORTED || state === TwapFormState.TX_BUNDLING_NOT_SUPPORTED
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ButtonSecondary, ExternalLink, InlineBanner, StatusColorVariant } from
import { Trans } from '@lingui/react/macro'
import styled from 'styled-components/macro'

import { UNSUPPORTED_WALLET_LINK } from 'modules/twap/const'
import { UNSUPPORTED_WALLET_LINK } from '../../../const'

const InterestButton = styled(ButtonSecondary).attrs({ type: 'button' })`
width: fit-content;
Expand All @@ -17,6 +17,9 @@ const InterestButton = styled(ButtonSecondary).attrs({ type: 'button' })`
export interface UnsupportedWalletWarningProps {
chainId: SupportedChainId
account?: string
/**
* If true, we want to suggest the user to try the Safe web app, because their wallet connection did not confirm tx bundling.
*/
isSafeViaWc: boolean
isInterestButtonVisible: boolean
isInterestRegistered: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export function TwapFormWidget({ tradeWarnings }: TwapFormWidget): ReactNode {

useEffect(() => {
if (account && verification) {
if (localFormValidation === TwapFormState.TX_BUNDLING_NOT_SUPPORTED) {
if (localFormValidation === TwapFormState.WALLET_NOT_SUPPORTED) {
cowAnalytics.sendEvent({
category: CowSwapAnalyticsCategory.TWAP,
action: 'non-compatible',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useAtomValue } from 'jotai'

import { useFeatureFlags } from '@cowprotocol/common-hooks'
import { useIsTxBundlingSupported, useWalletInfo } from '@cowprotocol/wallet'
import { isSafeAppAtom, isSafeViaWcAtom, useIsTxBundlingSupported, useWalletInfo } from '@cowprotocol/wallet'

import { useGetReceiveAmountInfo } from 'modules/trade'
import { tradeFormValidationContextAtom } from 'modules/tradeFormValidation'
Expand All @@ -28,9 +28,13 @@ export function useTwapFormState(): TwapFormState | null {
const tradeFormValidationContext = useAtomValue(tradeFormValidationContextAtom)

const verification = useFallbackHandlerVerification()
const isSafeApp = useAtomValue(isSafeAppAtom)
const isSafeViaWc = useAtomValue(isSafeViaWcAtom)
const isTxBundlingSupported = useIsTxBundlingSupported()
const isWalletSupported = isSafeApp === null || isSafeViaWc === null ? null : isSafeApp || isSafeViaWc

return getTwapFormState({
isWalletSupported,
isTxBundlingSupported,
verification,
twapOrder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,36 @@ const baseParams = {
partTime: 300,
numberOfPartsValue: 1,
tradeFormValidationContext: null,
isWalletSupported: true,
isTwapEoaEnabled: false,
} as const

describe('getTwapFormState()', () => {
it('returns WALLET_NOT_SUPPORTED for a non-Safe wallet', () => {
const result = getTwapFormState({
...baseParams,
isWalletSupported: false,
isTxBundlingSupported: true,
verification: ExtensibleFallbackVerification.HAS_NOTHING,
sellAmountPartFiat: null,
partTime: undefined,
})

expect(result).toEqual(TwapFormState.WALLET_NOT_SUPPORTED)
})

it('returns TX_BUNDLING_NOT_SUPPORTED for a Safe without batching support', () => {
const result = getTwapFormState({
...baseParams,
isTxBundlingSupported: false,
verification: ExtensibleFallbackVerification.HAS_NOTHING,
sellAmountPartFiat: null,
partTime: undefined,
})

expect(result).toEqual(TwapFormState.TX_BUNDLING_NOT_SUPPORTED)
})

describe('When sell fiat amount is under threshold', () => {
it('And order has buy amount, then should return SELL_AMOUNT_TOO_SMALL', () => {
const result = getTwapFormState({
Expand Down Expand Up @@ -91,6 +117,7 @@ describe('getTwapFormState()', () => {
it('Skips Safe guards when EOA flag is on so unsupported wallets can proceed', () => {
const result = getTwapFormState({
...baseParams,
isWalletSupported: false,
isTxBundlingSupported: false,
verification: null,
isTwapEoaEnabled: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { isPartTimeIntervalTooShort } from '../../utils/isPartTimeIntervalTooSho
import { isSellAmountTooSmall } from '../../utils/isSellAmountTooSmall'

export interface TwapFormStateParams {
isWalletSupported: boolean | null
isTxBundlingSupported: boolean | null
verification: ExtensibleFallbackVerification | null
twapOrder: TWAPOrder | null
Expand All @@ -27,6 +28,7 @@ export interface TwapFormStateParams {

export enum TwapFormState {
LOADING_SAFE_INFO = 'LOADING_SAFE_INFO',
WALLET_NOT_SUPPORTED = 'WALLET_NOT_SUPPORTED',
TX_BUNDLING_NOT_SUPPORTED = 'TX_BUNDLING_NOT_SUPPORTED',
SELL_AMOUNT_TOO_SMALL = 'SELL_AMOUNT_TOO_SMALL',
PART_TIME_INTERVAL_TOO_SHORT = 'PART_TIME_INTERVAL_TOO_SHORT',
Expand All @@ -36,6 +38,7 @@ export enum TwapFormState {

export function getTwapFormState(props: TwapFormStateParams): TwapFormState | null {
const {
isWalletSupported,
twapOrder,
isTxBundlingSupported,
verification,
Expand All @@ -49,9 +52,12 @@ export function getTwapFormState(props: TwapFormStateParams): TwapFormState | nu

// When TWAP for EOA is enabled, skip Safe/tx-bundling gates so EOAs can review and confirm.
if (!isTwapEoaEnabled) {
if (isWalletSupported === false) return TwapFormState.WALLET_NOT_SUPPORTED
if (isTxBundlingSupported === false) return TwapFormState.TX_BUNDLING_NOT_SUPPORTED

if (verification === null || isTxBundlingSupported === null) return TwapFormState.LOADING_SAFE_INFO
if (verification === null || isTxBundlingSupported === null || isWalletSupported === null) {
return TwapFormState.LOADING_SAFE_INFO
}
}

if (!isFractionFalsy(twapOrder?.buyAmount) && isSellAmountTooSmall(sellAmountPartFiat, chainId)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const buttonsMap: Record<TwapFormState, (_context: PrimaryActionButtonContext) =
<Trans>Loading...</Trans>
</ButtonPrimary>
),
[TwapFormState.WALLET_NOT_SUPPORTED]: () => (
<ButtonPrimary disabled={true} buttonSize={ButtonSize.BIG}>
<Trans>Unsupported wallet</Trans>
</ButtonPrimary>
),
[TwapFormState.TX_BUNDLING_NOT_SUPPORTED]: () => (
<ButtonPrimary disabled={true} buttonSize={ButtonSize.BIG}>
<Trans>Unsupported wallet</Trans>
Expand Down
Loading
Loading