Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
4a320f9
components structure refactor
mgrabina Oct 7, 2025
a097efc
fixes
mgrabina Oct 23, 2025
b86113f
fixed latest issues and unsupported features with cow adapters
mgrabina Oct 28, 2025
7ea5ea9
permit on classic swaps and some fixes
mgrabina Oct 28, 2025
c51908f
docs
mgrabina Oct 29, 2025
a0e67d9
delete legacy code
mgrabina Oct 29, 2025
0744de1
some fixes
mgrabina Oct 30, 2025
5e2fba1
safe check for nonce reuse in permits, fix for network fee
mgrabina Oct 30, 2025
20bf4b4
nits limit orders
mgrabina Oct 30, 2025
755c7c9
debounced
mgrabina Oct 30, 2025
71e1637
try fetch permit support from onchain fallback
mgrabina Oct 30, 2025
e553039
% selector in asset input
mgrabina Oct 30, 2025
91966bb
misc fixes
mgrabina Nov 3, 2025
250bf89
Merge branch 'main' into feat/cow-swap-adapters
mgrabina Nov 4, 2025
9114bb4
fix: use release versions for cow dps
mgrabina Nov 4, 2025
d84b564
misc fixes
mgrabina Nov 4, 2025
1452502
safe checks for reserves
mgrabina Nov 4, 2025
d2e330e
tracking adapters history in local
mgrabina Nov 5, 2025
9ebbe21
misc fixes
mgrabina Nov 5, 2025
88ae066
unify cow env
mgrabina Nov 5, 2025
6871e49
i18n
mgrabina Nov 5, 2025
752f37a
misc fixes
mgrabina Nov 5, 2025
a36e15c
misc
mgrabina Nov 6, 2025
ca72563
misc
mgrabina Nov 6, 2025
8fd65d2
misc
mgrabina Nov 6, 2025
ddd0e16
showing apys in picker
mgrabina Nov 6, 2025
5eb44d6
fix repay w collateral assets showing
mgrabina Nov 6, 2025
3a2bf32
misc
mgrabina Nov 7, 2025
35bdc2d
misc
mgrabina Nov 7, 2025
82b9938
cow release versions and polygon unsupported tokens
mgrabina Nov 7, 2025
15f9e2f
nit message on cancel modal, and safe check for rate change
mgrabina Nov 7, 2025
5160716
fix: use always underlying addresses in quotes
mgrabina Nov 7, 2025
16a5492
miisc nits
mgrabina Nov 7, 2025
ed39bac
add slippage tolerance logic to quote param
mgrabina Nov 7, 2025
812b152
balance check for repay w collateral
mgrabina Nov 7, 2025
55bc7f5
misc
mgrabina Nov 10, 2025
ea5a902
fix WandS paraswap
mgrabina Nov 10, 2025
9a21671
misc
mgrabina Nov 10, 2025
9aafaf9
native limit orders info
mgrabina Nov 11, 2025
fd5fda9
fix cancel add adapter
mgrabina Nov 11, 2025
6a9d4b9
add safe check for calculated instance changed
mgrabina Nov 11, 2025
b8132ff
temporary address warning
mgrabina Nov 11, 2025
13c0e00
misc
mgrabina Nov 11, 2025
e852a87
fix usdt reset
mgrabina Nov 11, 2025
c2c0fc5
do not add network costs to limit orders amounts
mgrabina Nov 11, 2025
e0cc0d4
high costs warning
mgrabina Nov 11, 2025
8ac69f1
better management of actions blocked to account for multiple reasons
mgrabina Nov 12, 2025
bcf1a7b
inform flashloan fee in paraswap flows
mgrabina Nov 12, 2025
e048454
do not show temporary contract warning for non flashloan flow
mgrabina Nov 12, 2025
93d2369
improve mobile responsiveness for cancel button
mgrabina Nov 12, 2025
069136b
nit text
mgrabina Nov 12, 2025
3c52856
change native tokens names
mgrabina Nov 12, 2025
62cb836
fix hf check re render
mgrabina Nov 12, 2025
8850c77
use optimal as price quality for quotes
mgrabina Nov 13, 2025
079c345
activate only base
mgrabina Nov 13, 2025
381a1ff
Merge branch 'main' into feat/cow-swap-adapters
mgrabina Nov 13, 2025
4f900b5
using latest cow version, contracts and limit orders only for cow
mgrabina Nov 13, 2025
1ec1f46
limit order pre warn only with cow
mgrabina Nov 13, 2025
c2fec96
nit
mgrabina Nov 13, 2025
92490bb
misc
mgrabina Nov 13, 2025
e6b7150
cancel only in classic swaps
mgrabina Nov 14, 2025
e55c49c
cancel adapter orders on chain via tx
mgrabina Nov 14, 2025
f0579c2
fix dust
mgrabina Nov 14, 2025
adde323
fix repay w coll and improved slippage
mgrabina Nov 14, 2025
453884e
using latest contracts and sdk
mgrabina Nov 17, 2025
61a433e
remove gho and eurc for base
mgrabina Nov 18, 2025
9656993
debt swap and repay through paraswap
mgrabina Nov 18, 2025
d21baf1
add quoteid to cow orders for analytics
mgrabina Nov 18, 2025
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: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ src/locales/
*.md
*.log
*.lock

src/components/transactions/Swap/backup/**/*.*
6 changes: 6 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Uncomment for CoW Preview Releases

# @cowprotocol:registry=https://npm.pkg.github.com
# always-auth=true
# # registry=https://registry.npmjs.org/
# //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
"@aave/math-utils": "1.36.1",
"@aave/react": "0.6.1",
"@amplitude/analytics-browser": "^2.13.0",
"@cowprotocol/sdk-app-data": "4.1.6",
"@cowprotocol/cow-sdk": "7.1.1",
"@cowprotocol/sdk-flash-loans": "1.5.2",
"@cowprotocol/sdk-viem-adapter": "0.2.0",
"@bgd-labs/aave-address-book": "^4.36.0",
"@cowprotocol/app-data": "^3.1.0",
"@cowprotocol/cow-sdk": "6.3.3",
"@emotion/cache": "11.10.3",
"@emotion/react": "11.10.4",
"@emotion/server": "latest",
Expand Down Expand Up @@ -157,4 +159,4 @@
"budgetPercentIncreaseRed": 20,
"showDetails": true
}
}
}
41 changes: 19 additions & 22 deletions pages/_app.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import { AddressBlocked } from 'src/components/AddressBlocked';
import { Meta } from 'src/components/Meta';
import { TransactionEventHandler } from 'src/components/TransactionEventHandler';
import { GasStationProvider } from 'src/components/transactions/GasStation/GasStationProvider';
import { CowOrderToast } from 'src/components/transactions/Switch/cowprotocol/CowOrderToast';
import { CowOrderToast } from 'src/components/transactions/Swap/modals/result/CowOrderToast';
import { AppDataProvider } from 'src/hooks/app-data-provider/useAppDataProvider';
import { CowOrderToastProvider } from 'src/hooks/useCowOrderToast';
import { ModalContextProvider } from 'src/hooks/useModal';
import { SwapOrdersTrackingProvider } from 'src/hooks/useSwapOrdersTracking';
import { Web3ContextProvider } from 'src/libs/web3-data-provider/Web3Provider';
import { useRootStore } from 'src/store/root';
import { SharedDependenciesProvider } from 'src/ui-config/SharedDependenciesProvider';
Expand All @@ -31,16 +31,22 @@ import createEmotionCache from '../src/createEmotionCache';
import { AppGlobalStyles } from '../src/layouts/AppGlobalStyles';
import { LanguageProvider } from '../src/libs/LanguageProvider';

const SwitchModal = dynamic(() =>
import('src/components/transactions/Switch/SwitchModal').then((module) => module.SwitchModal)
const SwapModal = dynamic(() =>
import('src/components/transactions/Swap/modals/SwapModal').then((module) => module.SwapModal)
);

const CollateralSwapModal = dynamic(() =>
import('src/components/transactions/Switch/CollateralSwap/CollateralSwapModal').then(
import('src/components/transactions/Swap/modals/CollateralSwapModal').then(
(module) => module.CollateralSwapModal
)
);

const DebtSwapModal = dynamic(() =>
import('src/components/transactions/Swap/modals/DebtSwapModal').then(
(module) => module.DebtSwapModal
)
);

const BridgeModal = dynamic(() =>
import('src/components/transactions/Bridge/BridgeModal').then((module) => module.BridgeModal)
);
Expand All @@ -53,16 +59,6 @@ const ClaimRewardsModal = dynamic(() =>
(module) => module.ClaimRewardsModal
)
);
const CollateralChangeModal = dynamic(() =>
import('src/components/transactions/CollateralChange/CollateralChangeModal').then(
(module) => module.CollateralChangeModal
)
);
const DebtSwitchModal = dynamic(() =>
import('src/components/transactions/DebtSwitch/DebtSwitchModal').then(
(module) => module.DebtSwitchModal
)
);
const EmodeModal = dynamic(() =>
import('src/components/transactions/Emode/EmodeModal').then((module) => module.EmodeModal)
);
Expand Down Expand Up @@ -160,7 +156,7 @@ export default function MyApp(props: MyAppProps) {
<Web3ContextProvider>
<AppGlobalStyles>
<AddressBlocked>
<CowOrderToastProvider>
<SwapOrdersTrackingProvider>
<ModalContextProvider>
<SharedDependenciesProvider>
<AppDataProvider>
Expand All @@ -170,24 +166,25 @@ export default function MyApp(props: MyAppProps) {
<WithdrawModal />
<BorrowModal />
<RepayModal />
<CollateralChangeModal />
<DebtSwitchModal />
<ClaimRewardsModal />
<EmodeModal />
<FaucetModal />
<TransactionEventHandler />
<SwitchModal />
<CollateralSwapModal />
<StakingMigrateModal />
<BridgeModal />
<ReadOnlyModal />
<CowOrderToast />

{/* Swap Modals */}
<SwapModal />
<CollateralSwapModal />
<DebtSwapModal />
<CancelCowOrderModal />
<CowOrderToast />
</GasStationProvider>
</AppDataProvider>
</SharedDependenciesProvider>
</ModalContextProvider>
</CowOrderToastProvider>
</SwapOrdersTrackingProvider>
</AddressBlocked>
</AppGlobalStyles>
</Web3ContextProvider>
Expand Down
8 changes: 7 additions & 1 deletion src/components/MarketSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,13 @@ type MarketLogoProps = {
export const MarketLogo = ({ size, logo, testChainName, sx }: MarketLogoProps) => {
return (
<Box sx={{ mr: 2, width: size, height: size, position: 'relative', ...sx }}>
<img src={logo} alt="" width="100%" height="100%" />
<img
src={logo}
alt=""
width="100%"
height="100%"
style={{ display: 'block', objectFit: 'contain', objectPosition: 'center center' }}
/>

{testChainName && (
<Tooltip title={testChainName} arrow>
Expand Down
19 changes: 16 additions & 3 deletions src/components/StyledToggleButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,31 @@ const CustomTxModalToggleButton = styled(ToggleButton)<ToggleButtonProps>(({ the
color: theme.palette.text.muted,
borderRadius: '4px',

// Selected (active) state
'&.Mui-selected, &.Mui-selected:hover': {
border: `1px solid ${theme.palette.other.standardInputLine}`,
backgroundColor: '#FFFFFF',
borderRadius: '4px !important',
},

'&.Mui-selected, &.Mui-disabled': {
color: theme.palette.background.header,
zIndex: 100,
height: '100%',
display: 'flex',
justifyContent: 'center',
},

// Disabled but NOT selected: keep readable text with slight fade
'&.Mui-disabled:not(.Mui-selected)': {
color: theme.palette.text.secondary,
opacity: 0.55,
},

// Disabled + selected: preserve the selected look
'&.Mui-disabled.Mui-selected': {
border: `1px solid ${theme.palette.other.standardInputLine}`,
backgroundColor: '#FFFFFF',
borderRadius: '4px !important',
color: theme.palette.background.header,
opacity: 1,
},
})) as typeof ToggleButton;

Expand Down
15 changes: 15 additions & 0 deletions src/components/infoTooltips/EstimatedCostsForLimitSwap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Trans } from '@lingui/macro';

import { TextWithTooltip } from '../TextWithTooltip';

export const EstimatedCostsForLimitSwapTooltip = () => {
return (
<TextWithTooltip variant="caption" text={<Trans>Estimated Costs & Fees</Trans>}>
<Trans>
These are the estimated costs associated with your limit swap, including costs and fees.
Consider these costs when setting your order amounts to help optimize execution and maximize
your chances of filling the order.
</Trans>
</TextWithTooltip>
);
};
11 changes: 11 additions & 0 deletions src/components/infoTooltips/ExecutionFeeTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Trans } from '@lingui/macro';

import { TextWithTooltip } from '../TextWithTooltip';

export const ExecutionFeeTooltip = () => {
return (
<TextWithTooltip variant="caption" text={<Trans>Execution fee</Trans>}>
<Trans>This is the fee for executing position changes, set by governance.</Trans>
</TextWithTooltip>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { OrderStatus, SupportedChainId } from '@cowprotocol/cow-sdk';
import { Trans } from '@lingui/macro';
import { useQueryClient } from '@tanstack/react-query';
import { Interface } from 'ethers/lib/utils';
import { useIsWrongNetwork } from 'src/hooks/useIsWrongNetwork';
import { useModalContext } from 'src/hooks/useModal';
import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
import {
ActionName,
CowSwapSubset,
isCowSwapSubset,
SwapActionFields,
TransactionHistoryItem,
} from 'src/modules/history/types';
import { useRootStore } from 'src/store/root';
import { getErrorTextFromError, TxAction } from 'src/ui-config/errorMapping';
import { updateCowOrderStatus } from 'src/utils/swapAdapterHistory';

import { ADAPTER_FACTORY } from '../Swap/constants/cow.constants';
import { TxActionsWrapper } from '../TxActionsWrapper';

interface CancelAdapterOrderActionsProps {
cowOrder: TransactionHistoryItem<
| SwapActionFields[ActionName.DebtSwap]
| SwapActionFields[ActionName.RepayWithCollateral]
| SwapActionFields[ActionName.CollateralSwap]
>;
blocked: boolean;
}

// ABI for cancelInstance function
const ADAPTER_ABI = ['function cancelInstance(address instance) external'];

export const CancelAdapterOrderActions = ({
cowOrder,
blocked,
}: CancelAdapterOrderActionsProps) => {
const { isWrongNetwork } = useIsWrongNetwork(cowOrder.chainId);
const { mainTxState, loadingTxns, setMainTxState, setTxError } = useModalContext();
const { sendTx } = useWeb3Context();
const queryClient = useQueryClient();
const account = useRootStore((state) => state.account);

const action = async () => {
try {
setMainTxState({ ...mainTxState, loading: true });

// Type guard to ensure we have a CowSwapSubset with adapter fields
if (!isCowSwapSubset(cowOrder)) {
throw new Error('Order is not a CoW swap order');
}

// At this point TypeScript knows cowOrder is CowSwapSubset, but we need to assert it has adapter fields
const cowSwapOrder = cowOrder as CowSwapSubset;

if (!cowSwapOrder.adapterInstanceAddress) {
throw new Error('Adapter instance address not found');
}

const adapterInterface = new Interface(ADAPTER_ABI);

const factoryAddress = ADAPTER_FACTORY[cowOrder.chainId as SupportedChainId];

if (!factoryAddress) {
throw new Error('Factory address not found for this chain');
}

const data = adapterInterface.encodeFunctionData('cancelInstance', [
cowSwapOrder.adapterInstanceAddress,
]);

const txResponse = await sendTx({
to: factoryAddress,
data,
chainId: cowOrder.chainId,
});

await txResponse.wait(1);

// Update order status to cancelled in local storage
if (account && cowSwapOrder.orderId) {
updateCowOrderStatus(
cowOrder.chainId,
account,
cowSwapOrder.orderId,
OrderStatus.CANCELLED
);
}

queryClient.invalidateQueries({ queryKey: 'transactionHistory' });
setMainTxState({
...mainTxState,
loading: false,
success: true,
txHash: txResponse.hash,
});
} catch (error) {
const parsedError = getErrorTextFromError(error, TxAction.MAIN_ACTION, false);
setTxError(parsedError);
setMainTxState({
txHash: undefined,
loading: false,
});
}
};

return (
<TxActionsWrapper
isWrongNetwork={isWrongNetwork}
handleAction={action}
actionText={<Trans>Cancel order</Trans>}
actionInProgressText={<Trans>Cancelling order...</Trans>}
blocked={blocked}
mainTxState={mainTxState}
requiresApproval={false}
preparingTransactions={loadingTxns}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,41 +1,58 @@
import { OrderBookApi, OrderSigningUtils } from '@cowprotocol/cow-sdk';
import { AdapterContext, OrderBookApi, OrderSigningUtils, OrderStatus } from '@cowprotocol/cow-sdk';
import { Trans } from '@lingui/macro';
import { useQueryClient } from '@tanstack/react-query';
import { useIsWrongNetwork } from 'src/hooks/useIsWrongNetwork';
import { useModalContext } from 'src/hooks/useModal';
import { getEthersProvider } from 'src/libs/web3-data-provider/adapters/EthersAdapter';
import { ActionFields, TransactionHistoryItem } from 'src/modules/history/types';
import { ActionName, SwapActionFields, TransactionHistoryItem } from 'src/modules/history/types';
import { useRootStore } from 'src/store/root';
import { getErrorTextFromError, TxAction } from 'src/ui-config/errorMapping';
import { wagmiConfig } from 'src/ui-config/wagmiConfig';
import { updateCowOrderStatus } from 'src/utils/swapAdapterHistory';
import { getWalletClient } from 'wagmi/actions';

import { COW_ENV, getCowAdapter } from '../Swap/helpers/cow';
import { TxActionsWrapper } from '../TxActionsWrapper';

// TODO: check with cow if we can cancel adapters orders
interface CancelCowOrderActionsProps {
cowOrder: TransactionHistoryItem<ActionFields['CowSwap']>;
cowOrder: TransactionHistoryItem<SwapActionFields[ActionName.Swap]>;
blocked: boolean;
}

export const CancelCowOrderActions = ({ cowOrder, blocked }: CancelCowOrderActionsProps) => {
const { isWrongNetwork } = useIsWrongNetwork(cowOrder.chainId);
const { mainTxState, loadingTxns, setMainTxState, setTxError } = useModalContext();
const queryClient = useQueryClient();
const account = useRootStore((state) => state.account);

const action = async () => {
try {
setMainTxState({ ...mainTxState, loading: true });
const provider = getEthersProvider(wagmiConfig, { chainId: cowOrder.chainId });
const signer = (await provider).getSigner();
const orderBookApi = new OrderBookApi({ chainId: cowOrder.chainId });

const adapter = await getCowAdapter(cowOrder.chainId);
AdapterContext.getInstance().setAdapter(adapter);
const orderBookApi = new OrderBookApi({ chainId: cowOrder.chainId, env: COW_ENV });
const walletClient = await getWalletClient(wagmiConfig, { chainId: cowOrder.chainId });

if (!walletClient || !walletClient.account) {
throw new Error('Wallet not connected for signing');
}
const { signature, signingScheme } = await OrderSigningUtils.signOrderCancellation(
cowOrder.id,
cowOrder.chainId,
signer
walletClient
);
await orderBookApi.sendSignedOrderCancellations({
orderUids: [cowOrder.id],
signature,
signingScheme,
});

// Update order status to cancelled in local storage
if (account && cowOrder.id) {
updateCowOrderStatus(cowOrder.chainId, account, cowOrder.id, OrderStatus.CANCELLED);
}

queryClient.invalidateQueries({ queryKey: 'transactionHistory' });
setTimeout(() => {
setMainTxState({
Expand Down
Loading
Loading