-
Notifications
You must be signed in to change notification settings - Fork 160
feat: show conesnts before import modal #6770
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
base: develop
Are you sure you want to change the base?
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds geo-based blocking and consent gating for token lists and token imports: new persisted restricted-lists state, blocked-source tracking, hooks/updaters to compute blocking, UI changes to surface reasons and disable imports, RWA consent modal wiring, and new translation strings. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as SelectTokenWidget / ImportModal
participant Geo as GeoStatusHook
participant Lists as RestrictedListsAtom/Updaters
participant RWA as RwaConsentModal
participant Importer as useAddTokenImportCallback
User->>UI: request import (token or list)
UI->>Geo: read geoStatus
UI->>Lists: query restricted info & blocked sources
Lists-->>UI: isBlocked / blockReason
alt blocked by geo (isBlocked)
UI->>User: show blocked warning (import disabled)
else not blocked
User->>UI: confirm import
UI->>Importer: start import flow
Importer->>Lists: check requiresConsent (consentHash)
alt consent required & not cached
Importer->>RWA: open consent modal
User->>RWA: accept consent
RWA-->>Importer: onImportSuccess
Importer->>UI: proceed with import
else consent present or not required
Importer->>UI: proceed with import
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/cowswap-frontend/src/modules/rwa/containers/RwaConsentModalContainer/index.tsx (1)
29-44: LGTM! Clear branching logic for import vs. trade flows.The conditional flow correctly handles both token import and trade scenarios. The comments clearly explain the intent, and the order of operations (confirm → close → proceed) makes sense for a smooth user experience.
Optional: Consider adding defensive error handling around the callbacks to prevent unhandled exceptions after consent is recorded and the modal is closed. However, this is a nice-to-have improvement rather than a critical issue.
🔎 Optional: Add error boundary for callbacks
- // if this is a token import flow, call the success callback to proceed to import modal - // if this is a trade flow, open the trade confirmation - if (context.onImportSuccess) { - context.onImportSuccess() - } else { - tradeConfirmActions.onOpen() - } + // if this is a token import flow, call the success callback to proceed to import modal + // if this is a trade flow, open the trade confirmation + try { + if (context.onImportSuccess) { + context.onImportSuccess() + } else { + tradeConfirmActions.onOpen() + } + } catch (error) { + console.error('Failed to proceed after consent:', error) + // Optionally: re-open modal or show error notification + }
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/cowswap-frontend/src/locales/en-US.poapps/cowswap-frontend/src/modules/rwa/containers/RwaConsentModalContainer/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/cowswap-frontend/src/locales/en-US.po
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-10-10T20:28:16.565Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 6347
File: apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx:49-49
Timestamp: 2025-10-10T20:28:16.565Z
Learning: In apps/cowswap-frontend/src/modules/trade, TradeConfirmation follows a two-layer architecture: TradeConfirmationView (pure/stateless) in pure/TradeConfirmation/index.tsx renders the UI, while TradeConfirmation (container) in containers/TradeConfirmation/index.tsx wraps it to freeze props during pending trades (via useStableTradeConfirmationProps), wire in signing state (useSigningStep), and inject trade confirmation state (useTradeConfirmState). Consuming modules should import the container TradeConfirmation from 'modules/trade' to preserve this stateful behavior.
<!-- [add_learning]
When reviewing component refactoring in apps/cowswap-frontend/src/modules/trade, recognize the pattern where a pure view component (e.g., TradeConfirmationView) is separated from a stateful container (e.g., TradeConfirmation) that wraps it. The container adds runtime state management (prop stabilization, signing state, etc.) while the view remains testable and composable. Do not flag usages that import th...
Applied to files:
apps/cowswap-frontend/src/modules/rwa/containers/RwaConsentModalContainer/index.tsx
📚 Learning: 2025-10-13T19:41:31.440Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.
Applied to files:
apps/cowswap-frontend/src/modules/rwa/containers/RwaConsentModalContainer/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Cypress
- GitHub Check: Setup
🔇 Additional comments (1)
apps/cowswap-frontend/src/modules/rwa/containers/RwaConsentModalContainer/index.tsx (1)
5-5: LGTM! Good consolidation of imports.Centralizing imports from the
modules/rwabarrel export improves maintainability and follows the established container/pure component pattern in the codebase.
| return true | ||
| } | ||
|
|
||
| return !blockedCountries.includes(countryKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
country list is not big, about 50 elements, don't need to use Set here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx (1)
27-45: LGTM! Conditional logic correctly handles all import states.The three-way rendering logic properly covers all combinations of
sourceandisBlocked:
- Existing non-blocked lists show "Loaded"
- Blocked lists (any source) show the block reason with AlertCircle
- External non-blocked lists show the import button
The
blockReason || <Trans>fallback ensures a sensible default message when no custom reason is provided.Optional: Consider adding accessibility attributes
For screen reader users, consider adding an
aria-labelto theAlertCircleicon or wrapping the blocked state in an element with appropriate ARIA attributes:<styledEl.BlockedInfo> - <AlertCircle size={16} strokeWidth={2} /> + <AlertCircle size={16} strokeWidth={2} aria-label="Blocked" /> <span>{blockReason || <Trans>Not available in your region</Trans>}</span> </styledEl.BlockedInfo>apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx (1)
204-212: Consider making the consent message more actionable.The current message "This list requires consent before importing." informs the user but doesn't guide them on how to proceed. When
isListBlockedis true, the ImportListModal hides the import button, potentially leaving users unclear about next steps.This partially addresses a past comment that flagged the message as confusing when it included "Please connect your wallet" (now removed). However, the message could still be enhanced to provide clearer guidance.
🔎 Possible enhancement
Consider adding more context about the consent requirement:
const listBlockReason = - account && requiresConsent ? t`This list requires consent before importing.` : undefined + account && requiresConsent + ? t`This list contains restricted tokens. Please review and accept the consent terms to proceed with importing.` + : undefinedNote: The actual consent flow appears to be handled in the import hooks (useAddListImport), so this message may be shown in edge cases. Verify the complete flow to ensure the message aligns with the user experience.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsxapps/cowswap-frontend/src/modules/tokensList/hooks/useConsentAwareToggleList.tsapps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.tsapps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsxapps/cowswap-frontend/src/modules/tokensList/updaters/BlockedListSourcesUpdater.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/cowswap-frontend/src/modules/tokensList/updaters/BlockedListSourcesUpdater.tsx
- apps/cowswap-frontend/src/modules/tokensList/hooks/useConsentAwareToggleList.ts
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts:27-31
Timestamp: 2025-12-30T18:48:59.430Z
Learning: In apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts, when restrictedLists.isLoaded is false or geoStatus.isLoading is true, the code intentionally proceeds with the import immediately without blocking. This allows imports to proceed during loading states, deferring consent checks to trade time when necessary data isn't yet available.
📚 Learning: 2025-12-30T18:48:59.430Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts:27-31
Timestamp: 2025-12-30T18:48:59.430Z
Learning: In apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts, when restrictedLists.isLoaded is false or geoStatus.isLoading is true, the code intentionally proceeds with the import immediately without blocking. This allows imports to proceed during loading states, deferring consent checks to trade time when necessary data isn't yet available.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsxapps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsxapps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-08-12T06:33:19.348Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6137
File: libs/tokens/src/state/tokens/allTokensAtom.ts:34-65
Timestamp: 2025-08-12T06:33:19.348Z
Learning: In libs/tokens/src/utils/parseTokenInfo.ts, the parseTokenInfo() function returns a new instance of TokenInfo using object spread syntax ({ ...token, ... }), making it safe to mutate properties like lpTokenProvider on the returned object without side effects.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx
📚 Learning: 2025-10-10T20:28:16.565Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 6347
File: apps/cowswap-frontend/src/modules/trade/pure/TradeConfirmation/index.tsx:49-49
Timestamp: 2025-10-10T20:28:16.565Z
Learning: In apps/cowswap-frontend/src/modules/trade, TradeConfirmation follows a two-layer architecture: TradeConfirmationView (pure/stateless) in pure/TradeConfirmation/index.tsx renders the UI, while TradeConfirmation (container) in containers/TradeConfirmation/index.tsx wraps it to freeze props during pending trades (via useStableTradeConfirmationProps), wire in signing state (useSigningStep), and inject trade confirmation state (useTradeConfirmState). Consuming modules should import the container TradeConfirmation from 'modules/trade' to preserve this stateful behavior.
<!-- [add_learning]
When reviewing component refactoring in apps/cowswap-frontend/src/modules/trade, recognize the pattern where a pure view component (e.g., TradeConfirmationView) is separated from a stateful container (e.g., TradeConfirmation) that wraps it. The container adds runtime state management (prop stabilization, signing state, etc.) while the view remains testable and composable. Do not flag usages that import th...
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsxapps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx
📚 Learning: 2025-09-19T11:38:59.206Z
Learnt from: fairlighteth
Repo: cowprotocol/cowswap PR: 6232
File: apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/index.tsx:199-200
Timestamp: 2025-09-19T11:38:59.206Z
Learning: The makeBuildClickEvent function in apps/cowswap-frontend/src/modules/tokensList/pure/ChainsSelector/index.tsx takes five parameters: defaultChainId, contextLabel, mode, isSwapMode, and chainsCount. The chainsCount parameter is used to determine the CrossChain flag in analytics events.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsxapps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx
📚 Learning: 2025-08-08T13:56:18.009Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/updaters/TokensListsUpdater/index.tsx:29-31
Timestamp: 2025-08-08T13:56:18.009Z
Learning: In libs/tokens/src/updaters/TokensListsUpdater/index.tsx, the project’s current Jotai version requires using `unstable_getOnInit` (not `getOnInit`) in atomWithStorage options; keep `{ unstable_getOnInit: true }` until Jotai is upgraded.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx
📚 Learning: 2025-08-08T13:55:17.528Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/state/tokens/allTokensAtom.ts:78-78
Timestamp: 2025-08-08T13:55:17.528Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts (TypeScript/Jotai), the team prefers to wait for token lists to initialize (listsStatesListAtom non-empty) before returning tokens. No fallback to favorites/user-added/native tokens should be used when listsStatesList is empty.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsxapps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsxapps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-10-13T19:41:31.440Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsxapps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-07-18T08:07:55.497Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5992
File: libs/tokens/src/const/tokensList.json:135-167
Timestamp: 2025-07-18T08:07:55.497Z
Learning: Token lists for CoW Swap are maintained in a separate repository at https://github.com/cowprotocol/token-lists, not in the main cowswap repository. Issues related to missing token lists should be tracked in the token-lists repository.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx
📚 Learning: 2025-12-30T18:51:02.867Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useConsentAwareToggleList.ts:38-78
Timestamp: 2025-12-30T18:51:02.867Z
Learning: In apps/cowswap-frontend/src/modules/tokensList/hooks/useConsentAwareToggleList.ts and similar toggle functions, the `enabled` parameter represents the current state of the item (not the desired state). When `enabled === true`, the item is currently enabled and the user is disabling it; when `enabled === false`, the item is currently disabled and the user is enabling it.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx
📚 Learning: 2025-12-30T18:51:02.867Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useConsentAwareToggleList.ts:38-78
Timestamp: 2025-12-30T18:51:02.867Z
Learning: In useConsentAwareToggleList.ts and other similar toggle functions under apps/cowswap-frontend/src/modules/tokensList/hooks, clarify that the 'enabled' parameter represents the current state of the item (not the desired state). When enabled is true, the user is attempting to disable the currently-enabled item; when enabled is false, the user is attempting to enable a currently-disabled item. Ensure the toggle logic uses this current-state semantics (e.g., derive nextState as !enabled) and update comments/tests accordingly to reflect this behavior.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
🧬 Code graph analysis (3)
apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx (1)
libs/tokens/src/types.ts (1)
ListState(39-42)
apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx (4)
apps/cowswap-frontend/src/modules/tokensList/hooks/useRestrictedTokenImportStatus.ts (1)
useRestrictedTokenImportStatus(29-56)apps/cowswap-frontend/src/modules/rwa/hooks/useGeoCountry.ts (1)
useGeoCountry(11-24)libs/tokens/src/hooks/lists/useIsListBlocked.ts (1)
useIsListBlocked(22-43)apps/cowswap-frontend/src/modules/tokensList/pure/ImportListModal/index.tsx (1)
ImportListModal(24-79)
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts (7)
libs/wallet/src/api/hooks.ts (1)
useWalletInfo(24-26)apps/cowswap-frontend/src/modules/rwa/hooks/useGeoStatus.ts (1)
useGeoStatus(10-19)libs/tokens/src/index.ts (2)
restrictedListsAtom(60-60)getSourceAsKey(79-79)libs/tokens/src/state/restrictedTokens/restrictedTokensAtom.ts (1)
restrictedListsAtom(62-62)apps/cowswap-frontend/src/modules/rwa/state/rwaConsentAtom.ts (2)
rwaConsentCacheAtom(8-10)getConsentFromCache(32-45)libs/tokens/src/hooks/lists/useIsListBlocked.ts (1)
getSourceAsKey(6-8)apps/cowswap-frontend/src/modules/rwa/types/rwaConsent.ts (1)
RwaConsentKey(11-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Cypress
- GitHub Check: Setup
🔇 Additional comments (6)
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts (1)
16-61: LGTM! Hook logic is sound and well-integrated.The hook correctly implements the consent requirement logic with appropriate handling for:
- Loading states (defers consent to trade time per project patterns)
- Unknown country scenarios (requires consent when wallet connected)
- Known country scenarios (delegates to blocking logic elsewhere)
- Proper cache lookups using wallet and IPFS hash
Based on learnings, the behavior of allowing imports to proceed during loading states (
requiresConsent: false, isLoading: true) is intentional.apps/cowswap-frontend/src/modules/tokensList/pure/ImportTokenListItem/index.tsx (3)
1-1: LGTM! Imports support the new blocking UI.The
ReactElementtype andAlertCircleicon imports are appropriate for the new blocked-state rendering.Also applies to: 6-6
16-17: LGTM! Optional props maintain backwards compatibility.The
isBlockedandblockReasonprops are correctly typed as optional, allowing existing call sites to continue working without modification.
21-22: LGTM! Function signature improvement.Adding the explicit
ReactElementreturn type enhances type safety and documentation.apps/cowswap-frontend/src/modules/tokensList/containers/SelectTokenWidget/index.tsx (2)
126-133: LGTM: Blocking logic correctly implements geo-restriction and consent requirements.The combined logic properly handles the different scenarios:
- Country blocked: blocks import with region message
- Country unknown + wallet connected: requires consent
- Country unknown + no wallet: allows import (consent deferred to trade time)
Based on learnings and the hook implementations,
isBlockedandrequiresConsentare mutually exclusive, preventing conflicting messages.
157-173: LGTM: Clean refactoring extracts reusable logic.The
selectAndClosehelper properly encapsulates the token selection and modal dismissal flow. The refactoredimportTokenAndClosecorrectly uses this helper for the first imported token.
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
Show resolved
Hide resolved
|
@elena-zh thank you for testing!
5. We have a cache, it's why if you don't open a new incognito tab - you see these tokens
I added filter for that, should work properly
@shoom3301 thank you for the review, added test cases |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts (1)
33-60: Core consent logic is correct and well-structured.The consent determination flow properly implements all PR requirements:
- Restricted lists are identified via
consentHashPerListlookup- When country is known, consent checks are skipped (blocking handled by other hooks)
- When country is unknown and no wallet is connected, consent is deferred to the modal
- When country is unknown and wallet is connected, existing consent is checked via cache
The optional chaining on line 57 (
!existingConsent?.acceptedAt) correctly handles all cases: undefined consent, null consent, or missing/falsyacceptedAtall result inrequiresConsent: true.💡 Optional: enhance comments for future maintainability
Consider clarifying two comments to improve code documentation:
- // If country is known, no consent check needed (blocked check happens elsewhere) + // If country is known, no consent check needed (geo-blocking is enforced by useIsListBlocked and related hooks) if (geoStatus.country) { return { requiresConsent: false, consentHash, isLoading: false } } // Country is unknown - check if consent is given - // If no wallet connected, don't block - the consent modal will handle wallet connection + // If no wallet connected, don't block here - consent modal will prompt for wallet connection when user attempts import if (!account) { return { requiresConsent: false, consentHash, isLoading: false } }These clarifications would help future maintainers understand:
- Where the geo-blocking logic resides
- The user flow when no wallet is connected
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts:27-31
Timestamp: 2025-12-30T18:48:59.430Z
Learning: In apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts, when restrictedLists.isLoaded is false or geoStatus.isLoading is true, the code intentionally proceeds with the import immediately without blocking. This allows imports to proceed during loading states, deferring consent checks to trade time when necessary data isn't yet available.
📚 Learning: 2025-12-30T18:48:59.430Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts:27-31
Timestamp: 2025-12-30T18:48:59.430Z
Learning: In apps/cowswap-frontend/src/modules/tokensList/hooks/useAddListImport.ts, when restrictedLists.isLoaded is false or geoStatus.isLoading is true, the code intentionally proceeds with the import immediately without blocking. This allows imports to proceed during loading states, deferring consent checks to trade time when necessary data isn't yet available.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-12-30T18:51:02.867Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6770
File: apps/cowswap-frontend/src/modules/tokensList/hooks/useConsentAwareToggleList.ts:38-78
Timestamp: 2025-12-30T18:51:02.867Z
Learning: In useConsentAwareToggleList.ts and other similar toggle functions under apps/cowswap-frontend/src/modules/tokensList/hooks, clarify that the 'enabled' parameter represents the current state of the item (not the desired state). When enabled is true, the user is attempting to disable the currently-enabled item; when enabled is false, the user is attempting to enable a currently-disabled item. Ensure the toggle logic uses this current-state semantics (e.g., derive nextState as !enabled) and update comments/tests accordingly to reflect this behavior.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-10-13T19:41:31.440Z
Learnt from: limitofzero
Repo: cowprotocol/cowswap PR: 6351
File: apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts:87-121
Timestamp: 2025-10-13T19:41:31.440Z
Learning: In apps/cowswap-frontend/src/modules/erc20Approve, useApproveCallback returns Promise<TransactionResponse | undefined> and is distinct from useApproveCurrency, which can return Promise<TransactionReceipt | SafeMultisigTransactionResponse>. When reviewing approval flows, verify which hook is actually being used before flagging Safe wallet concerns.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-08-08T13:56:18.009Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/updaters/TokensListsUpdater/index.tsx:29-31
Timestamp: 2025-08-08T13:56:18.009Z
Learning: In libs/tokens/src/updaters/TokensListsUpdater/index.tsx, the project’s current Jotai version requires using `unstable_getOnInit` (not `getOnInit`) in atomWithStorage options; keep `{ unstable_getOnInit: true }` until Jotai is upgraded.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
📚 Learning: 2025-08-08T13:55:17.528Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6125
File: libs/tokens/src/state/tokens/allTokensAtom.ts:78-78
Timestamp: 2025-08-08T13:55:17.528Z
Learning: In libs/tokens/src/state/tokens/allTokensAtom.ts (TypeScript/Jotai), the team prefers to wait for token lists to initialize (listsStatesListAtom non-empty) before returning tokens. No fallback to favorites/user-added/native tokens should be used when listsStatesList is empty.
Applied to files:
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts
🧬 Code graph analysis (1)
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts (7)
libs/wallet/src/api/hooks.ts (1)
useWalletInfo(24-26)apps/cowswap-frontend/src/modules/rwa/hooks/useGeoStatus.ts (1)
useGeoStatus(10-19)libs/tokens/src/index.ts (2)
restrictedListsAtom(60-60)getSourceAsKey(79-79)libs/tokens/src/state/restrictedTokens/restrictedTokensAtom.ts (1)
restrictedListsAtom(62-62)apps/cowswap-frontend/src/modules/rwa/state/rwaConsentAtom.ts (2)
rwaConsentCacheAtom(8-10)getConsentFromCache(32-45)libs/tokens/src/hooks/lists/useIsListBlocked.ts (1)
getSourceAsKey(6-8)apps/cowswap-frontend/src/modules/rwa/types/rwaConsent.ts (1)
RwaConsentKey(11-14)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Setup
- GitHub Check: Cypress
🔇 Additional comments (2)
apps/cowswap-frontend/src/modules/tokensList/hooks/useIsListRequiresConsent.ts (2)
1-13: LGTM! Clean imports and interface definition.The imports are well-organized, and the
ListConsentResultinterface clearly defines the hook's return type. The previous type inconsistency (Boolean vs boolean) has already been addressed.
22-31: Loading-state logic correctly defers consent checks.The hook correctly returns
requiresConsent: falsewithisLoading: truewhen restricted lists or geo data are still loading. This intentional behavior allows imports to proceed during loading states, deferring consent checks until the necessary data is available (typically at trade time).Based on learnings, this pattern is consistent with the design decision to avoid blocking user actions when loading states prevent a definitive consent determination.

Summary
This PR extends the RWA (Real World Assets) consent system to cover token importing flows, in addition to the existing trading flows. It blocks users from importing restricted tokens or token lists when they are in a blocked country.
Resolves this issue.
Key Changes
1. Block Token List Imports for Blocked Countries
2. Block Individual Token Imports for Blocked Countries
3. Hide Blocked Token Lists from UI
4. Consent Flow for Unknown Countries (Wallet Connected)
5. No Blocking for Unknown Countries (No Wallet)
modal with consents for token list

Testing table
To Test
Test restricted token import from blocked country:
Test token list import from blocked country:
Test Manage Lists filtering:
Test import with unknown country + wallet connected:
Test import with unknown country + no wallet:
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.