Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
aa8d820
refactor(optimization): @1inch/permit-signed-approvals-utils@1.5.1 su…
crutch12 Dec 27, 2025
a23e691
chore: fix vite.config types
crutch12 Dec 27, 2025
85a9cc7
refactor(optimization): dedupe bn.js
crutch12 Dec 27, 2025
f0cccee
refactor(optimization): dynamic import @1inch/permit-signed-approvals…
crutch12 Dec 27, 2025
eb48d90
refactor(optimization): @safe-global new version migration (esm)
crutch12 Dec 27, 2025
2384228
refactor(optimization): update deps
crutch12 Dec 27, 2025
20f60c5
refactor(optimization): dynamic import huge json files and framer-mor…
crutch12 Dec 27, 2025
ecd1c08
chore: @safe-global/api-kit is not really tree-shakable, use original…
crutch12 Dec 27, 2025
5801967
chore: build-analyze - emit analyse.html into build dir; treemap by d…
crutch12 Dec 27, 2025
47b8bf7
chore(eslint): fix no-restricted-imports comments
crutch12 Dec 27, 2025
40c9bc1
refactor(optimization): concurrent @trezor import
crutch12 Dec 27, 2025
b879580
chore: lock file
crutch12 Dec 27, 2025
7d7eabf
chore: @1inch/permit-signed-approvals-utils re-export stats comment
crutch12 Dec 27, 2025
9e7e920
chore(build): add prefixes to chunks
crutch12 Dec 28, 2025
4ee4170
refactor(optimization): force deps esm usage (better tree-shaking)
crutch12 Dec 28, 2025
012a863
chore: comment i18n initial render problem
crutch12 Dec 28, 2025
4f0f2b5
chore: pr fixes
crutch12 Dec 28, 2025
bd2dc76
chore: add bundleStats
crutch12 Dec 28, 2025
62351b7
chore(docs): Bundle optimization
crutch12 Dec 28, 2025
15716a7
chore: eslint fixes
crutch12 Dec 29, 2025
b2d650a
chore: pr fixes
crutch12 Dec 29, 2025
f550b8f
chore: patch-package @1inch/permit-signed-approvals-utils update
crutch12 Jan 4, 2026
279a1b0
chore: @1inch/permit-signed-approvals-utils@1.5.1 in @cowprotocol/per…
crutch12 Jan 4, 2026
751fa73
Merge branch 'develop' into refactor/swap-bundle-optimization
kernelwhisperer Jan 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ yalc.lock
# vercel
.vercel

analyse.html

# NX
.nx

Expand Down
28 changes: 25 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,29 @@ Additional Guidelines:

---

## 8. Testing
## 8. Bundle optimization

Problems detection:

1. run `yarn analyze-build`
2. check `build/cowswap/analyse.html` and `build/cowswap/bundle-stats.html`

Optimization rules:

1. Dynamic imports

- Every huge (> 100kb) dependency should be loaded via dynamic `import()`
- Dynamic import breaks tree-shaking, so re-export only used variables when possible (see imports/1inchPermitUtils)
- Add eslint `@typescript-eslint/no-restricted-imports` rules for dynamically imported modules

2. Dependency size

- Always check if huge dependency has a new version, especially if it's `cjs` module (`cjs` is non tree-shakable)
- [Bundlephobia](https://bundlephobia.com/) shows if module is tree-shakeable and it's actual size

---

## 9. Testing

- Unit tests / integration tests required when applicable
- Jest unit tests for logic
Expand All @@ -159,7 +181,7 @@ Additional Guidelines:

---

## 9. Interaction Contract
## 10. Interaction Contract

1. Ask clarifying questions when requirements are ambiguous
2. Output only ready-to-paste code, using repo-root-relative paths
Expand All @@ -169,7 +191,7 @@ Additional Guidelines:

---

## 10. Development Communication
## 11. Development Communication

- Use descriptive commit messages, inline comments, and rich PR descriptions (expected behaviour & QA scope)
- Plan work up-front to keep each PR scoped to a single feature/fix
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useCallback } from 'react'

import { useCowAnalytics } from '@cowprotocol/analytics'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { LpToken } from '@cowprotocol/common-const'
import { LpTokenProvider } from '@cowprotocol/types'
import { BigNumber } from '@ethersproject/bignumber'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { ReactNode, useState } from 'react'

import { CowHookDetails, HookToDappMatch } from '@cowprotocol/hook-dapp-lib'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { ReactElement, useEffect, useMemo, useState } from 'react'

import { cowAppDataLatestScheme } from '@cowprotocol/cow-sdk'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { GPv2Settlement, CoWSwapEthFlow } from '@cowprotocol/abis'
import { calculateGasMargin } from '@cowprotocol/common-utils'
import { BigNumber } from '@ethersproject/bignumber'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useCallback } from 'react'

import { getIsNativeToken } from '@cowprotocol/common-utils'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useCallback } from 'react'

import { getIsNativeToken } from '@cowprotocol/common-utils'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { USDC } from '@cowprotocol/common-const'
import { getWrappedToken, tryParseCurrencyAmount } from '@cowprotocol/common-utils'
import { SupportedChainId } from '@cowprotocol/cow-sdk'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useMemo } from 'react'

import { SupportedChainId } from '@cowprotocol/cow-sdk'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useMemo } from 'react'

import { useTradeTypeInfo } from 'modules/trade'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useMemo } from 'react'

import { MIN_FIAT_SURPLUS_VALUE, MIN_FIAT_SURPLUS_VALUE_MODAL, MIN_SURPLUS_UNITS } from '@cowprotocol/common-const'
Expand Down
2 changes: 1 addition & 1 deletion apps/cowswap-frontend/src/common/hooks/useNavigate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useCallback } from 'react'

import { isInjectedWidget } from '@cowprotocol/common-utils'

// eslint-disable-next-line no-restricted-imports
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { NavigateOptions, To, useNavigate as useNavigateOriginal } from 'react-router'

export type NavigateFunction = (to: To, options?: NavigateOptions) => void | Promise<void>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useCallback } from 'react'

import { getChainInfo } from '@cowprotocol/common-const'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useCallback } from 'react'

import { tryParseCurrencyAmount } from '@cowprotocol/common-utils'
Expand Down
18 changes: 9 additions & 9 deletions apps/cowswap-frontend/src/common/hooks/useSafeApiKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ import { useEffect, useState } from 'react'

import { createSafeApiKitInstance } from '@cowprotocol/core'
import { useIsSafeWallet, useWalletInfo } from '@cowprotocol/wallet'
import { useWalletProvider } from '@cowprotocol/wallet-provider'
import SafeApiKit from '@safe-global/api-kit'
import type SafeApiKit from '@safe-global/api-kit'

export function useSafeApiKit(): SafeApiKit | null {
const [safeApiClient, setSafeApiClient] = useState<SafeApiKit | null>(null)
const { chainId } = useWalletInfo()
const provider = useWalletProvider()
const isSafeWallet = useIsSafeWallet()

useEffect(() => {
if (provider && chainId && isSafeWallet) {
setSafeApiClient(createSafeApiKitInstance(chainId, provider))
} else {
setSafeApiClient(null)
}
}, [chainId, isSafeWallet, provider])
;(async () => {
if (chainId && isSafeWallet) {
setSafeApiClient(await createSafeApiKitInstance(chainId))
} else {
setSafeApiClient(null)
}
})()
}, [chainId, isSafeWallet])

return safeApiClient
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useMemo } from 'react'

import { getChainInfo, TokenWithLogo } from '@cowprotocol/common-const'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useMemo } from 'react'

import { getChainInfo, TokenWithLogo } from '@cowprotocol/common-const'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useMemo } from 'react'

import { TokenWithLogo } from '@cowprotocol/common-const'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import React, { useCallback, useMemo, useRef } from 'react'

import { useMediaQuery } from '@cowprotocol/common-hooks'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import React, { ReactNode } from 'react'

import { Command } from '@cowprotocol/types'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'

import { NATIVE_CURRENCIES } from '@cowprotocol/common-const'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { ReactNode } from 'react'

import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { rawToTokenAmount } from '@cowprotocol/common-utils'
import { Currency, CurrencyAmount, Price } from '@uniswap/sdk-core'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { ReactNode } from 'react'

import { TokenAmount } from '@cowprotocol/ui'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import React, { ReactNode } from 'react'

import { isFractionFalsy } from '@cowprotocol/common-utils'
Expand Down
2 changes: 1 addition & 1 deletion apps/cowswap-frontend/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type SafeTransactionParams = {
submissionDate: string
executionDate: string | null
isExecuted: boolean
nonce: number
nonce: string
confirmationsRequired: number
confirmations: number
safeTxHash: string
Expand Down
2 changes: 1 addition & 1 deletion apps/cowswap-frontend/src/common/updaters/SentryUpdater.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useEffect } from 'react'

import { useIsWindowVisible } from '@cowprotocol/common-hooks'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { ReactNode } from 'react'

import { useCowAnalytics } from '@cowprotocol/analytics'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useCallback, useEffect, useRef } from 'react'

import { CANCELLED_ORDERS_PENDING_TIME } from '@cowprotocol/common-const'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useMemo, useRef } from 'react'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useSetAtom } from 'jotai'
import { useCallback, useEffect, useMemo, useRef } from 'react'

Expand Down Expand Up @@ -87,7 +87,11 @@ async function _updatePresignGnosisSafeTx(
* If an order has a nonce lower than the current Safe nonce, it means that the proposed transaction was replaced by another one.
* In this case, we should cancel the order.
*/
const isOrderTxReplaced = !!(safeNonce && safeTransaction.nonce < safeNonce && !safeTransaction.isExecuted)
const isOrderTxReplaced = !!(
safeNonce &&
BigInt(safeTransaction.nonce) < BigInt(safeNonce) &&
!safeTransaction.isExecuted
)

if (CREATING_STATES.includes(order.status) && isOrderTxReplaced) {
cancelOrdersBatch({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useSetAtom } from 'jotai'
import { useEffect, useMemo } from 'react'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useSetAtom } from 'jotai'
import { useCallback } from 'react'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { useAtom, useSetAtom } from 'jotai'
import { useRef } from 'react'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-restricted-imports */ // TODO: Don't use 'modules' import
/* eslint-disable @typescript-eslint/no-restricted-imports */ // TODO: Don't use 'modules' import
import { doesHookHavePermit } from '@cowprotocol/hook-dapp-lib'

import { getAppDataHooks } from 'modules/appData'
Expand Down
13 changes: 3 additions & 10 deletions apps/cowswap-frontend/src/legacy/hooks/useGetSafeTxInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,24 @@ import { useCallback } from 'react'
import { retry, RetryOptions } from '@cowprotocol/common-utils'
import { getSafeTransaction } from '@cowprotocol/core'
import { useWalletInfo } from '@cowprotocol/wallet'
import { useWalletProvider } from '@cowprotocol/wallet-provider'
import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types'
import type { SafeMultisigTransactionResponse } from '@safe-global/types-kit'

import { t } from '@lingui/core/macro'
import { RetryResult } from 'types'

const DEFAULT_RETRY_OPTIONS: RetryOptions = { n: 3, minWait: 1000, maxWait: 3000 }

export type GetSafeTxInfo = (hash: string) => RetryResult<SafeMultisigTransactionResponse>

export function useGetSafeTxInfo(): GetSafeTxInfo {
const provider = useWalletProvider()
const { chainId } = useWalletInfo()

const getSafeInfo = useCallback<GetSafeTxInfo>(
(hash) => {
return retry(() => {
if (!provider) {
throw new Error(t`There is no provider to get Gnosis safe info`)
}

return getSafeTransaction(chainId, hash, provider)
return getSafeTransaction(chainId, hash)
}, DEFAULT_RETRY_OPTIONS)
},
[chainId, provider],
[chainId],
)

return getSafeInfo
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types'
import type { SafeMultisigTransactionResponse } from '@safe-global/types-kit'

import { createAction } from '@reduxjs/toolkit'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OrderClass } from '@cowprotocol/cow-sdk'
import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types'
import type { SafeMultisigTransactionResponse } from '@safe-global/types-kit'

import { createReducer } from '@reduxjs/toolkit'

Expand All @@ -22,7 +22,7 @@ export enum HashType {
export interface EnhancedTransactionDetails {
hash: string // The hash of the transaction, normally Ethereum one, but not necessarily
hashType: HashType // Transaction hash: could be Ethereum tx, or for multisigs could be some kind of hash identifying the order (i.e. Gnosis Safe)
transactionHash?: string // Transaction hash. For EOA this field is immediately available, however, other wallets go through a process of offchain signing before the transactionHash is available
transactionHash: string | null // Transaction hash. For EOA this field is immediately available, however, other wallets go through a process of offchain signing before the transactionHash is available
nonce: number

// Params using for polling handling
Expand Down Expand Up @@ -122,7 +122,7 @@ export default createReducer(initialState, (builder) =>
const txs = transactions[chainId] ?? {}
txs[hash] = {
hash,
transactionHash: hashType === HashType.ETHEREUM_TX ? hash : undefined,
transactionHash: hashType === HashType.ETHEREUM_TX ? hash : null,
nonce,
hashType,
addedTime: now(),
Expand Down
2 changes: 1 addition & 1 deletion apps/cowswap-frontend/src/legacy/state/orders/actions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EnrichedOrder, OrderClass, OrderCreation, SupportedChainId as ChainId, UID } from '@cowprotocol/cow-sdk'
import { BigNumberish } from '@ethersproject/bignumber'
import type { SafeMultisigTransactionResponse } from '@safe-global/safe-core-sdk-types'
import type { SafeMultisigTransactionResponse } from '@safe-global/types-kit'
import { Currency, CurrencyAmount, Token } from '@uniswap/sdk-core'

import { createAction } from '@reduxjs/toolkit'
Expand Down
Loading
Loading