Skip to content

refactor(swap): bundle optimization#6775

Merged
shoom3301 merged 43 commits intocowprotocol:developfrom
crutch12:refactor/swap-bundle-optimization
Jan 27, 2026
Merged

refactor(swap): bundle optimization#6775
shoom3301 merged 43 commits intocowprotocol:developfrom
crutch12:refactor/swap-bundle-optimization

Conversation

@crutch12
Copy link
Copy Markdown
Contributor

@crutch12 crutch12 commented Dec 28, 2025

Summary

Bundle size optimization for swap.cow.fi (see grant proposal)

Results:

  • initial load size (brotli) 2.104kb -> 1.254kb
  • total bundle size (brotli) 4.52mb -> 3.91mb
  • thx to dynamic imports, dev mode should start faster
Initial loading size before/after

Before
image

After
image

Done

  • @safe-global/api-kit - dynamic import + @safe-global/** new versions (esm support)
  • @1inch/permit-signed-approvals-utils - dynamic import + partial re-export (for better tree-shaking) + new version (esm support) + hardcode used constants
  • use esm instead of cjs for supported "bad configured" deps (e.g. @use-gesture/core and @safe-global/safe-apps-sdk)
  • dedupe bn.js
  • lottie-react - dynamic import
  • framer-motion - dynamic import
  • huge lottie jsons - dynamic import
  • updated a lot of deps to new versions (esm support)
  • eslint rules for added dynamic imports
  • updated contribution docs

Other

Todo

  • testing

Caveats

  • @safe-global/** new versions have slightly different types (e.g. for nonce), there may be problems I couldn't catch (e.g. on the sdk side)

To Test

  • run rimraf node_modules before yarn install usage
  • should work as well as production, but faster

Background

Optional: Give background information for changes you've made, that might be difficult to explain via comments

Summary by CodeRabbit

  • New Features

    • Lazy-loaded animations and motion assets; improved code-splitting for faster initial load.
  • Bug Fixes

    • Fixed Safe transaction nonce handling for more reliable on-chain transaction status.
  • Chores / Refactor

    • Updated Safe and permit-related packages and build configuration to improve bundling and analysis.
  • Documentation

    • Contributor guide expanded with bundle optimization and testing guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 28, 2025

@crutch12 is attempting to deploy a commit to the cow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 28, 2025

Walkthrough

Made lint-rule migrations, migrated Safe/permit integrations to async/dynamic imports, centralized 1inch permit constants, introduced lazy loading for Lottie/framer-motion, adjusted nonce/transaction-hash types to string/BigInt flows, added bundle-stats and chunk naming helpers, and bumped/updated related dependencies.

Changes

Cohort / File(s) Summary
ESLint & lint-rule updates
eslint.config.js, many apps/*/src/** (common/hooks, containers, updaters, modules, storybook, widget-configurator)
Replaced no-restricted-imports with @typescript-eslint/no-restricted-imports; added rules restricting certain imports (permit utils, Safe API, lottie-react, framer-motion) and a no-restricted-syntax entry.
Async SafeApiKit refactor & gnosisSafe
libs/core/src/gnosisSafe/index.ts, apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts, libs/wallet/src/web3-react/updater.ts, apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
SafeApiKit creation/getClient made async with dynamic import; removed runtime provider dependency from several APIs; updated public signatures to async and adjusted cache/type usage.
Permit utils async + central constants
libs/permit-utils/src/lib/getPermitUtilsInstance.ts, libs/permit-utils/src/consts/1inchPermitUtils.ts (new), libs/permit-utils/src/index.ts, libs/permit-utils/src/lib/*, apps/cowswap-frontend/src/modules/permit/*, apps/cowswap-frontend/src/modules/ordersTable/utils/*, apps/cowswap-frontend/src/utils/orderUtils/*
getPermitUtilsInstance now returns Promise and uses dynamic import; introduced oneInchPermitUtilsConsts constants and replaced scattered selector/ABI usages to reference centralized constants.
Nonce / transaction-hash type changes
apps/cowswap-frontend/src/common/types.ts, apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx, apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts, apps/cowswap-frontend/src/modules/onchainTransactions/updaters/*, apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts, apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx
Changed nonce/nonce comparisons to string/BigInt where appropriate; changed EnhancedTransactionDetails.transactionHash to `string
Lazy-loading UI libraries & assets
apps/cowswap-frontend/src/modules/orderProgressBar/pure/*, apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx, related Step/TopSections/FinishedStep files
Replaced eager imports of lottie-react and framer-motion with React.lazy/Suspense and dynamic JSON asset loading (useSWR) with fallback handling.
Safe type/import migrations
*@safe-global/* type import updates across apps/ and libs/ (many files), libs/wallet/src/api/types.ts, libs/wallet/src/api/hooks/useSendBatchTransactions.ts
Switched several imports from @safe-global/safe-core-sdk-types to @safe-global/types-kit and introduced type-only imports for @safe-global/api-kit where applicable.
Bundle tooling & chunk naming
apps/cowswap-frontend/vite.config.mts, tools/formatChunkFileName.ts (new)
Added rollup-plugin-bundle-stats integration, introduced formatChunkFileName helper, adjusted manualChunks and chunkFileNames, extended optimize/resolution options and plugin typing.
Dependency / build updates & patches
.gitignore, apps/cowswap-frontend/package.json, libs/permit-utils/package.json, libs/core/package.json, libs/wallet/package.json, apps/cowswap-frontend/patches/*
Removed analyse.html from .gitignore, bumped @1inch/permit-signed-approvals-utils, updated Safe packages and ethers version spec, added bundle-stats, and updated patch to export Eip2612PermitUtils with nonce resolution change.
Import path consolidation & tsconfig changes
apps/explorer/src/components/**, apps/cowswap-frontend-e2e/tsconfig.json, apps/explorer/tsconfig.json
Replaced deep imports with barrel imports for UI components; removed custom path alias mappings from certain tsconfig files (affects module resolution in those targets).
Misc small changes
apps/cowswap-frontend/src/lib/i18n.tsx, CONTRIBUTING.md, libs/wallet/src/web3-react/connectors/*, apps/cowswap-frontend/src/locales/en-US.po, apps/explorer/vite.config.mts
i18n Provider return type to ReactNode; CONTRIBUTING reworked with bundle-optimization guidance; Trezor imports optimized via Promise.all; some locale entries re-enabled/disabled; BN dedupe in explorer vite config.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant useSafeApiKit
    participant gnosisSafe
    participant SafeApiKit

    rect rgba(200,150,255,0.5)
    Note over Client,SafeApiKit: Old Flow (synchronous provider-based)
    Client->>useSafeApiKit: mount(chainId, provider)
    useSafeApiKit->>gnosisSafe: getSafeTransaction(chainId, hash, provider)
    gnosisSafe->>SafeApiKit: instantiate SafeApiKit with EthAdapter (sync import)
    SafeApiKit-->>gnosisSafe: instance
    gnosisSafe-->>useSafeApiKit: transaction data
    useSafeApiKit-->>Client: update state
    end

    rect rgba(100,200,100,0.5)
    Note over Client,SafeApiKit: New Flow (async dynamic import)
    Client->>useSafeApiKit: mount(chainId)
    useSafeApiKit->>gnosisSafe: getSafeTransaction(chainId, hash)
    gnosisSafe->>gnosisSafe: await _getClientOrThrow(chainId)
    gnosisSafe->>gnosisSafe: await createSafeApiKitInstance(chainId) (dynamic import)
    gnosisSafe->>SafeApiKit: dynamic import + new SafeApiKit(txServiceUrl, chainId)
    SafeApiKit-->>gnosisSafe: instance
    gnosisSafe-->>useSafeApiKit: Promise<transaction data>
    useSafeApiKit-->>Client: update state
    end
Loading
sequenceDiagram
    participant PermitHook
    participant getPermitUtilsInstance
    participant Cache
    participant Eip2612PermitUtils

    rect rgba(200,150,255,0.5)
    Note over PermitHook,Eip2612PermitUtils: Old Flow (sync)
    PermitHook->>getPermitUtilsInstance: call(chainId, provider, account)
    getPermitUtilsInstance->>Cache: check cache
    alt hit
        Cache-->>getPermitUtilsInstance: Eip2612PermitUtils
    else miss
        getPermitUtilsInstance->>Eip2612PermitUtils: new Eip2612PermitUtils(...)
        Eip2612PermitUtils-->>getPermitUtilsInstance: instance
        getPermitUtilsInstance->>Cache: store instance
    end
    getPermitUtilsInstance-->>PermitHook: Eip2612PermitUtils
    PermitHook->>Eip2612PermitUtils: getTokenNonce(...)
    Eip2612PermitUtils-->>PermitHook: nonce
    end

    rect rgba(100,200,100,0.5)
    Note over PermitHook,Eip2612PermitUtils: New Flow (async dynamic import)
    PermitHook->>getPermitUtilsInstance: await call(chainId, provider, account)
    getPermitUtilsInstance->>Cache: check cache
    alt hit
        Cache-->>getPermitUtilsInstance: Promise<Eip2612PermitUtils> | instance
    else miss
        getPermitUtilsInstance->>getPermitUtilsInstance: dynamic import('./imports/1inchPermitUtils')
        getPermitUtilsInstance->>Eip2612PermitUtils: new Eip2612PermitUtils(...)
        Eip2612PermitUtils-->>getPermitUtilsInstance: instance
        getPermitUtilsInstance->>Cache: store instance
    end
    getPermitUtilsInstance-->>PermitHook: Promise<Eip2612PermitUtils>
    PermitHook->>Eip2612PermitUtils: await getTokenNonce(...)
    Eip2612PermitUtils-->>PermitHook: nonce
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

RELEASE

Suggested reviewers

  • elena-zh

Poem

🐇 I hopped through builds and linting rules,

I fetched Safe kits, no provider tools.
I centralized permit bits with care,
Made Lottie nap until load is there.
BigInt and strings now dance in queue—hooray, code's anew!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'refactor(swap): bundle optimization' clearly and concisely summarizes the main change—bundle size optimization for the swap application—which aligns with the extensive refactoring work shown in the changeset.
Description check ✅ Passed The description provides a comprehensive summary of changes, quantified results, detailed methodology (dynamic imports, dependency upgrades, etc.), testing guidance, and caveats. It covers all key template sections except 'To Test' (which is present but minimal) and includes screenshots for documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

}

export function getSafeTransaction(
export async function getSafeTransaction(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new versions of SafeApiKit don't requre Web3Provider

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (7)
apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts (1)

1-1: Consistent lint rule migration.

Same pattern as other files in this PR—correctly migrated to @typescript-eslint/no-restricted-imports.

apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx (1)

1-1: Consistent lint rule migration.

apps/cowswap-frontend/src/common/hooks/useSwapResultsContext.ts (1)

1-1: Consistent lint rule migration.

apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts (1)

1-1: Consistent lint rule migration.

apps/cowswap-frontend/src/common/pure/ReceiveAmount/index.tsx (1)

1-1: Consistent lint rule migration.

apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts (1)

1-1: Consistent lint rule migration.

apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts (1)

1-1: Consistent lint rule migration.

🧹 Nitpick comments (14)
apps/cowswap-frontend/src/lib/i18n.tsx (1)

59-62: Consider prioritizing this TODO to eliminate the initial null render.

This TODO correctly identifies a UX issue where I18nProvider may render null during the initial render. Combined with the potential guard logic issue on lines 54-57, this could result in a flash of missing content for users.

Possible solutions:

  • Pre-load the default locale messages before the first render (as suggested in the TODO).
  • Ensure the synchronous guard on line 54 works correctly to activate the default locale immediately.
  • Add a loading state/skeleton instead of rendering null.
apps/cowswap-frontend/src/modules/ordersTable/hooks/useNoOrdersAnimation.ts (1)

5-5: Consider using type-only import.

LottieComponentProps is only used in type positions (line 17, 18). Using import type would be more explicit and could help with tree-shaking:

-import { LottieComponentProps } from 'lottie-react'
+import type { LottieComponentProps } from 'lottie-react'

However, if this change was intentional due to module resolution issues with lottie-react, please disregard.

apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts (1)

91-95: BigInt comparison logic is correct but guard differs from similar code.

The logic correctly identifies replaced Safe transactions. Note that in checkSafeTransaction.ts (line 26), the guard uses typeof safeNonce === 'string', while here it uses a truthy check safeNonce &&.

If safeNonce could be a number (from GnosisSafeInfo), the BigInt conversion will still work correctly. However, consider aligning the guard style for consistency:

-          const isOrderTxReplaced = !!(
-            safeNonce &&
-            BigInt(safeTransaction.nonce) < BigInt(safeNonce) &&
-            !safeTransaction.isExecuted
-          )
+          const isOrderTxReplaced = !!(
+            typeof safeNonce !== 'undefined' &&
+            BigInt(safeTransaction.nonce) < BigInt(safeNonce) &&
+            !safeTransaction.isExecuted
+          )
libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts (1)

81-82: Use Buffer.from() instead of deprecated new Buffer() constructor.

The Buffer constructor with string arguments is deprecated and will show warnings. Consider updating these lines while making changes to this file:

🔎 Proposed fix
-  hdKey.publicKey = new Buffer(payload.publicKey, 'hex')
-  hdKey.chainCode = new Buffer(payload.chainCode, 'hex')
+  hdKey.publicKey = Buffer.from(payload.publicKey, 'hex')
+  hdKey.chainCode = Buffer.from(payload.chainCode, 'hex')
libs/permit-utils/src/consts/1inchPermitUtils.ts (1)

1-68: LGTM! Well-documented rationale for hardcoding these constants.

The approach of extracting stable constants from an archived library is sensible for bundle optimization. The permit selectors and typehash are cryptographic constants tied to EIP-2612 specifications and won't change.

Consider adding as const to the ABI array for stricter typing if consumers need literal types:

-export const DAI_EIP_2612_PERMIT_ABI = [
+export const DAI_EIP_2612_PERMIT_ABI = [
   {
     // ...
   },
-]
+] as const
eslint.config.js (1)

149-155: Clarify the error message for the dynamic import restriction.

The no-restricted-syntax rule blocks dynamic imports (import(...)) from @1inch/permit-signed-approvals-utils, but the message says "Please import dynamically from @cowprotocol/permit-utils". This could be confusing since you're blocking dynamic imports, not encouraging them.

Consider rewording to clarify that developers should use the @cowprotocol/permit-utils wrapper instead:

🔎 Suggested fix
       'no-restricted-syntax': [
         'error',
         {
           selector: 'ImportExpression[source.value="@1inch/permit-signed-approvals-utils"]',
-          message: 'Please import dynamically from @cowprotocol/permit-utils',
+          message: 'Please use @cowprotocol/permit-utils instead, which provides optimized dynamic imports',
         },
       ],
apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx (1)

40-47: Consider a loading skeleton fallback instead of null.

The null fallback means users see nothing while the Lottie animation loads. For a better UX, consider a lightweight placeholder (e.g., a static checkmark icon or a small spinner) to avoid layout shift.

apps/cowswap-frontend/src/modules/orderProgressBar/pure/StepComponent.tsx (1)

42-50: Consider a fallback for the Suspense boundary.

The null fallback means users see nothing while the cancellation animation loads. Since this is a cancellation state, consider showing a simple static icon (e.g., an "X" or spinner) to provide immediate visual feedback during the lazy load.

libs/permit-utils/src/imports/1inchPermitUtils.ts (1)

1-10: LGTM! Good selective re-export pattern for bundle optimization.

The documentation clearly explains the rationale (642kb → 256kb reduction), and the ESLint disable is appropriate since this is the designated entry point for the dynamic import.

Minor typo in line 4: "dymaic" should be "dynamic".

🔎 Optional fix for typo
- * It uses esm, but dymaic import breaks tree shaking, so we re-export here only used variables (642kb -> 256kb).
+ * It uses esm, but dynamic import breaks tree shaking, so we re-export here only used variables (642kb -> 256kb).
apps/cowswap-frontend/src/modules/orderProgressBar/pure/TopSections.tsx (1)

52-58: Consider loading states for better UX.

Both components return null while the Lottie assets are loading. This could cause layout shifts or brief empty states in the UI. Consider whether a skeleton or placeholder would provide a smoother user experience, especially on slower connections.

Also applies to: 92-98

tools/formatChunkFileName.ts (1)

8-17: Consider edge case where derived name becomes empty.

If the path after the key consists only of segments like index, dist, node_modules, or browser, the name variable could become an empty string (or just -), resulting in filenames like static/page--[hash].js.

🔎 Proposed fix to handle empty name
       const name = splitted[splitted.length - 1]
         .replace(/\/(index|dist|node_modules|browser)/g, '')
         .replace(/\.(tsx?|jsx?|mjs|mts|cjs)$/, '')
         .replace(/\//g, '-')
+        .replace(/^-+|-+$/g, '') // trim leading/trailing hyphens

+      if (!name) return undefined // fallback to default naming
+
       return chunkGroups[key].replace(/\[name\]/g, name)
libs/permit-utils/src/lib/getPermitUtilsInstance.ts (1)

17-51: Potential race condition during concurrent initial calls.

If multiple callers invoke getPermitUtilsInstance simultaneously before the cache is populated, each will proceed to create a new instance (due to the await import()), potentially resulting in multiple instances being created and only the last one being cached. This is a minor concern since the instances are functionally equivalent, but it wastes resources.

🔎 Optional fix using a pending promise cache
+const PENDING_CACHE = new Map<string, Promise<Eip2612PermitUtils>>()
+
 export async function getPermitUtilsInstance(
   chainId: number,
   provider: JsonRpcProvider,
   account?: string | undefined,
 ): Promise<Eip2612PermitUtils> {
   const chainCache = CHAIN_UTILS_CACHE.get(chainId)
 
   if (!account && chainCache) {
     return chainCache
   }
   const providerCacheKey = `${chainId}-${account}`
   const providerCache = PROVIDER_UTILS_CACHE.get(providerCacheKey)
 
   if (providerCache) {
     return providerCache
   }
 
+  const cacheKey = account ? providerCacheKey : `chain-${chainId}`
+  const pending = PENDING_CACHE.get(cacheKey)
+  if (pending) return pending
+
+  const promise = (async () => {
     const web3ProviderConnector = new PermitProviderConnector(provider, account ? undefined : PERMIT_SIGNER)
     const Eip2612PermitUtilsClass = await import('../imports/1inchPermitUtils').then((r) => r.Eip2612PermitUtils)
-  const eip2612PermitUtils = new Eip2612PermitUtilsClass(web3ProviderConnector, { enabledCheckSalt: true })
+    return new Eip2612PermitUtilsClass(web3ProviderConnector, { enabledCheckSalt: true })
+  })()
+
+  PENDING_CACHE.set(cacheKey, promise)
+  const eip2612PermitUtils = await promise
+  PENDING_CACHE.delete(cacheKey)
libs/core/src/gnosisSafe/index.ts (1)

24-37: Same race condition concern as in permit utils.

Similar to getPermitUtilsInstance, concurrent calls to _getClient before the cache is populated could result in multiple SafeApiKit instances being created. Given this is a heavier module with network-related setup, consider adding a pending promise cache.

🔎 Optional fix using pending promise pattern
+const PENDING_CLIENTS = new Map<number, Promise<SafeApiKitType | null>>()
+
 async function _getClient(chainId: number): Promise<SafeApiKitType | null> {
   const cachedClient = SAFE_TRANSACTION_SERVICE_CACHE[chainId]
 
   if (cachedClient !== undefined) {
     return cachedClient
   }
 
+  const pending = PENDING_CLIENTS.get(chainId)
+  if (pending) return pending
+
+  const promise = createSafeApiKitInstance(chainId)
+  PENDING_CLIENTS.set(chainId, promise)
+
-  const client = await createSafeApiKitInstance(chainId)
+  const client = await promise
+  PENDING_CLIENTS.delete(chainId)
 
   // Add client to cache (or null if unknown network)
   SAFE_TRANSACTION_SERVICE_CACHE[chainId] = client
 
   return client
 }
apps/cowswap-frontend/vite.config.mts (1)

185-185: Update or remove the outdated comment about @1inch.

The comment // was used by @1inch is misleading—the web3 package is actively used in the codebase (imported in explorer utilities), and this manual chunk configuration helps ensure it bundles correctly. Either remove the comment entirely or clarify its actual purpose if there's a specific reason for this chunking strategy.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3a013fb and 012a863.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (92)
  • .gitignore
  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx
  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/types.ts
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/index.tsx
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts
  • apps/cowswap-frontend/src/common/hooks/useConvertUsdToTokenValue.ts
  • apps/cowswap-frontend/src/common/hooks/useEnhancedActivityDerivedState.ts
  • apps/cowswap-frontend/src/common/hooks/useGetMarketDimension.ts
  • apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts
  • apps/cowswap-frontend/src/common/hooks/useNavigate.ts
  • apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.tsx
  • apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts
  • apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeContext.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapResultsContext.ts
  • apps/cowswap-frontend/src/common/pure/CoWAmmBannerContent/index.tsx
  • apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/ConfirmationPendingContentShell.tsx
  • apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx
  • apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts
  • apps/cowswap-frontend/src/common/pure/ExecutionPrice/hooks/useExecutionPriceFiat.ts
  • apps/cowswap-frontend/src/common/pure/ReceiveAmount/index.tsx
  • apps/cowswap-frontend/src/common/pure/ReceiveAmountInfo/index.tsx
  • apps/cowswap-frontend/src/common/types.ts
  • apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/WidgetTokensUpdater.tsx
  • apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/OrdersFromApiUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater/hooks/useUpdateIsUnfillableFlag.ts
  • apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater/updaters/UnfillableOrderUpdater.ts
  • apps/cowswap-frontend/src/common/utils/doesOrderHavePermit.ts
  • apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
  • apps/cowswap-frontend/src/legacy/state/enhancedTransactions/actions.ts
  • apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts
  • apps/cowswap-frontend/src/legacy/state/orders/actions.ts
  • apps/cowswap-frontend/src/lib/i18n.tsx
  • apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveButton/TradeApproveButton.tsx
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveAndSwap.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveCurrency.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/utils/getIsTradeApproveResult.ts
  • apps/cowswap-frontend/src/modules/limitOrders/services/safeBundleFlow/index.ts
  • apps/cowswap-frontend/src/modules/onchainTransactions/updaters/FinalizeTxUpdater/services/checkSafeTransaction.ts
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/LottieContainer.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/RenderProgressTopSection.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/StepComponent.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/TopSections.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useNoOrdersAnimation.ts
  • apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/pure/ReceiptModal/fields/SafeTxFields.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/utils/checkPermitNonceAndAmount.ts
  • apps/cowswap-frontend/src/modules/ordersTable/utils/extractPermitData.ts
  • apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts
  • apps/cowswap-frontend/src/modules/permit/hooks/useGetCachedPermit.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleApprovalFlow.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts
  • apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
  • apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.ts
  • apps/cowswap-frontend/src/modules/twap/services/extensibleFallbackSetupTxs.ts
  • apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
  • apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx
  • apps/cowswap-frontend/src/modules/zeroApproval/hooks/useZeroApprove.ts
  • apps/cowswap-frontend/src/utils/orderUtils/getOrderPermitAmount.test.ts
  • apps/cowswap-frontend/src/utils/orderUtils/isPermitValidForOrder.ts
  • apps/cowswap-frontend/vite.config.mts
  • apps/explorer/src/storybook/decorators.tsx
  • apps/widget-configurator/src/app/embedDialog/index.tsx
  • eslint.config.js
  • libs/core/src/gnosisSafe/index.ts
  • libs/permit-utils/README.md
  • libs/permit-utils/src/consts/1inchPermitUtils.ts
  • libs/permit-utils/src/imports/1inchPermitUtils.ts
  • libs/permit-utils/src/index.ts
  • libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts
  • libs/permit-utils/src/lib/getPermitUtilsInstance.ts
  • libs/permit-utils/src/lib/getTokenPermitInfo.ts
  • libs/permit-utils/src/utils/PermitProviderConnector.ts
  • libs/permit-utils/src/utils/buildPermitCallData.ts
  • libs/wallet/src/api/hooks/useSendBatchTransactions.ts
  • libs/wallet/src/api/types.ts
  • libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts
  • libs/wallet/src/web3-react/connectors/TrezorConnector/index.ts
  • libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts
  • libs/wallet/src/web3-react/updater.ts
  • package.json
  • tools/formatChunkFileName.ts
💤 Files with no reviewable changes (1)
  • .gitignore
🧰 Additional context used
🧠 Learnings (21)
📓 Common learnings
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5443
File: apps/cowswap-frontend/src/modules/swap/containers/ConfirmSwapModalSetup/index.tsx:71-71
Timestamp: 2025-02-20T15:59:33.749Z
Learning: The swap module in apps/cowswap-frontend/src/modules/swap/ is marked for deletion in PR #5444 as part of the swap widget unification effort.
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.
📚 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/legacy/state/orders/actions.ts
  • apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
  • apps/cowswap-frontend/src/modules/limitOrders/services/safeBundleFlow/index.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveAndSwap.ts
  • apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
  • apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts
  • apps/cowswap-frontend/src/modules/onchainTransactions/updaters/FinalizeTxUpdater/services/checkSafeTransaction.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveButton/TradeApproveButton.tsx
  • apps/cowswap-frontend/src/legacy/state/enhancedTransactions/actions.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleApprovalFlow.ts
  • apps/cowswap-frontend/src/modules/ordersTable/utils/checkPermitNonceAndAmount.ts
  • apps/cowswap-frontend/src/modules/ordersTable/utils/extractPermitData.ts
  • apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
  • apps/cowswap-frontend/src/modules/permit/hooks/useGetCachedPermit.ts
  • apps/cowswap-frontend/src/modules/twap/services/extensibleFallbackSetupTxs.ts
  • libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts
  • libs/wallet/src/api/hooks/useSendBatchTransactions.ts
  • apps/cowswap-frontend/src/common/hooks/useConvertUsdToTokenValue.ts
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
  • libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveCurrency.ts
  • apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/utils/getIsTradeApproveResult.ts
  • apps/cowswap-frontend/src/modules/zeroApproval/hooks/useZeroApprove.ts
  • apps/cowswap-frontend/src/utils/orderUtils/isPermitValidForOrder.ts
  • apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts
  • libs/core/src/gnosisSafe/index.ts
📚 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/legacy/state/orders/actions.ts
  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
  • apps/cowswap-frontend/src/common/pure/ReceiveAmountInfo/index.tsx
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/index.tsx
  • apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
  • apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.tsx
  • apps/cowswap-frontend/src/common/pure/ConfirmationPendingContent/ConfirmationPendingContentShell.tsx
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeContext.ts
  • apps/cowswap-frontend/src/modules/limitOrders/services/safeBundleFlow/index.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveAndSwap.ts
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/StepComponent.tsx
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/TopSections.tsx
  • apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts
  • apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
  • apps/cowswap-frontend/src/common/pure/ReceiveAmount/index.tsx
  • apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts
  • apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveButton/TradeApproveButton.tsx
  • apps/cowswap-frontend/src/legacy/state/enhancedTransactions/actions.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleApprovalFlow.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/RenderProgressTopSection.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/LottieContainer.tsx
  • apps/cowswap-frontend/src/modules/twap/services/extensibleFallbackSetupTxs.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
  • apps/cowswap-frontend/src/common/hooks/useGetMarketDimension.ts
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveCurrency.ts
  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/types.ts
  • apps/cowswap-frontend/src/modules/erc20Approve/utils/getIsTradeApproveResult.ts
  • apps/cowswap-frontend/src/modules/zeroApproval/hooks/useZeroApprove.ts
  • apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx
  • apps/cowswap-frontend/src/modules/twap/services/createTwapOrderTxs.ts
  • apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts
📚 Learning: 2025-08-05T14:27:05.023Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5992
File: libs/wallet/src/web3-react/utils/switchChain.ts:36-38
Timestamp: 2025-08-05T14:27:05.023Z
Learning: In libs/wallet/src/web3-react/utils/switchChain.ts, the team prefers using Record<SupportedChainId, string | null> over Partial<Record<SupportedChainId, string>> for WALLET_RPC_SUGGESTION to enforce that all supported chain IDs have explicit values set, even if some might be null. This ensures compile-time completeness checking.

Applied to files:

  • apps/cowswap-frontend/src/legacy/state/orders/actions.ts
  • apps/cowswap-frontend/src/modules/twap/services/fetchTwapOrdersFromSafe.ts
  • apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.tsx
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeContext.ts
  • apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
  • apps/cowswap-frontend/src/common/hooks/useEnhancedActivityDerivedState.ts
  • libs/wallet/src/web3-react/updater.ts
  • apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
  • libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
  • apps/cowswap-frontend/src/common/hooks/useConvertUsdToTokenValue.ts
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
  • libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts
  • libs/wallet/src/api/types.ts
  • apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts
  • apps/cowswap-frontend/src/modules/zeroApproval/hooks/useZeroApprove.ts
  • apps/cowswap-frontend/src/utils/orderUtils/isPermitValidForOrder.ts
  • apps/cowswap-frontend/src/legacy/state/enhancedTransactions/reducer.ts
  • libs/core/src/gnosisSafe/index.ts
📚 Learning: 2025-07-24T16:42:53.154Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6009
File: apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/HighFeeWarningTooltipContent.tsx:23-33
Timestamp: 2025-07-24T16:42:53.154Z
Learning: In apps/cowswap-frontend/src/modules/tradeWidgetAddons/containers/HighFeeWarning/HighFeeWarningTooltipContent.tsx, the use of toFixed(2) for percentage formatting in tooltip content is intentional and differs from the banner message formatting that uses toSignificant(2, undefined, Rounding.ROUND_DOWN). This formatting difference serves different UX purposes and should not be flagged as inconsistent.

Applied to files:

  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx
  • apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx
  • apps/cowswap-frontend/src/common/pure/ExecutionPrice/hooks/useExecutionPriceFiat.ts
  • apps/cowswap-frontend/src/common/hooks/useConvertUsdToTokenValue.ts
📚 Learning: 2025-09-11T08:25:51.460Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 6234
File: libs/tokens/src/index.ts:1-4
Timestamp: 2025-09-11T08:25:51.460Z
Learning: In the cowprotocol/cowswap project, there is currently no SSR (Server-Side Rendering) support, so localStorage access at module import time does not cause SSR-related issues.

Applied to files:

  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/index.tsx
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/index.tsx
  • apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.tsx
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeContext.ts
  • apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/TopSections.tsx
  • apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/CurrencyInputPanel.tsx
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts
  • apps/cowswap-frontend/src/common/hooks/useGetSurplusFiatValue.ts
  • apps/cowswap-frontend/src/common/hooks/useEnhancedActivityDerivedState.ts
  • apps/cowswap-frontend/src/common/updaters/orders/CancelledOrdersUpdater.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
  • apps/cowswap-frontend/src/common/hooks/useRateInfoParams.ts
  • apps/cowswap-frontend/src/common/hooks/useConvertUsdToTokenValue.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapResultsContext.ts
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
  • apps/cowswap-frontend/src/common/updaters/WidgetTokensUpdater.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx
📚 Learning: 2025-08-12T05:57:08.021Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6138
File: libs/hook-dapp-lib/src/hookDappsRegistry.ts:1-1
Timestamp: 2025-08-12T05:57:08.021Z
Learning: The matchHooksToDapps function in libs/hook-dapp-lib/src/utils.ts provides backward compatibility for permit hooks through function selector detection (EIP_2612_PERMIT_SELECTOR and DAI_PERMIT_SELECTOR) rather than dappId matching, making it robust against dappId changes.

Applied to files:

  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
  • apps/cowswap-frontend/src/common/hooks/useOnSelectNetwork.tsx
  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveAndSwap.ts
  • apps/cowswap-frontend/src/common/utils/doesOrderHavePermit.ts
  • libs/permit-utils/src/consts/1inchPermitUtils.ts
  • apps/cowswap-frontend/src/modules/ordersTable/utils/checkPermitNonceAndAmount.ts
  • apps/cowswap-frontend/src/modules/ordersTable/utils/extractPermitData.ts
  • apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
  • apps/cowswap-frontend/src/modules/permit/hooks/useGetCachedPermit.ts
  • libs/permit-utils/src/lib/getPermitUtilsInstance.ts
  • libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts
  • libs/permit-utils/src/imports/1inchPermitUtils.ts
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
  • libs/wallet/src/web3-react/hooks/useSafeAppsSdk.ts
  • libs/permit-utils/README.md
  • libs/permit-utils/src/lib/getTokenPermitInfo.ts
  • libs/permit-utils/src/utils/PermitProviderConnector.ts
  • libs/permit-utils/src/utils/buildPermitCallData.ts
  • apps/cowswap-frontend/src/utils/orderUtils/isPermitValidForOrder.ts
  • apps/cowswap-frontend/src/utils/orderUtils/getOrderPermitAmount.test.ts
  • apps/cowswap-frontend/src/modules/permit/hooks/useGeneratePermitHook.ts
📚 Learning: 2025-09-25T08:49:32.256Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:62-67
Timestamp: 2025-09-25T08:49:32.256Z
Learning: In the cowswap-frontend codebase, when testing hooks that use multiple bridge providers, both providers are always properly mocked as complete jest.Mocked<BridgeProvider<BridgeQuoteResult>> objects with all required methods stubbed, ensuring no undefined returns that could break the hook logic.

Applied to files:

  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/HookItem/index.tsx
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeContext.ts
  • apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
📚 Learning: 2025-06-16T15:58:00.268Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5830
File: apps/cowswap-frontend/src/modules/trade/containers/TradeWidget/index.tsx:1-2
Timestamp: 2025-06-16T15:58:00.268Z
Learning: JSX can be imported as a named export from React in modern React versions (React 17+). The import `import { JSX } from 'react'` is valid and does not cause compilation errors.

Applied to files:

  • apps/cowswap-frontend/src/common/pure/ReceiveAmountInfo/index.tsx
  • apps/cowswap-frontend/src/common/pure/CoWAmmBannerContent/index.tsx
  • apps/cowswap-frontend/src/common/pure/ReceiveAmount/index.tsx
  • apps/cowswap-frontend/src/common/pure/CurrencyInputPanel/types.ts
  • eslint.config.js
📚 Learning: 2025-09-25T08:48:53.495Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 6299
File: apps/cowswap-frontend/src/entities/bridgeProvider/useBridgeSupportedNetworks.test.tsx:58-60
Timestamp: 2025-09-25T08:48:53.495Z
Learning: In the cowswap-frontend codebase, when writing SWR tests, the team prefers maximum test isolation by using `provider: () => new Map()` in SWRConfig wrappers, even if it recreates cache on every render, to ensure tests don't share any state.

Applied to files:

  • apps/cowswap-frontend/src/common/containers/OrderHooksDetails/index.tsx
  • apps/cowswap-frontend/src/common/hooks/useEnhancedActivityDerivedState.ts
  • apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
📚 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/common/hooks/useOnSelectNetwork.tsx
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeContext.ts
  • apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
  • apps/cowswap-frontend/src/common/hooks/useEnhancedActivityDerivedState.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
  • apps/cowswap-frontend/src/common/hooks/useConvertUsdToTokenValue.ts
📚 Learning: 2025-04-02T09:58:29.374Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5549
File: apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts:152-152
Timestamp: 2025-04-02T09:58:29.374Z
Learning: In the `safeBundleEthFlow` function, `account` is guaranteed to be truthy based on the type system (`PostOrderParams` defines it as a required string) and the context in which the function is called, so additional runtime checks are unnecessary.

Applied to files:

  • apps/cowswap-frontend/src/modules/limitOrders/services/safeBundleFlow/index.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts
  • apps/cowswap-frontend/src/modules/onchainTransactions/updaters/FinalizeTxUpdater/services/checkSafeTransaction.ts
  • apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleApprovalFlow.ts
  • libs/wallet/src/web3-react/updater.ts
  • apps/cowswap-frontend/src/modules/ordersTable/utils/checkPermitNonceAndAmount.ts
📚 Learning: 2025-02-20T15:59:33.749Z
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5443
File: apps/cowswap-frontend/src/modules/swap/containers/ConfirmSwapModalSetup/index.tsx:71-71
Timestamp: 2025-02-20T15:59:33.749Z
Learning: The swap module in apps/cowswap-frontend/src/modules/swap/ is marked for deletion in PR #5444 as part of the swap widget unification effort.

Applied to files:

  • apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveAndSwap.ts
  • apps/cowswap-frontend/src/modules/twap/services/cancelTwapOrderTxs.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapAndBridgeOverview.ts
  • apps/cowswap-frontend/src/common/hooks/useSwapResultsContext.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/common/updaters/orders/UnfillableOrdersUpdater/hooks/useUpdateIsUnfillableFlag.ts
  • apps/cowswap-frontend/src/common/updaters/orders/OrdersFromApiUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts
  • libs/wallet/src/web3-react/updater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater/updaters/UnfillableOrderUpdater.ts
  • libs/permit-utils/src/lib/getTokenPermitInfo.ts
  • apps/cowswap-frontend/src/common/updaters/WidgetTokensUpdater.tsx
  • apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts
  • apps/cowswap-frontend/src/modules/twap/updaters/TwapOrdersUpdater.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/common/updaters/orders/UnfillableOrdersUpdater/hooks/useUpdateIsUnfillableFlag.ts
  • apps/cowswap-frontend/src/common/updaters/orders/OrdersFromApiUpdater.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useSendOnChainCancellation.ts
  • apps/cowswap-frontend/src/common/hooks/useCancelOrder/useGetOnChainCancellation.ts
  • apps/cowswap-frontend/src/common/updaters/orders/SpotPricesUpdater.ts
  • apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater/updaters/UnfillableOrderUpdater.ts
  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/types.ts
  • apps/cowswap-frontend/src/common/updaters/orders/PendingOrdersUpdater.ts
📚 Learning: 2025-06-16T16:01:46.729Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5831
File: apps/cowswap-frontend/src/modules/application/containers/AppMenu/index.tsx:7-9
Timestamp: 2025-06-16T16:01:46.729Z
Learning: React Router v7 restructured packages - NavLink and other core routing components should be imported from 'react-router' (not 'react-router-dom'). In v7, 'react-router-dom' mainly re-exports for backward compatibility, while 'react-router' is the new preferred import path for most components.

Applied to files:

  • apps/cowswap-frontend/src/common/hooks/useNavigate.ts
  • eslint.config.js
📚 Learning: 2025-06-16T16:01:46.729Z
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5831
File: apps/cowswap-frontend/src/modules/application/containers/AppMenu/index.tsx:7-9
Timestamp: 2025-06-16T16:01:46.729Z
Learning: In React Router v6+, NavLink can be imported directly from 'react-router' package, not just 'react-router-dom'. The package structure has evolved and the import from 'react-router' is valid for the latest versions.

Applied to files:

  • apps/cowswap-frontend/src/common/hooks/useNavigate.ts
📚 Learning: 2025-09-24T14:52:37.874Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6285
File: apps/cowswap-frontend/src/modules/swap/updaters/index.tsx:49-53
Timestamp: 2025-09-24T14:52:37.874Z
Learning: UnfillableOrdersUpdater instances can be safely mounted in multiple locations (SwapUpdaters and OrdersTableWidget) because they use window visibility checks to prevent simultaneous network calls, ensuring only one instance makes API requests at a time.

Applied to files:

  • apps/cowswap-frontend/src/common/updaters/orders/UnfillableOrdersUpdater/updaters/UnfillableOrderUpdater.ts
📚 Learning: 2025-12-03T19:23:35.789Z
Learnt from: kernelwhisperer
Repo: cowprotocol/cowswap PR: 6610
File: apps/cowswap-frontend/project.json:38-39
Timestamp: 2025-12-03T19:23:35.789Z
Learning: In the cowswap-frontend project configuration (apps/cowswap-frontend/project.json), the Vite dev server option `"host": true` is set to support Windows + WSL development environments, where binding to all network interfaces is required for the Windows host to access the dev server running in WSL.

Applied to files:

  • apps/cowswap-frontend/vite.config.mts
📚 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/common/containers/CoWAmmBanner/types.ts
  • libs/permit-utils/src/lib/getTokenPermitInfo.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/state/tokens/allTokensAtom.ts, the parseTokenInfo() function returns a new instance of TokenInfo each time, making it safe to mutate properties like lpTokenProvider on the returned object without side effects.

Applied to files:

  • apps/cowswap-frontend/src/common/containers/CoWAmmBanner/types.ts
  • libs/permit-utils/src/lib/getTokenPermitInfo.ts
🧬 Code graph analysis (12)
apps/cowswap-frontend/src/modules/onchainTransactions/updaters/FinalizeTxUpdater/services/checkSafeTransaction.ts (1)
apps/cowswap-frontend/src/modules/onchainTransactions/updaters/FinalizeTxUpdater/services/handleTransactionReplacement.ts (1)
  • handleTransactionReplacement (8-18)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/RenderProgressTopSection.tsx (3)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/ProgressSkeleton.tsx (1)
  • ProgressSkeleton (71-90)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/styled.ts (1)
  • ProgressTopSection (75-92)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/ProgressTopSection/index.tsx (1)
  • ProgressTopSection (32-95)
libs/wallet/src/web3-react/updater.ts (1)
libs/core/src/gnosisSafe/index.ts (1)
  • getSafeInfo (81-90)
apps/cowswap-frontend/src/modules/ordersTable/utils/checkPermitNonceAndAmount.ts (2)
libs/permit-utils/src/index.ts (1)
  • getPermitUtilsInstance (5-5)
libs/permit-utils/src/lib/getPermitUtilsInstance.ts (1)
  • getPermitUtilsInstance (17-51)
apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts (3)
libs/wallet/src/api/hooks.ts (1)
  • useWalletInfo (24-26)
libs/core/src/gnosisSafe/index.ts (2)
  • getSafeInfo (81-90)
  • getSafeTransaction (71-79)
apps/explorer/src/utils/miscellaneous.ts (1)
  • retry (120-138)
tools/formatChunkFileName.ts (1)
apps/cowswap-frontend/public/emergency.js (1)
  • key (22-22)
libs/permit-utils/src/lib/checkIsCallDataAValidPermit.ts (2)
libs/permit-utils/src/imports/1inchPermitUtils.ts (1)
  • Eip2612PermitUtils (10-10)
libs/permit-utils/src/types.ts (1)
  • PermitInfo (8-13)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx (1)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/styled.ts (1)
  • TransactionStatus (262-291)
apps/cowswap-frontend/vite.config.mts (1)
tools/formatChunkFileName.ts (1)
  • formatChunkFileName (3-20)
apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts (3)
libs/wallet/src/api/hooks.ts (1)
  • useWalletInfo (24-26)
libs/wallet/src/web3-react/hooks/useWalletMetadata.ts (1)
  • useIsSafeWallet (133-135)
libs/core/src/gnosisSafe/index.ts (1)
  • createSafeApiKitInstance (39-48)
libs/permit-utils/src/lib/getTokenPermitInfo.ts (2)
libs/permit-utils/src/index.ts (1)
  • getPermitUtilsInstance (5-5)
libs/permit-utils/src/lib/getPermitUtilsInstance.ts (1)
  • getPermitUtilsInstance (17-51)
apps/cowswap-frontend/src/lib/i18n.tsx (2)
jest.setup.ts (1)
  • i18n (51-51)
libs/common-const/src/locales.ts (1)
  • DEFAULT_LOCALE (10-10)
🪛 Biome (2.1.2)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/LottieContainer.tsx

[error] 65-65: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)

apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx

[error] 39-39: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)

apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx

[error] 107-107: Wrap comments inside children within braces.

Unsafe fix: Wrap the comments with braces

(lint/suspicious/noCommentText)

⏰ 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

Comment thread apps/cowswap-frontend/src/lib/i18n.tsx
Comment thread apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx Outdated
Comment thread libs/wallet/src/web3-react/updater.ts Outdated
threshold,
owners,
nonce,
nonce: String(nonce),
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Dec 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Verify nonce type consistency across both code paths.

Line 95 explicitly converts nonce to a string when using the Safe Apps SDK, but line 114 assigns nonce directly from the getSafeInfo API without conversion. This inconsistency could cause type mismatches in the GnosisSafeInfo object if the two sources return different types.

Given that the PR migrates to new @safe-global/** versions with type changes, ensure both paths produce the same nonce type. Consider applying String() conversion on line 114 as well, or verify that both APIs return string values.

🔎 Proposed fix to ensure consistent nonce type handling
            const _safeInfo = await getSafeInfo(chainId, account)
            const { address, threshold, owners, nonce } = _safeInfo
            setSafeInfo((prevSafeInfo) => ({
              ...prevSafeInfo,
              chainId,
              address,
              threshold,
              owners,
-             nonce,
+             nonce: String(nonce),
              isReadOnly: false,
            }))

Also applies to: 114-114

🤖 Prompt for AI Agents
In libs/wallet/src/web3-react/updater.ts around lines 95 and 114, the nonce is
explicitly converted to a string at line 95 but assigned raw at line 114,
causing inconsistent types in the GnosisSafeInfo object; make the nonce type
consistent by converting the value at line 114 to a string (e.g., wrap with
String(...) or otherwise coerce to string) so both code paths produce the same
nonce type and update any related typings if necessary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's intended

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crutch12, understood! Thank you for clarifying. If the Safe Apps SDK returns a number while the getSafeInfo API returns a string in the new version, then the different handling makes sense. Appreciate the confirmation! 👍


🧠 Learnings used
Learnt from: alfetopito
Repo: cowprotocol/cowswap PR: 5992
File: libs/wallet/src/web3-react/utils/switchChain.ts:36-38
Timestamp: 2025-08-05T14:27:05.023Z
Learning: In libs/wallet/src/web3-react/utils/switchChain.ts, the team prefers using Record<SupportedChainId, string | null> over Partial<Record<SupportedChainId, string>> for WALLET_RPC_SUGGESTION to enforce that all supported chain IDs have explicit values set, even if some might be null. This ensures compile-time completeness checking.

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.

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.

Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5549
File: apps/cowswap-frontend/src/modules/tradeFlow/services/safeBundleFlow/safeBundleEthFlow.ts:152-152
Timestamp: 2025-04-02T09:58:29.374Z
Learning: In the `safeBundleEthFlow` function, `account` is guaranteed to be truthy based on the type system (`PostOrderParams` defines it as a required string) and the context in which the function is called, so additional runtime checks are unnecessary.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
apps/cowswap-frontend/src/modules/orderProgressBar/pure/LottieContainer.tsx (1)

65-73: JSX comment syntax fixed; consider a loading skeleton.

The invalid JSX comment from the previous review has been corrected. The Suspense wrapper is properly implemented with a valid fallback={null}.

Since the TODO already flags this, consider whether a loading skeleton or placeholder would improve UX by preventing a brief flash when the Lottie animation loads. For a progress indicator, null may be acceptable if the load is fast enough.

apps/cowswap-frontend/vite.config.mts (1)

182-190: Manual chunks configuration looks good.

The chunking strategy for large dependencies (@sentry, @uniswap, @ethersproject, etc.) is sensible for code splitting. The bn.js chunk complements the dedupe setting above.

One minor note: the comment on line 187 states web3 "was used by @1inch" - if @1inch no longer uses web3 after this refactor, consider verifying this chunk is still needed.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 012a863 and 62351b7.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • CONTRIBUTING.md
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/LottieContainer.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/TopSections.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx
  • apps/cowswap-frontend/vite.config.mts
  • package.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/steps/FinishedStep.tsx
  • apps/cowswap-frontend/src/modules/orderProgressBar/pure/TopSections.tsx
  • apps/cowswap-frontend/src/modules/ordersTable/pure/OrdersTableContainer/NoOrdersContent.tsx
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: shoom3301
Repo: cowprotocol/cowswap PR: 5443
File: apps/cowswap-frontend/src/modules/swap/containers/ConfirmSwapModalSetup/index.tsx:71-71
Timestamp: 2025-02-20T15:59:33.749Z
Learning: The swap module in apps/cowswap-frontend/src/modules/swap/ is marked for deletion in PR #5444 as part of the swap widget unification effort.
📚 Learning: 2025-07-28T16:26:08.051Z
Learnt from: cowdan
Repo: cowprotocol/cowswap PR: 6034
File: apps/cowswap-frontend-e2e/src/e2e/fiat-amounts.test.ts:44-47
Timestamp: 2025-07-28T16:26:08.051Z
Learning: In the cowswap codebase, using trivial placeholder tests like `it('should be true', () => { expect(true).to.be.true })` in e2e test files is an intentional pattern when disabling broken tests to keep CI green while maintaining build efficiency.

Applied to files:

  • CONTRIBUTING.md
📚 Learning: 2025-12-03T19:23:35.789Z
Learnt from: kernelwhisperer
Repo: cowprotocol/cowswap PR: 6610
File: apps/cowswap-frontend/project.json:38-39
Timestamp: 2025-12-03T19:23:35.789Z
Learning: In the cowswap-frontend project configuration (apps/cowswap-frontend/project.json), the Vite dev server option `"host": true` is set to support Windows + WSL development environments, where binding to all network interfaces is required for the Windows host to access the dev server running in WSL.

Applied to files:

  • apps/cowswap-frontend/vite.config.mts
📚 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/orderProgressBar/pure/LottieContainer.tsx
🧬 Code graph analysis (1)
apps/cowswap-frontend/vite.config.mts (1)
tools/formatChunkFileName.ts (1)
  • formatChunkFileName (3-20)
🪛 LanguageTool
CONTRIBUTING.md

[grammar] ~168-~168: Use a hyphen to join words.
Context: ...ially if it's cjs module (cjs is non tree-shakable) - [Bundlephobia](https://...

(QB_NEW_EN_HYPHEN)

⏰ 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 (13)
CONTRIBUTING.md (3)

155-156: Verify build analysis output paths are implemented.

The documentation references build/cowswap/analyse.html and build/cowswap/bundle-stats.html, but the PR objectives list "Add rollup-plugin-bundle-stats" as a TODO. Ensure these output paths are available and that the yarn analyze-build command is properly configured before merging, or update the guidance to reflect the current state of implementation.


151-171: Bundle optimization section is well-structured and actionable.

The new section provides clear, practical guidance aligned with the PR's bundle optimization objectives. The problem-detection steps, dynamic import rules, and dependency-size considerations are directly applicable to contributors and enforce key optimization patterns introduced in this PR.


173-194: Section numbering correctly updated after restructuring.

All downstream sections (Testing, Interaction Contract, Development Communication) are properly renumbered to account for the new Bundle optimization section.

apps/cowswap-frontend/src/modules/orderProgressBar/pure/LottieContainer.tsx (1)

1-1: LGTM! Lazy loading correctly implemented.

The lazy import of lottie-react follows the standard React.lazy pattern and aligns with the PR's bundle optimization goals. This will defer loading the Lottie library until the component is actually rendered.

Also applies to: 5-5

apps/cowswap-frontend/vite.config.mts (6)

5-5: LGTM on imports and type annotations.

The new imports for bundleStats, formatChunkFileName, and type-only imports for TemplateType and PluginOption are correctly structured. The ESLint directive update to @typescript-eslint/no-restricted-imports aligns with the broader rule transition in this PR.

Also applies to: 17-17, 21-23


37-37: Good addition of explicit type annotation.

Typing plugins as PluginOption[] improves type safety and aligns with the casts used when pushing analyzer plugins.


75-87: Verify intended behavior with open: true and emitFile: true.

With emitFile: true, the analysis HTML will be written to the build output directory. Note that open: true (line 79) combined with emitFile: true may still attempt to open the file in a browser after the build. If the intent is only to emit the file without opening it, consider setting open: false.


138-143: Good ESM prioritization for dependency optimization.

Setting mainFields: ['exports', 'module', 'main'] ensures esbuild prefers ESM builds when available, improving tree-shaking effectiveness. The comment appropriately documents the rationale.


149-154: Effective deduplication and ESM resolution strategy.

The bn.js deduplication with the v5/v4 compatibility note is a good optimization. The conditions array correctly prioritizes ESM resolution. These settings work well together with the optimizeDeps.mainFields configuration above.


169-181: Improved chunk naming for better debuggability.

The formatChunkFileName helper with descriptive prefixes (page-, connectors-, lottie-react-, etc.) makes it much easier to identify chunk origins in build output and DevTools. The fallback to static/[name]-[hash].js ensures all chunks are handled.

package.json (3)

46-46: LGTM: Improved visualization format.

The treemap template generally provides better visibility for bundle size analysis compared to sunburst.


93-93: LGTM: New dependency addition.

The @ethereumjs/util package is properly versioned with a caret for receiving updates.


338-338: No action needed. The rollup-plugin-bundle-stats package is properly integrated into the Vite build configuration (imported and added to the plugins array in vite.config.mts).

Likely an incorrect or invalid review comment.

Comment thread CONTRIBUTING.md
Comment thread package.json Outdated
Comment thread package.json Outdated
Comment on lines +119 to +121
"@safe-global/api-kit": "^4.0.1",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-core-sdk-types": "^2.2.0",
"@safe-global/safe-ethers-lib": "^1.9.4",
"@safe-global/types-kit": "^3.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find all usages of Safe Global types and nonce handling
rg -n --type=ts --type=tsx 'SafeMultisigTransactionResponse|SafeApiKit|nonce' --max-count=50

Repository: cowprotocol/cowswap

Length of output: 90


🏁 Script executed:

# Check for test files related to Safe operations
fd -e 'test.ts' -e 'test.tsx' -e 'spec.ts' -e 'spec.tsx' | xargs rg -l 'Safe|nonce' 2>/dev/null | head -20

Repository: cowprotocol/cowswap

Length of output: 623


🏁 Script executed:

# Look for the actual Safe Global package versions and their changelog implications
rg -n '@safe-global' package.json

Repository: cowprotocol/cowswap

Length of output: 352


🏁 Script executed:

# Search for SafeApiKit usage patterns in the codebase
rg -n 'SafeApiKit' --type=ts --type=tsx -B2 -A5

Repository: cowprotocol/cowswap

Length of output: 90


🏁 Script executed:

# Search for SafeApiKit and SafeMultisigTransactionResponse usage
rg -n 'SafeApiKit|SafeMultisigTransactionResponse' --type=ts --max-count=30

Repository: cowprotocol/cowswap

Length of output: 5579


🏁 Script executed:

# Search for nonce handling patterns
rg -n 'nonce' --type=ts apps/cowswap-frontend/ | head -30

Repository: cowprotocol/cowswap

Length of output: 4892


🏁 Script executed:

# Find where Safe Global types are imported
rg -n 'from.*@safe-global' --type=ts --max-count=30

Repository: cowprotocol/cowswap

Length of output: 3094


🏁 Script executed:

# Check the actual Safe approval-related code mentioned in learnings
cat apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.ts

Repository: cowprotocol/cowswap

Length of output: 5470


🏁 Script executed:

# Check test coverage in Safe-related test files
cat apps/explorer/src/test/hooks/useSafeState.hooks.test.tsx

Repository: cowprotocol/cowswap

Length of output: 2040


🏁 Script executed:

# Check useTradeApproveCallback test file to see what's tested
head -100 apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.test.ts

Repository: cowprotocol/cowswap

Length of output: 4213


🏁 Script executed:

# Search for TODO or FIXME related to testing in Safe modules
rg -n 'TODO|FIXME' --type=ts apps/cowswap-frontend/src/modules/zeroApproval/ apps/cowswap-frontend/src/modules/twap/ libs/core/src/gnosisSafe/

Repository: cowprotocol/cowswap

Length of output: 7331


🏁 Script executed:

# Verify SafeApiKit instantiation and version compatibility
cat libs/core/src/gnosisSafe/index.ts

Repository: cowprotocol/cowswap

Length of output: 3556


🏁 Script executed:

# Check Safe-related test implementations
cat apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.test.ts | tail -200

Repository: cowprotocol/cowswap

Length of output: 7133


🏁 Script executed:

# Look for Safe scenario tests
rg -n 'Safe|nonce|safeApiKit' apps/cowswap-frontend/src/modules/erc20Approve/containers/TradeApproveModal/useTradeApproveCallback.test.ts

Repository: cowprotocol/cowswap

Length of output: 82


🏁 Script executed:

# Check if there are integration tests for Safe flows
fd -path '*/test*' -o -path '*/spec*' | xargs rg -l 'SafeApiKit\|SafeMultisigTransactionResponse' 2>/dev/null

Repository: cowprotocol/cowswap

Length of output: 233


🏁 Script executed:

# Search for actual Safe wallet test coverage in approval flows
rg -n 'Safe|safeMultisig|safeApiKit' --type=ts apps/cowswap-frontend/src/modules/erc20Approve/ apps/cowswap-frontend/src/modules/zeroApproval/ -i | grep -i test

Repository: cowprotocol/cowswap

Length of output: 45


🏁 Script executed:

# Check if there are dedicated Safe approval integration tests
find apps/cowswap-frontend -name '*.test.ts' -o -name '*.test.tsx' | xargs rg -l 'SafeMultisigTransactionResponse|useApproveCurrency|useZeroApprove' 2>/dev/null

Repository: cowprotocol/cowswap

Length of output: 257


🏁 Script executed:

# Look at the actual useApproveCurrency hook which handles Safe responses
cat apps/cowswap-frontend/src/modules/erc20Approve/hooks/useApproveCurrency.ts

Repository: cowprotocol/cowswap

Length of output: 1198


🏁 Script executed:

# Check for useZeroApprove tests
find apps/cowswap-frontend -name '*useZeroApprove*test*'

Repository: cowprotocol/cowswap

Length of output: 45


🏁 Script executed:

# Check for useApproveCurrency tests
find apps/cowswap-frontend -name '*useApproveCurrency*test*'

Repository: cowprotocol/cowswap

Length of output: 45


🏁 Script executed:

# Look at useZeroApprove implementation to understand its Safe interaction
cat apps/cowswap-frontend/src/modules/zeroApproval/hooks/useZeroApprove.ts

Repository: cowprotocol/cowswap

Length of output: 2568


Add test coverage for Safe wallet approval flows.

The Safe Global package updates are properly integrated with BigInt chainId conversion already in place (libs/core/src/gnosisSafe/index.ts) and defensive nonce type handling established. However, the approval flows lack dedicated test coverage for Safe-specific scenarios:

  • useZeroApprove directly calls SafeApiKit.getTransaction() and polls for transaction execution with waitForSafeTransactionExecution() — needs tests for this polling behavior and Safe wallet detection conditions
  • useApproveCurrency combines trade approval with zero approval but has no tests
  • Current test coverage focuses on standard transactions; Safe wallet scenarios (isSafeWallet + isWalletConnect conditional logic) are untested

Add tests for Safe transaction execution flows, Safe wallet routing, and transaction polling edge cases before merging.

🤖 Prompt for AI Agents
In package.json around lines 119 to 121, tests for Safe wallet approval flows
are missing; add unit/integration tests that mock SafeApiKit.getTransaction and
waitForSafeTransactionExecution to cover polling behavior, simulate Safe wallet
detection (isSafeWallet true/false and isWalletConnect branches), and assert
useZeroApprove and useApproveCurrency handle zero-approval flow, combined
approval flow, retries, and timeout/edge cases; update test
scripts/devDependencies as needed to run these tests and ensure mocks restore
state between cases.

Comment thread package.json Outdated
Comment on lines +138 to +140
"@walletconnect/ethereum-provider": "^2.23.0",
"@walletconnect/types": "^2.23.0",
"@walletconnect/utils": "^2.23.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

@walletconnect/ethereum-provider latest version npm

💡 Result:

Latest version: 2.21.8 (as of December 28, 2025). Install: npm i @walletconnect/ethereum-provider. [1]

Sources:
[1] npm package page for @walletconnect/ethereum-provider. [2] jsDelivr package info.


🌐 Web query:

WalletConnect v2 deprecated Reown migration 2024

💡 Result:

Short summary — yes: WalletConnect Inc. rebranded to Reown and deprecated the WalletConnect-branded SDK packages (including v2 SDK packages under the WalletConnect org). A limited‑support window ran Sept 17, 2024 → Feb 17, 2025; full end‑of‑life (no updates/support) began Feb 18, 2025. Reown published replacement packages (AppKit / WalletKit, Reown org repos) and migration guides for Web, React Native, Swift, Flutter, etc. Action: identify which WalletConnect packages you use, follow the corresponding Reown migration guide (replace @walletconnect/* / Web3Modal / Web3Wallet with @reown/* equivalents), and complete migration to Reown packages. [1][2][3]

Sources:

  • Reown — Deprecated WalletConnect SDKs (deprecation schedule + affected packages). [1]
  • WalletConnect / Reown migration docs — Upgrade from Web3Wallet to Reown WalletKit (migration steps). [2]
  • Reown announcement / rebrand blog. [3]

🌐 Web query:

@walletconnect/types @walletconnect/utils latest version

💡 Result:

As of today (December 28, 2025):

  • @walletconnect/types — 2.21.8. Install: npm i @walletconnect/types. [1]
  • @walletconnect/utils — 2.21.8. Install: npm i @walletconnect/utils. [2]

Sources: npm package pages. [1] https://www.npmjs.com/package/%40walletconnect/types [2] https://www.npmjs.com/package/%40walletconnect/utils


Migrate from deprecated WalletConnect v2 packages to Reown equivalents—this is critical.

The @WalletConnect v2 packages (@walletconnect/ethereum-provider, @walletconnect/types, @walletconnect/utils) reached end-of-life on February 18, 2025 and no longer receive updates or support. WalletConnect Inc. rebranded to Reown and deprecated the entire v2 SDK. Migration to @reown/* packages (AppKit/WalletKit) is required. Additionally, version 2.23.0 does not appear to exist on npm; the latest v2 release is 2.21.8—verify the actual resolved versions and migrate to Reown's replacement packages per their official migration guides.

Comment thread package.json Outdated
Comment thread package.json Outdated
},
"dependencies": {
"@1inch/permit-signed-approvals-utils": "^1.4.10",
"@1inch/permit-signed-approvals-utils": "1.5.1",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elena-zh please test permits in this PR

Comment thread package.json Outdated
"@rjsf/core": "^4.2.2",
"@safe-global/api-kit": "^1.3.0",
"@safe-global/protocol-kit": "^1.2.0",
"@safe-global/api-kit": "^4.0.1",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elena-zh please test integration with Safe (web/walletConnect)

)}
</motion.div>
</AnimatePresence>
<Suspense fallback={<ProgressSkeleton />}>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@elena-zh please test order progress modal

@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 29, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
cowfi Ready Ready Preview Jan 27, 2026 10:57am
explorer-dev Ready Ready Preview Jan 27, 2026 10:57am
swap-dev Ready Ready Preview Jan 27, 2026 10:57am
widget-configurator Ready Ready Preview Jan 27, 2026 10:57am
2 Skipped Deployments
Project Deployment Review Updated (UTC)
cosmos Ignored Ignored Jan 27, 2026 10:57am
sdk-tools Ignored Ignored Preview Jan 27, 2026 10:57am

Request Review

@shoom3301
Copy link
Copy Markdown
Collaborator

@crutch12 thank you!
Lint is failed, could you check it please?

… refactor/swap-bundle-optimization

# Conflicts:
#	libs/wallet/src/web3-react/updater.ts
… refactor/swap-bundle-optimization

# Conflicts:
#	apps/cowswap-frontend/patches/@1inch+permit-signed-approvals-utils+1.4.10.patch
#	apps/cowswap-frontend/patches/@1inch+permit-signed-approvals-utils+1.5.1.patch
#	apps/cowswap-frontend/src/common/hooks/useCancelOrder/onChainCancellation.ts
#	apps/cowswap-frontend/src/modules/ordersTable/hooks/useDoesOrderHaveValidPermit.test.ts
#	apps/cowswap-frontend/src/utils/orderUtils/getOrderPermitAmount.test.ts
#	apps/cowswap-frontend/src/utils/orderUtils/isPermitValidForOrder.ts
#	eslint.config.js
#	libs/permit-utils/package.json
#	package.json
#	patches/@1inch+permit-signed-approvals-utils+1.4.10.patch
#	yarn.lock
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@apps/cowswap-frontend/src/locales/en-US.po`:
- Around line 5957-5958: The msgid "There is no provider to get Gnosis safe
info" is marked obsolete in en-US.po but remains active in other locale catalogs
(el-GR, es-ES, tr-TR, ru-RU, pt-BR, pl-PL); either mark this msgid obsolete
across those locale files to match en-US or re-extract/sync all translation
catalogs so the msgid is consistently present or removed in every locale,
updating the corresponding .po entries to match (use the msgid string to locate
entries).

In `@libs/wallet/package.json`:
- Around line 40-45: Remove the unused legacy dependency "ethereumjs-util" from
package.json and keep the modern "@ethereumjs/util" v10.1.0 in place;
specifically delete the "ethereumjs-util" entry, run the package manager to
update lockfiles (npm/yarn/pnpm install), and verify imports in
libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts still
reference "@ethereumjs/util" (not "ethereumjs-util") so nothing breaks.
🧹 Nitpick comments (4)
apps/cowswap-frontend/src/locales/en-US.po (1)

2586-2587: Keep other locale catalogs in sync for the re-enabled copy.

Since this msgid is active again, please ensure other locale .po catalogs have active entries too, otherwise non‑English users may see fallbacks.

apps/cowswap-frontend/vite.config.mts (1)

179-186: Remove the unused web3 chunk configuration.

The web3/dist chunk is dead code—web3 is not imported anywhere in the cowswap-frontend app and is not listed as a dependency in its package.json. Even though @1inch remains a dependency, there's no evidence it requires web3. This chunk can be safely removed.

libs/wallet/package.json (1)

40-40: Consider removing the legacy ethereumjs-util package.

Both @ethereumjs/util (v10, line 40) and ethereumjs-util (v7, line 55) are present. The @ethereumjs/util package is the modern ESM rewrite, while ethereumjs-util is the legacy CommonJS package. Since this PR focuses on bundle optimization and ESM migration, keeping both adds redundant code to the bundle.

#!/bin/bash
# Description: Check if ethereumjs-util (legacy) is still being used
# Expect: If no direct imports, the legacy package can be removed

echo "=== Imports from legacy ethereumjs-util ==="
rg -n "from 'ethereumjs-util'|from \"ethereumjs-util\"|require\('ethereumjs-util'\)" --type ts --type js

echo ""
echo "=== Imports from modern `@ethereumjs/util` ==="
rg -n "from '@ethereumjs/util'|from \"@ethereumjs/util\"" --type ts --type js

Also applies to: 55-55

apps/explorer/tsconfig.json (1)

11-11: Reconsider disabling noImplicitAny.
This overrides the stricter setting in tsconfig.base.json and contradicts strict: true. Enabling noImplicitAny: true would strengthen type safety. The codebase has untyped callback parameters (e.g., .catch((error) => and .map((item) =>) that would need explicit type annotations, but this is worthwhile for preventing regressions.

♻️ Proposed change
-    "noImplicitAny": false
+    "noImplicitAny": true

Comment on lines +5957 to +5958
#~ msgid "There is no provider to get Gnosis safe info"
#~ msgstr "There is no provider to get Gnosis safe info"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any remaining usage of the msgid in code
rg -n "There is no provider to get Gnosis safe info"

Repository: cowprotocol/cowswap

Length of output: 877


🏁 Script executed:

#!/bin/bash
# Search for code references to this message (excluding .po files)
rg -n "Gnosis safe info" --type-not po

Repository: cowprotocol/cowswap

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Search for any "Gnosis safe" references in code
rg "Gnosis safe" --type-not po

Repository: cowprotocol/cowswap

Length of output: 464


Remove obsolete marking or synchronize all locale files.

The string is confirmed unused in code, so marking it obsolete in en-US.po is appropriate. However, 6 other locale files (el-GR.po, es-ES.po, tr-TR.po, ru-RU.po, pt-BR.po, pl-PL.po) still have this msgid as active entries. Either mark it obsolete consistently across all locales or re-extract catalogs to synchronize all translation files.

🤖 Prompt for AI Agents
In `@apps/cowswap-frontend/src/locales/en-US.po` around lines 5957 - 5958, The
msgid "There is no provider to get Gnosis safe info" is marked obsolete in
en-US.po but remains active in other locale catalogs (el-GR, es-ES, tr-TR,
ru-RU, pt-BR, pl-PL); either mark this msgid obsolete across those locale files
to match en-US or re-extract/sync all translation catalogs so the msgid is
consistently present or removed in every locale, updating the corresponding .po
entries to match (use the msgid string to locate entries).

Comment thread libs/wallet/package.json
Comment on lines +40 to +45
"@ethereumjs/util": "^10.1.0",
"@metamask/jazzicon": "^2.0.0",
"@metamask/sdk": "^0.31.4",
"@safe-global/api-kit": "^1.3.0",
"@safe-global/api-kit": "^4.0.1",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-core-sdk-types": "^2.2.0",
"@safe-global/types-kit": "^3.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all usages of SafeApiKit and Safe types
echo "=== SafeApiKit instantiation patterns ==="
rg -n 'SafeApiKit' --type ts --type tsx | head -30

echo ""
echo "=== Imports from `@safe-global` packages (old and new) ==="
rg -n 'from ["\x27]@safe-global/(api-kit|types-kit|safe-core-sdk-types)' --type ts --type tsx

echo ""
echo "=== SafeMultisigTransactionResponse usage ==="
rg -n 'SafeMultisigTransactionResponse' --type ts --type tsx

echo ""
echo "=== ethereumjs-util vs `@ethereumjs/util` usage ==="
rg -n 'from ["\x27](ethereumjs-util|@ethereumjs/util)' --type ts --type tsx

Repository: cowprotocol/cowswap

Length of output: 389


🏁 Script executed:

#!/bin/bash
# Check which Safe types are being imported and from where
echo "=== All imports containing 'Safe' from `@safe-global` ==="
rg -n 'import.*from.*@safe-global' --type ts --type tsx -A 1 | head -50

echo ""
echo "=== Check package.json for both ethereumjs packages ==="
rg -n 'ethereumjs' libs/wallet/package.json

Repository: cowprotocol/cowswap

Length of output: 294


🏁 Script executed:

#!/bin/bash
# Broader search without tsx file type issues
echo "=== SafeApiKit usage ==="
rg -n 'SafeApiKit' --type js --type ts 2>/dev/null || rg -n 'SafeApiKit'

echo ""
echo "=== Safe imports from `@safe-global` ==="
rg -n 'from.*@safe-global' --type js --type ts 2>/dev/null || rg -n 'from.*@safe-global'

echo ""
echo "=== `@ethereumjs/util` imports ==="
rg -n 'from.*@ethereumjs/util' --type js --type ts 2>/dev/null || rg -n 'from.*@ethereumjs/util'

echo ""
echo "=== ethereumjs-util imports ==="
rg -n 'from.*ethereumjs-util' --type js --type ts 2>/dev/null || rg -n 'from.*ethereumjs-util'

Repository: cowprotocol/cowswap

Length of output: 5520


🏁 Script executed:

#!/bin/bash
# Check the purpose and scope of libs/wallet
echo "=== libs/wallet package.json metadata ==="
head -20 libs/wallet/package.json

echo ""
echo "=== libs/wallet directory structure ==="
find libs/wallet -maxdepth 2 -type f -name "*.ts" -o -name "*.js" | head -20

Repository: cowprotocol/cowswap

Length of output: 725


🏁 Script executed:

#!/bin/bash
# Search more broadly for any Safe-related code
rg -n 'Safe' -i --max-count=30

Repository: cowprotocol/cowswap

Length of output: 50377


🏁 Script executed:

#!/bin/bash
# Check if ethereumjs-util is a transitive dependency
echo "=== Check which package depends on ethereumjs-util ==="
rg -n "ethereumjs-util" libs/wallet/package.json libs/core/package.json package.json

echo ""
echo "=== Check lock file for ethereumjs-util dependency chain ==="
rg -B5 -A2 "^  ethereumjs-util@" pnpm-lock.yaml 2>/dev/null | head -50

Repository: cowprotocol/cowswap

Length of output: 819


🏁 Script executed:

#!/bin/bash
# Check the TrezorConnector usage to confirm it's the only place `@ethereumjs/util` is used
echo "=== Verify TrezorConnector usage of `@ethereumjs/util` ==="
cat -n libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts | head -20

Repository: cowprotocol/cowswap

Length of output: 964


Verify SafeApiKit v4 integration and remove unused ethereumjs-util dependency.

The upgrade from @safe-global/api-kit v1.x to v4.x is properly integrated across the codebase. Imports from the new @safe-global/types-kit (replacing safe-core-sdk-types) are used correctly throughout, including SafeMultisigTransactionResponse and MetaTransactionData.

However, ethereumjs-util v7.1.5 (line 55) is listed in dependencies but has no usages in the codebase. The package @ethereumjs/util v10.1.0 (line 40) is the active modern ESM replacement, used only in libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts. Remove the unused ethereumjs-util entry to clean up dependencies.

🤖 Prompt for AI Agents
In `@libs/wallet/package.json` around lines 40 - 45, Remove the unused legacy
dependency "ethereumjs-util" from package.json and keep the modern
"@ethereumjs/util" v10.1.0 in place; specifically delete the "ethereumjs-util"
entry, run the package manager to update lockfiles (npm/yarn/pnpm install), and
verify imports in
libs/wallet/src/web3-react/connectors/TrezorConnector/getAccountsList.ts still
reference "@ethereumjs/util" (not "ethereumjs-util") so nothing breaks.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
eslint.config.js (2)

240-271: Rule override may unintentionally drop root restrictions.

This config block defines a new @typescript-eslint/no-restricted-imports for apps/cowswap-frontend/** files. In ESLint flat config, this completely replaces (not merges with) the root-level restrictions defined at lines 125-159.

As a result, for cowswap-frontend files, the following root restrictions will not apply:

  • ethers → use @ethersproject/*
  • styled-components → use styled-components/macro
  • @1inch/permit-signed-approvals-utils → use @cowprotocol/permit-utils
  • @safe-global/api-kit → use dynamic import

To preserve the root restrictions while adding frontend-specific ones, you need to merge the paths arrays explicitly.

🔧 Suggested fix to merge restrictions
   // CoW Swap's rules
   {
     files: ['apps/cowswap-frontend/**/*.{ts,tsx,js,jsx}'],
     rules: {
       '@typescript-eslint/no-restricted-imports': [
         'error',
         {
           paths: [
+            // Root restrictions (must be duplicated for flat config)
+            {
+              name: 'ethers',
+              message: "Please import from '@ethersproject/module' directly to support tree-shaking.",
+            },
+            {
+              name: 'styled-components',
+              message: 'Please import from styled-components/macro.',
+            },
+            {
+              name: '@1inch/permit-signed-approvals-utils',
+              message: 'Please import from `@cowprotocol/permit-utils`.',
+              allowTypeImports: true,
+            },
+            {
+              name: '@safe-global/api-kit',
+              message: 'Please use dynamic import.',
+              allowTypeImports: true,
+            },
+            // Frontend-specific restrictions
             {
               name: 'react-router',
               importNames: ['useNavigate'],
               message: "Please import useNavigate from our own common package instead: 'common/hooks/useNavigate'",
             },
             {
               name: 'lottie-react',
               message: 'Please use dynamic import.',
               allowTypeImports: true,
             },
             {
               name: 'framer-motion',
               message: 'Please use dynamic import.',
               allowTypeImports: true,
             },
           ],
 
           patterns: [
             {
               group: ['**/dist'],
               message: 'Do not import from dist/ - this is an implementation detail, and breaks tree-shaking.',
             },
             {
               group: ['!styled-components/macro'],
             },
           ],
         },
       ],
     },
   },

Alternatively, consider extracting the common restrictions into a shared variable and spreading them into each config block to avoid duplication.


281-292: Same rule override concern applies here.

This config for apps/cowswap-frontend/src/common/** also defines its own @typescript-eslint/no-restricted-imports, which will replace both the root restrictions and the cowswap-frontend restrictions for files in the common directory.

Files in common/ will lose restrictions on ethers, styled-components, @1inch/*, @safe-global/api-kit, lottie-react, framer-motion, and useNavigate.

If this is intentional (only wanting the modules import restriction for common/), consider documenting it. Otherwise, merge the paths arrays as suggested for the frontend config.

🤖 Fix all issues with AI agents
In `@apps/widget-configurator/package.json`:
- Line 37: Update the pinned ethers dependency in package.json: change the exact
"ethers": "5.7.2" entry to either the latest v5 release "5.8.0" or use a caret
range like "ethers": "^5.7.2" so the package can receive patch updates; modify
the dependency string in apps/widget-configurator's package.json (the "ethers"
entry) accordingly and run npm/yarn install to update lockfiles.

"@mui/icons-material": "^5.17.1",
"@mui/material": "^5.17.1",
"@web3modal/ethers5": "^4.1.9",
"ethers": "5.7.2",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check `@web3modal/ethers5` peer dependency requirements for ethers
npm view `@web3modal/ethers5`@4.1.9 peerDependencies --json 2>/dev/null | jq '.ethers // "not specified"'

# Check latest ethers v5.x version
npm view ethers versions --json 2>/dev/null | jq '[.[] | select(startswith("5."))] | .[-1]'

Repository: cowprotocol/cowswap

Length of output: 87


Update ethers to the latest v5 version (5.8.0) or use caret to allow patch updates.

The version 5.7.2 is compatible with @web3modal/ethers5@4.1.9 (which requires >=4.1.0 <6.0.0), but it is outdated. The latest ethers v5 version is 5.8.0. Since you've pinned the version exactly without a caret, this dependency won't receive patch updates that may include security fixes or bug improvements. Consider updating to 5.8.0 or using ^5.7.2 to allow automatic patch updates.

🤖 Prompt for AI Agents
In `@apps/widget-configurator/package.json` at line 37, Update the pinned ethers
dependency in package.json: change the exact "ethers": "5.7.2" entry to either
the latest v5 release "5.8.0" or use a caret range like "ethers": "^5.7.2" so
the package can receive patch updates; modify the dependency string in
apps/widget-configurator's package.json (the "ethers" entry) accordingly and run
npm/yarn install to update lockfiles.

Copy link
Copy Markdown
Contributor

@elena-zh elena-zh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you

@shoom3301 shoom3301 merged commit 287a94e into cowprotocol:develop Jan 27, 2026
13 of 17 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jan 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants